Wrong setter is called when row is selected - jsf

I got the following problem using Primefaces 5.2 and JSF 2.1
I got a p:dataTable, and when the user selects a row, the selected object's data should be shown below the table. One requirement is that there should be a checkbox below the table, which should be editable. If the user toggles the checkbox and selects a different entry in the table, the checkbox' new value should be saved. (see the code below)
But I observed the following behaviour. When I select object1, check its checkbox and then select object2, object2's setter will be called, not object1's. Thus object2.someValue will be changed, while object1.someValue won't be. any idea?
<p:dataTable var="myVar" selectionMode="single"
id="myTable" selection="#{form.myValue}"
rowKey="#{myVar.id}"
value="#{form.myTableData}">
<!-- columns here -->
<p:ajax event="rowSelect" process="my_booleancheckbox" update="wrapper">
<p:dataTable>
<h:panelGroup id="wrapper">
<p:booleanCheckbox value="#{form.myValue.someValue}" id="my_booleancheckbox"/>
<!--other stuff here -->
</h:panelGroup>

That's how it is supposed to work, the rowSelect event is fired after the property selection of your p:dataTable is updated
move your ajax action to the p:booleanCheckbox
<p:dataTable var="myVar" selectionMode="single"
id="myTable" selection="#{form.myValue}"
rowKey="#{myVar.id}"
value="#{form.myTableData}">
<!-- columns here -->
<p:dataTable>
<h:panelGroup id="wrapper">
<p:booleanCheckbox value="#{form.myValue.someValue}" id="my_booleancheckbox">
<p:ajax process="my_booleancheckbox" update="wrapper">
</p:booleanCheckbox>
<!--other stuff here -->
</h:panelGroup>

Related

JSF - rich:tabPanel - A backing bean property is called for each tab and not for the active one only

I have 15 tabs containing a similar table, so I have only one backing bean collection of items defining my table. When the tab changes, the collection changes accordingly. So, when the tab is rendered, I am expecting the get method of my collection to be called only once, for my active tab because on screen and in the DOM this tab is the only one with a table. BUT, the get method of my collection is called 15 times, which I guess is because I have 15 tabs.
How do you explain that ? Here is my code.
<rich:tabPanel activeItem="#{myBean.selectedTab}" itemChangeListener="#{myBean.changeItems}" >
<c:forEach items="#{myBean.tabs}" var="t">
<rich:tab id="tab_#{t.code}" header="#{t.libelle}" name="#{t.code}" >
<!-- ############ HEADER ############ -->
<rich:dataTable id="tableHeader_#{t.code}">
<f:facet name="header">
<rich:columnGroup>
<!-- Some columns. Let's say that I have a button like a sort
with a render attribute set to "tab_#{t.code}"
Then all will be correctly rendered but
the get of my collection would have been called 15 times -->
</rich:columnGroup>
</f:facet>
</rich:dataTable>
<!-- ############ DATA ############ -->
<rich:dataTable id="tableData_#{t.code}" value="#{myBean.collectionOfItems}" var="i">
<!-- Some columns -->
</rich:dataTable>
</rich:tab>
</c:forEach>
</rich:tabPanel>
Thank you in advance !
The generation called 15 because the tab captions should be generated (header facets). But if you want to do something #{myBean.selectedTab} specific check this out (or something like that ):
<c:forEach items="#{myBean.tabs}" var="t">
<c:if test="#{t.equals( myBean.selectedTab )}" >
...
</c:if>

get selected row in ace:datatable Icefaces

I am using an in rowselection mode and trying just to get the selected row of the datatable.
I have tried it using the stateMap of IceFaces, but it does not work. The ajax event opens a dialog after selection, where I want to show data of the selected row.
<ace:dataTable id="datatable"
value="#{myBean.myValues()}"
var="myValue" paginator="true" paginatorPosition="bottom"
selectionMode="single" rows="15" rowKey="#{myValue.id}"
doubleClickSelect="true">
<ace:ajax event="select" render="#this" execute="#this"
onStart="ice.ace.instance('#{myDialog.clientId}').show();" />
...
You can add rowSelectListener to the tag <ace:dataTable>
<ace:dataTable rowSelectListener="#{manageBean.rowSelectListener1}" >
And add a function in the code behind to get the row selected.
public void rowSelectListener1(SelectEvent event){
DataType selectedItem = (DataType )event.getObject();
}

create DataTable with Two dimensional with InputText into cells

I need create an primefaces Datatable with InputText into cells and get de information edited in the inputText
I create the datatable with the next code:
<p:dataTable value="#{busquedaArticulo.attr}" var="rowName" styleClass="table table-bordered table-stripped" rowIndexVar="rowIdx">
<p:column headerText="" styleClass="ui-widget-header">
<h:outputText value="#{rowName}"/>
</p:column>
<p:columns value="#{busquedaArticulo.siz}" var="columnName" headerText="#{columnName}" columnIndexVar="colIdx">
<h:inputText id="siz" value="#" styleClass="form-control" />
</p:columns>
</p:dataTable>
I suggest you to use editable row. you can show value of each entry if it has been set by user or has a default value or leave it empty or "not set" if it's not set.
user can click on pencil icon and edit value of each row. once row has been edited you can get new value in your backing bean.
look at this: http://www.primefaces.org/showcase/ui/data/datatable/edit.xhtml
hope it was useful :)

Check box and Radio Button selection gets cleared on h:selectOneMenu value change

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.

Value of <h:selectBooleanCheckbox> inside <p:dataTable> remains false on submit

I have a primefaces datatable and inside the primefaces datatable, I have a column, which contains the . The issue is,I have set the default value for the as false. When I click/check the , its still retrieving the value as false. I tried it multiple times but not sure why its returning false. Please find the sample code below.
<p:dataTable id="review-table" var="item" value="#{demandBean.filterVOList}">
<p:column id="SelectallID" style="text-align: left; width:40px;" rendered="#{demandBean.screeRenderVo.selectAllRenderer}">
<f:facet name="header" >
<h:outputText id="selectId" value="#{demandBean.dmdScreenLabelVO.selectAll}" />
<div></div>
<h:selectBooleanCheckbox id="checkbox1" value="Select All" onclick="checkAll(this)"/>
</f:facet>
<h:selectBooleanCheckbox id="checkbox2" value="#{item.selected}"/>
</p:column>
Im getting the value as false, when I check the and click on the save button. I have written an Action listerner, below is the code corresponding to the actionListener
public void saveData(ActionEvent event)
{
System.out.println("Entering the Save :");
selected = isSelected();
System.out.println("value of Selected"+selected);
}
I have tried debugging the code as well, but not sure why the value for is getting displayed as false. Please Assist. Thanks in Advance
You seem to be binding the value of all checkboxes in the column to the one and same bean property. This way the value will ultimately end up to be the one of the last row in the column.
This is not how it's supposed to be used.
You basically need to bind the value of the checkbox to the property of the currently iterated row object (the one behind the var attribute of the datatable).
<p:dataTable value="#{bean.items}" var="item">
<p:column>
<p:selectBooleanCheckbox value="#{item.selected}" />
Alternatively, you could use the <p:column selectionMode="multiple" /> to use builtin multiple selection support of the PrimeFaces datatable (see also the showcase example).
<p:dataTable value="#{bean.items}" var="item" rowKey="#{item.id}" selection="#{bean.selectedItems}">
<p:column selectionMode="multiple" />

Resources