jsf validation for datatable - jsf-2

I want to validate the below datatable only if user doesn't enter any values in the given p:inputText field
<p:dataTable id="depositDataTable" value="#{pc_intimationDeposit.pendingRep.depositeBeans}" var="deposit">
<p:column style="text-align:right">
<h:outputText value="#{deposit.depParticulars}" />
</p:column>
<p:column id="value">
<h:inputText id="depositDetails" class="right_input" value="#{deposit.amnt}" tabindex="2" converterMessage="Please Enter Numbner's Only" validatorMessage="please">
<f:convertNumber pattern="##,####,##0.00" for="depositDetails" type="currency" />
</h:inputText>
<p:message id="errMsgDepositDetails" for="depositDetails" display="text"></p:message>
</p:column>
</p:dataTable>
pc_intimationDeposit.pendingRep.depositeBeans----> is a list(size 3) of depositBeans
i have used f:convertNumber for the entered values are correct to our requirements
but if user doesn't enter A SINGLE VALUE then i need validate for null check
i.e., user has to enter any one field
and i need to display the error message on top of the datatable used
please help me
Thank in you advance

If you want to have every depositDetail inputs populated, mark
them with required=true.
If you only want to have one of them filled, on your action method,
iterate over your model to ensure there's at least one not empty (you shouldn't have null values here):
boolean filled = false;
for (DepositeBean dep : depositeBeans){
if (!dep.getAmnt.equals("")){
filled = true;
}
}
if (!filled){
FacesContext.getCurrentInstance().addMessage(null,
new FacesMessage(FacesMessage.SEVERITY_ERROR, "You have to fill at least one deposit detail field", null));
}
For messages to be displayed, add an h:message tag and point it to your table:
<h:message for="depositDataTable" style="color:red" />

Related

Prime Faces InputText inside an ordered list

I have a requirement in primefaces to have an inputText inside an orderlist and on changing the inputText want to reflect it in the object model. But i suppose there is a bug or some kind of problem as whenever I submit the form there is a null pointer error. It says that the object is unreachable. The weird part is that it does show the correct data (ie. gets the data) but is unable to set it.
<p:orderList value="#{artifactController.uploadedFiles}"
var="uploadedFile" itemValue="#{uploadedFile}"
controlsLocation="left" id="artifactList"
converter="customUploadedFileConverter"
selection="#{artifactController.selectedUploadedFile}"
selectionMode="single">
<p:column style="width:25%">
<p:graphicImage
value="/faces/pages/image#{uploadedFile.imagePath}?mimeType=#{uploadedFile.mimeType}"
width="100" height="50">
</p:graphicImage>
</p:column>
<p:column style="width:75%;">
<p:inputText value = #{uploadedFile.fileName} ></p:inputText>
</p:column>
</p:orderList>
The Controller has all the setters and getters in place.
The input text shows the data while retrieving but fails to update the value in the controller. Isn't it supposed to work like that (similar to dataTable). It gives uploadedFile is unreachable error.

Primefaces enum output facet updates wrong

I'm facing some problems using a primefaces cell editing table. So, I have a datatable, which contains an editable column. This datatable is populated through a list of jpa entity.
Focusing on wich matters, my editable cell, has an outputText in the output facet and a selectOneMenu in the input facet, which is populated by an enum.
My problem is that, datatable is correctly loaded at beginning, I can successfully edit the wanted field, selectOneMenu is correctly populated with enum. If I choose an option in the selectOneMenu, it gets fine, HOWEVER when I click outside the datatable (to quit editing mode), it gets a wrong value, since it gets the code, and it should get description.
My code:
Enum:
public enum EnumSimNao implements DetalheDominioEnum {
/**
* Sim
*/
S("Sim"),
/**
* Não
*/
N("Não");
Enum has a getter that refreshes the value based in some services. It always get those values from the service. I've tested it and the values are right here. When I say description, I mean "Sim" or "Nao", and the codes are respectively "S" or "N". From the database it comes a code, that is associated with enum through an #Enumerated attribute in an jpa entity. When I have #{tp.respostaObrigatoria.description} it returns me "Sim" or "Não" based on the returned code.
public String getDescription() {
DetalheEstaticoDominioEnumHelper.INSTANCE.fillDescriptions(this);
return description == null ? defaultDescription : description;
}
#Override
public void setDescription(String description) {
this.description = description;
}
xhtml:
<p:cellEditor>
<f:facet name="output">
<h:outputText
value="#{tp.respostaObrigatoria.description}" />
</f:facet>
<f:facet name="input">
<h:selectOneMenu value="#{tp.respostaObrigatoria}">
<f:selectItems value="#{Factories.enumSimNao}" var="simNao"
itemLabel="#{simNao.description}" itemValue="#{simNao}" />
</h:selectOneMenu>
</f:facet>
</p:cellEditor>
tp is an entity whcih comes from a list that comes from backing bean:
So, when I edit the cell, I can see both descriptions ("Sim" or "Nao"), but when I exit the edit mode it shows "S" or "N". Finally, if I refresh the page, it gets the correct description value I had choose.
Do you have any tip?
Thanks
Primefaces 3.5 has this bug which apparently was filed under this issue http://code.google.com/p/primefaces/issues/detail?id=6116 and solved in version 3.5.15 which is only available on Elite version. Version 4.0 seems to have this fixed.
I found a workaround for 3.5 which involves re-rendering the form enclosing the datatable which is working fine for me.
What you need to do is to use an ajax event listener inside the selectOneMenu component which triggers the render of the form like this:
<p:cellEditor>
<f:facet name="output">
<h:outputText
value="#{tp.respostaObrigatoria.description}" />
</f:facet>
<f:facet name="input">
<h:selectOneMenu value="#{tp.respostaObrigatoria}">
<f:selectItems value="#{Factories.enumSimNao}" var="simNao"
itemLabel="#{simNao.description}" itemValue="#{simNao}" />
<f:ajax listener="#{bean.submit}" render="#form" />
</h:selectOneMenu>
</f:facet>
</p:cellEditor>

ignoreValidationFailed doesn´t work inside p:dataTable

I am using actionListener ajax call inside datatable and trying to do the following :
skip validation
update the model with the inserted values
I knew that omnifaces utility liberary by BalusC can do this using o:ignoreValidationFailed
But it failed with me to work inside primefaces datatable.
Also I found that it failed to work inside ui:repeat in another post here
I dont know if its a bug or not.
here is my code example
<o:form id ="trans_desc_form">
<p:outputPanel id="stkdetailsid">
<p:dataTable id="transactiondetailsid" value="#{stockTransactionsBean.stkTransHeader.stkTransDetailsList}"
var="stkTransDet" rowIndexVar="rowIndex">
<p:column>
<f:facet name="header">
<h:outputText value="Item Code" />
</f:facet>
<p:autoComplete id="dd" required="true"
value="#{stkTransDet.item}" var="i" itemLabel="#{i.itemno} #{i.itemnamee}"
itemValue="#{i}" converter="itemsConverter"
completeMethod="#{stockTransactionsBean.completeItems}"/>
</p:column>
<p:column>
<p:commandButton value="-" update="#form" process="#form"
actionListener="#{stockTransactionsBean.removeRow(rowIndex)}">
<o:ignoreValidationFailed />
</p:commandButton>
</p:column>
</p:dataTable>
</p:outputPanel>
</o:form>
As a workaround, I added
1- add a condition to the required field to know if the ajax come from submit button or not
to the autoComplete component where the trans_desc_form is thte entire form id and savetransid is the submit button save id
required="#{!empty param['trans_desc_form:savetransid']}"/>
2- I removed #NotNull from my JPA entity which force the validation
#JoinColumn(name = "ITEMNO", referencedColumnName = "ITEMNO")
#ManyToOne(optional = false, fetch = FetchType.LAZY)
//#NotNull
private Item item;
To skip validation you can use the immediate="true" attribute on your p:commandButton

Autocomplete not working in some condtion

I am using primefaces autocomplete component with itemtip option,
after getting suggestions I am selectiing one value as a example lastname,
but I want to display in textbox both lastname and firstname of player, so tried in this way.
itemLabel="#{p.lastName} #{p.firstName} " having some space with these two .
<p:autoComplete id="watermark" value="#{backingBean.object}"
size="40" completeMethod="#{backingBean.completeholder}"
var="p"
itemLabel="#{p.lastName} #{p.firstName} " itemValue="#{p}" converter="player">
<f:facet name="itemtip">
<h:panelGrid columns="2" styleClass="cellsp-panel">
<f:facet name="header">
<p:graphicImage value="#{p.imagePath}" width="60"
height="60" />
</f:facet>
<h:outputText value="LastName " style="font-weight:bold" />
<h:outputText id="ln" value="#{p.lastName}" />
<h:outputText value="FirstName " style="font-weight:bold" />
<h:outputText id="fn" value="#{p.firstName}" />
</h:panelGrid>
</f:facet>
<p:ajax event="itemSelect" update="e,c">
</p:ajax>
</p:autoComplete>
so after selecting a suggestion, it displays lastname and firstname of player perfectly.
But one problem is created as - it creates a space in autocomplete textbox, so i need to use
backspace to remove this space so that I can search a for getting suggestions.
How can I overcome from this problem?
Also I am using watermark on autocomplete , it works only when I use single itemLabel like
itemLabel="#{p.lastName} otherwise it unable to display watermark in autocomplete.
3.Also when I use for no-case sensitive input so that user can search without case sensitive,
once I get any suggestions and still if try to type some keyworks for further filterations,
suggestions disappears,it works if I go for case sensitive by default way.
User can type players lastname or firstname , and still he needs to gets suggestion ,what modifications should I need to done in following method ?
I have stored lastname with First letter as a Capital, so I am using toUpperCase() in this way
public List completePlayer(String query) {
List suggestions = new ArrayList();
for(Player p : players) {
if(p.getlastName().startsWith(query.toUpperCase()))
suggestions.add(p);
}
return suggestions;
}
How can I overcome from this problem?
Your player compare is resolving to this:
Smith.startsWith("S") -> true
Smith.startsWith("SM") -> false
What you want is:
if(p.getlastName().toUpperCase().startsWith(query.toUpperCase()))
The space in your autocomplete is coming from this line:
itemLabel="#{p.lastName} #{p.firstName} " itemValue="#{p}" converter="player">
You have a space after #{p.firstName} in itemLabel before your closing quote.
As for the watermark, I don't know. I have never tried it with an autocomplete. Can you include your p:watermark tag so we can see what it is referencing?

Getting the filtered list in datatable

I am trying to filter a datatable using filter field in the column and get the filtered list (which populates datatable) and update another component (Toplam TL Teminati and Toplam Dolar Teminati) according to the filtered list's values in my page.
Is there anyway to do this in Primefaces 2.2.1 and JSF 2? If not can you rec commend a workaround for this case?
Thanks in advance.
To give you an example of how I achieved custom filter logic in my Primefaces 2.2.1 dataTable, I am giving you a scaled version of my code.
<p:dataTable value="#{listBeans.beans}" var="bean" dynamic="true" paginator="true" rows="20" paginatorPosition="bottom"
emptyMessage="No Beans" loadingMessage="Loading. . ." selectionMode="single" selection="#{listBeans.selectedBean}"
id="beanList" widgetVar="beanTable">
<f:facet name="header">
<h:panelGrid columns="4">
<h:outputText value="Bean List" />
<p:outputPanel>
<h:outputText value="Year Filter: " />
<h:selectOneMenu value="#{listBeans.yearFilter}"
onchange="yearFilterBtn.jq.click(); refreshFilters();">
<f:selectItems value="#{listBeans.years}" />
</h:selectOneMenu>
<p:commandButton id="yearFilterBtn" widgetVar="yearFilterBtn" action="#{listBeans.filterYears}"
update="listBeansForm:beanList" style="display:none;" />
</p:outputPanel>
<p:outputPanel>
<h:outputText value="Filter By Beanchild: " />
<p:inputText value="#{listBeans.beanchildFilter}" style="width: 150px; margin-right: 4px;" />
<!-- refreshFilters forces the visitor filter to refresh the selection if column filters are selected. -->
<p:commandButton oncomplete="refreshFilters();" value="Filter"
action="#{listBeans.filterBeanchildren}" update="listBeansForm:beanList" />
</p:outputPanel>
<p:commandButton value="Export to XLS" ajax="false">
<p:dataExporter target="beanList" type="xls" fileName="BeanReport"
excludeColumns="0,5,6" postProcessor="#{listBeans.postProcessExcelReport}" />
</p:commandButton>
</h:panelGrid>
</f:facet>
<p:column style="width:16px">
<p:rowToggler />
</p:column>
<p:column filterStyleClass="filtertag" filterBy="#{bean.beanDateDisplay}" filterMatchMode="startsWith">
....
</p:dataTable>
Without really going into too much detail about the managed bean code, the actions of the command button are essentially passing filter arguments to my BO layer that requery the database for the new list of beans. The explicit update of the dataTable component is needed to refresh the data.
You will notice that on the explicit Beanchild Filter button that is not hidden, I have an oncomplete attribute that references a javascript function called refreshFilters(). I can't remember exactly the problem I had, but I think it is a bug in the 2.2.1 version of Primefaces when a column filter value exists and an asynchronous update occurs within the dataTable itself. Here is the javascript function:
function refreshFilters() {
var filters = jQuery('.filtertag');
var uppedOnce = false;
filters.each(function(idx) {
var curEl = jQuery(this);
if (curEl.val() != '') {
curEl.keyup();
uppedOnce = true;
}
});
if (!uppedOnce) {
jQuery(filters[0]).keyup();
}
}
You can see here that I am locating every DOM element that has the class filtertag, which would be the column filters. I am saying that if a value exists in that field after the server action is complete, then I am manually triggering a keyup event as this will "refilter" the column with the previous value from before.
I am not sure if it is necessary in later versions of Primefaces, I am not even sure it is necessary now, so I suggest trying to do this without the Javascript workaround and if you run into problems cooridnating the two then you can consider using the Javascript.

Resources