I have a question about selectOneMenu and settting the values. I have an Object SampleDesc that has and ID, Text, and a List<SampleDescValues>. For each datatable row the Text is the output label and the select one menu values are the List<SampleDescValues>.
XHTML:
<h:panelGroup id="tables">
<p:dataTable resizableColumns="true"
var="sampleDesc" id="SampleDescTable" rowIndexVar="rowIndex"
value="#{sampleBean.sampleDescList.list}"
rendered="#{sampleBean.sampleDescList.list.size() gt 0}">
<p:column>
<h:outputLabel value="#{sampleDesc.sampleDescText}"/>
</p:column>
<p:column>
<h:selectOneMenu required="#{sampleBean.sampleDescList.list.size() gt 0}" converter="#{sampleDescValueConverter}"
id="SampleDescValue" value="#{sampleBean.selectedSampleDescList.get(rowIndex)}">
<f:selectItem itemLabel="Select One" itemValue="#{null}"/>
<f:selectItems value="#{sampleDesc.sampleDescValues}" var="sdv"
itemLabel="#{sdv.sampleDescValuesText}" itemValue="#{sdv}" />
</h:selectOneMenu>
</p:column>
</p:dataTable>
</h:panelGroup>
I have the converter setup and it works because ive set it to a single SampleDescValue and it set the value.
The problem is when i try and populate the form with a Sample from the database it can only set one of the dropdowns when there could be an infinite number of selectonemenu's
I set the value selected to private List<SampleDescValue> selectedSampleDescList;
When i try and submit it does nothing, it works when the datatable is not rendered.
Your menu value is wrong:
<h:selectOneMenu value="#{sampleBean.selectedSampleDescList.get(rowIndex)}">
It's not possible to perform a set operation on this EL expression.
Use the brace notation instead:
<h:selectOneMenu value="#{sampleBean.selectedSampleDescList[rowIndex]}">
Note that this expects a non-null selectedSampleDescList. So make sure that you've already properly initialized it with a new ArrayList<>() beforehand. EL won't do that for you. It will only set the list items using List#add(index, object) method.
See also:
Our EL wiki page
Unrelated to the concrete problem, this expression
#{sampleBean.sampleDescList.list.size() gt 0}
can be simplified as follows
#{not empty sampleBean.sampleDescList.list}
And this is unnecessary in the required attribute of the <h:selectOneMenu> as it would always evaluate true at that point. Just use required="true" directly instead.
Related
I am trying to filter my primefaces datatable by a boolean column using a checkbox filter but unfortunately filtering in primefaces datatable seems it does not work with any type other than String, but there should be a workaround for this case.
datatable column
<p:column headerText="A_boolean_column" filterBy="#{myBean.myBoolean}" filterMatchMode="exact">
<f:facet name="filter">
<p:selectCheckboxMenu label="BooleanFilter" onchange="PF('mydatatable').filter()" styleClass="custom-filter">
<f:selectItems value="#{myBean.possibleAnswers}" />
<p:ajax update="#form" oncomplete="PF('mydatatable').filter();"/>
</p:selectCheckboxMenu>
</f:facet>
<h:outputText value="#{myBean.myBoolean}"/>
</p:column>
where possibleAnswers variable is a list that has been initialized on init method of myBean with true && false values
#PostConstruct
public void init(){
this.possibleAnswers= new ArrayList<>();
possibleAnswers.add(true);
possibleAnswers.add(false);
}
I have similar working examples in my datatable with text values and are working perfectly. Of course I could do a workaround to fix my issue by converting the values from boolean ( true / false) into String ("true" / "false") ( or even write a custom function to check for equality)but I don't really like this solution and I would prefer any other out of the box solution ( perhaps a different filterMatchMode ? ).
I am using primefaces 7.0
Normally an input component has a 'value' attribute that is bound to a field (getter/setter) in a backing bean. The type of this field can be used to automatically convert the technical string of the http request to the correct java type. For a datatable filter this cannot be automatically done since there is no value attribute. Giving all components knowledge about all possible containers they can be used in is bad design. So the only and corrrect solution is to use an explicit converter.
Have a Look at the Implementation of the Status-Column in the PrimeFaces datatable filter showcase, as far as I see it it is exactly what you need
for Reference:
<p:column filterBy="#{myBean.myBoolean}" filterMatchMode="in">
<f:facet name="filter">
<p:selectCheckboxMenu label="BooleanFilter"
onchange="PF('mydatatable').filter()" styleClass="custom-filter">
<f:converter converterId="javax.faces.Boolean" />
<f:selectItems value="#{myBean.possibleAnswers}" />
<p:ajax update="#form" oncomplete="PF('mydatatable').filter();"/>
</p:selectCheckboxMenu>
</f:facet>
</p:column>
I've got a dynamic dataTable and would like to display different filter types depending on the column but it seems that I can only use one object within a filter facet at a time. If I try to use multiple input types I get a
java.lang.ClassCastException: javax.faces.component.UIPanel cannot be cast to javax.faces.component.ValueHolder
My current (not working) code looks like this:
<f:facet name="filter">
<p:inputText onkeyup="PF('myTable').filter()" rendered="#{column.filterType=='TEXT'}" />
<p:selectOneMenu onchange="PF('myTable').filter()" rendered="#{column.filterType=='LIST'}">
<f:selectItems value="#{column.filterMap}" />
</p:selectOneMenu>
</f:facet>
The inputText and selectOneMenus are displayed correctly, but I can't filter my table because of the ClassCast Exception.
If I only use one of the input types, the filtering works as expected.
Is it possible to conditionally show different filter facets or input types within the facet?
The only "solution" I found, is to always use selectOneMenus and make them editable and look like inputTexts if the filter type is "TEXT"
<p:selectOneMenu onchange="PF('myTable').filter()" editable="#{column.filterType=='TEXT'}" styleClass="#{column.filterType}">
following your 2nd comment I tested this code and it works; The idea is that the filter depends on the column, so:
<p:column filterBy="#{column.attribute}" filterMatchMode="contains" rendered="#{column.filterType=='TEXT'}" >
<f:facet name="filter">
<p:inputText onkeyup="PF('myTable').filter()" />
</f:facet>
</p:column>
<p:column filterBy="#{column.attribute}" filterMatchMode="equals" rendered="#{column.filterType=='LIST'}">
<f:facet name="filter">
<p:selectOneMenu onchange="PF('myTable').filter()" >
<f:selectItems value="#{column.filterMap}" />
</p:selectOneMenu>
</f:facet>
</p:column>
you show and hide the column, not the filter.
NB : The filter mode of an inputText is contains AND for a List is Equals.
I am using PrimeFaces 5.1, In my project dataTable to filter used.In text filter is work fine but dropdown filter is not working properly (i.e) In dropdown I show department,First time I choose any value from dropdown is work fine anothertime I choose dropdown It not return any value show in dataTable.I choose select one first value from dropdown also throw null pointer exception.
<p:dataTable id="datalist" widgetVar="datalist" var="user" value=#{beanList.userList}>
<p:column headerText="Department" filterBy="#{user.deptname}"
filterMatchMode="exact" >
<f:facet name="filter">
<p:selectOneMenu onchange="PF('datalist').filter()">
<f:selectItem itemLabel="ALL" itemValue="#{null}"
noSelectionOption="true" />
<f:selectItems value="#{datalist.deptList}" />
</p:selectOneMenu>
</f:facet>
<h:outputText value="#{user.depatname}" />
</p:column>
</p:dataTable>
My doubt is default value ALL click and second time select any value return null or no data show in dataTable.
Since I don't know the scope of your Managed Bean: Try a scope longer than request (see PrimeFaces 5.1 User Documentation), and provide a value "filteredValue" for your table, like this:
<p:dataTable id="datalist" widgetVar="datalist" var="user"
value="#{beanList.userList}" filteredValue="#{beanList.filteredUserList}">
With that, you make sure to keep your filtered table/list in a field in your managed bean and the contents won't get lost.
Also, make sure your Managed Bean class is serializable (See this stackoverflow post)
I'm currently working on a dynamic datatable. Let's say this table has 4 columns (name, x, y, z). x, y must be number text field and z is a label which shows the sum of x and y. When the values on either x or y is changed the value on z must be recomputed.
My problem right now is I'm not able to bind the text fields to the datatable entity, if I use the edit from primefaces, I need to add an edit event which I don't like. Also it display the cell initially as label, then need to click it to show the textfield.
Any suggestions? Thanks.
Here's my solution, instead of using primefaces datatable.edit feature. I just use a textfield in the cell and added a p:ajax that triggers a recompute method on change. Note the use of update parameter, we can directly reference a field on the row.
<h:form id="creditNoteLinesForm">
<p:dataTable id="resultsId_creditNoteLines" var="entity"
value="#{creditNoteBean.entity.creditNoteLines}">
<!-- // -->
<p:column
headerText="#{messages['creditNote.list.amountWithoutTax']}">
<p:inputText value="#{entity.amountWithoutTax}">
<p:ajax event="change"
listener="#{creditNoteBean.reCompute(entity)}"
update="amountWithTax"></p:ajax>
</p:inputText>
</p:column>
<p:column headerText="#{messages['creditNote.list.amountTax']}">
<p:inputText value="#{entity.taxAmount}">
<p:ajax event="change"
listener="#{creditNoteBean.reCompute(entity)}"
update="amountWithTax"></p:ajax>
</p:inputText>
</p:column>
<p:column
headerText="#{messages['creditNote.list.amountWithTax']}">
<h:outputText id="amountWithTax" value="#{entity.amountWithTax}" />
</p:column>
</p:dataTable>
</h:form>
sdfdsf
public void reCompute(CreditNoteLine line) {
line.computeWithTax();
}
I am working on a form which has two datatables. In the first datatable, I am displaying the radio buttons and checkboxes, whereas the second datatable contains
selectOneMenu(s). Value change listener has been implemented on the selectOneMenu and on value change, the subsequent fields gets populated based on the selection.
Everything works fine except that when I select the value from the dropdown, the checkbox and the radio button values are cleared.
f:ajax event="change" has been used for the change event on selectOneMenu. Looks like the whole page gets refreshed and the values are cleared.
I also tried using f:ajax by updating the id of the datatable in which the selectOneMenu is present.
<p:dataTable styleClass="borderless" id="inResultTable" var="result" value="#{RequestBean.fooFields}" rendered="#{not empty RequestBean.fooFields}">
<p:column style="width:150px;">
<f:facet name="header">
<h:outputText value=" " />
</f:facet>
<h:outputText value="#{msg[result.fldLabel]}" />
</p:column>
<p:column>
<f:facet name="header">
<h:outputText value="" />
</f:facet>
<ui:repeat value="#{RequestBean.fooFields}"
var="itm">
<h:selectOneMenu value="#{itm.indFieldValue}"
rendered="#{result.lvlid==itm.lvlid}"
style="width:250px;padding-right:150px;text-align: left;">
<f:selectItems value="#{RequestBean[itm.indField]}" />
</h:selectOneMenu>
<h:selectOneRadio value="#{itm.indFieldValue}" rendered="#{result.lvlid==itm.lvlid and result.fldType=='radio'}"
style="width:250px;padding-right:150px;text-align: left;">
<f:selectItems value="#{RequestBean[itm.indField]}" />
</h:selectOneRadio>
<h:selectManyCheckbox value="#{itm.indFieldCheckBox}" rendered="#{result.lvlid==itm.lvlid and result.fldType=='selectbox'}">
<f:selectItems value="#{RequestBean[itm.indField]}" />
</h:selectManyCheckbox>
</ui:repeat>
</p:column>
</p:dataTable>
<p:dataTable styleClass="borderless"
id="resultTable" var="result"
value="#{RequestBean.depFields}">
<h:selectOneMenu value="#{RequestBean.field4Value}"
valueChangeListener="#{RequestBean.processValueChange4}"
rendered="#{result.lvlid=='5' and result.fldType=='selectbox'}"
style="width:250px;padding-right:150px;text-align: left;">
<f:selectItem itemLabel="--Please Select--" itemValue="#{null}" />
<f:selectItems value="#{RequestBean[result.field]}" />
<f:ajax event="change" render="#form" />
</h:selectOneMenu>
...
...
</p:dataTable>
N.B: The requirement is such that the datatable with checkbox and radio buttons has to be placed at the top. IDs cannot be used for the selectOneMenu in the second table since I am
populating the selecOneMenu(s) dynamically based upon the entries in the database.
I know that this might be a simple issue but didn't have any luck with the info posted on most websites.
Any help would be appreciated.
Here's your <f:ajax>.
<f:ajax event="change" render="#form" />
You didn't specify the process attribute. So it defaults to #this, which means that only the current input component is processed during submit. However, you specified a render of the whole form. So the whole form will be refreshed. However, the other input components aren't been processed during submit. So their model values won't be updated, which means that during render response the initial values will be redisplayed instead of the submitted values, which are in your case apparently blank/null.
You've basically 2 options:
Process the whole form during submit.
<f:ajax process="#form" render="#form" />
Or, update only those components which really needs to be updated.
<f:ajax render="clientId1 clientId2 clientId3" />
In your particular case I think option 2 isn't viable, so option 1 is the best one. Please note that I omitted the event attribute. It defaults to change already.
Unrelated to the concrete problem, I'm not sure what you're all doing in your value change listener method, but I only want to note that most starters abuse it for the purpose of manipulating the model values and that it don't always work quite as expected (changed model values are not reflected at all). If this is true in your case, then you should actually be using <f:ajax listener> instead.
See also:
When to use valueChangeListener or f:ajax listener?
The main reason for the values of Check boxes & Radio buttons getting cleared after a value change listener could be that the model values are not updated.
Value change listeners are called before updating the model.
For these kind of issues, it is very important to have an understanding of the JSF lifecycle.
Please try following code in your value change listener and see.
public void valueChange(ValueChangeEvent event){
PhaseId phase = event.getPhaseId();
if (phase.equals(PhaseId.ANY_PHASE))
{
event.setPhaseId(PhaseId.UPDATE_MODEL_VALUES);
event.queue();
return;
}
if(!phase.equals(PhaseId.UPDATE_MODEL_VALUES))
{
return;
}
// Your code
}
I didn't try this code with your example. Please let me know with complete example source code if it is not working.
Thanks.