I am using a <h:selectBooleanCheckbox>
in the facet header of a DataTable. All the rows content for that <h:column>
DataTable are <h:selectBooleanCheckbox>
. The rows are getting selected perfectly the way I wanted. Below is the code I used:
<h:form>
<h:dataTable
value="#{employeeService.employeeList }"
var="empl"
binding="#{employeeService.dataTablebinding }">
......
......
......
<h:column>
<f:facet name="header">
<h:selectBooleanCheckbox id="chkBoxAll" value="#{employeeService.checkedHdr }" valueChangeListener="#{employeeService.checkAll }" onclick="submit()"></h:selectBooleanCheckbox>
</f:facet>
<h:selectBooleanCheckbox id="tableChkBox" value="#{empl.checked }" valueChangeListener="#{employeeService.getCheckChanged }" onclick="submit()"></h:selectBooleanCheckbox>
</h:column>
</h:dataTable>
This is the code for the ValueChangeListener
:
public void checkAll(ValueChangeEvent event){
if(isInvokeApplicationPhase(event)){
Iterator<Employee> empl = employeeList.iterator();
while(empl.hasNext()){
Employee emp = empl.next();
emp.setChecked(checkedHdr);
}
}
}
This is the isInvokeApplicationPhase
utility I added up for making this code work (referred the solution suggested by BalusC
in this link: JSF 1.2: valueChangeListener event not returning newly selected value ):
public boolean isInvokeApplicationPhase(FacesEvent event){
if(event.getPhaseId() != PhaseId.INVOKE_APPLICATION){
event.setPhaseId(PhaseId.INVOKE_APPLICATION);
event.queue();
return false;
}
return true;
}
Now my Question:
What is the use of that isInvokeApplicationPhase
check in the ValueChangeListener
method? If I comment out this check then it does not work - WHY? I thought I have understood the JSF life cycle properly but this behavior proves that I have not :(
Kindly let me know the explanation based on the JSF life cycle phases.
The value change listener runs during validations phase and is intented to hook on the value change event. I.e. the newly submitted value is different from the original model value.
The validations phase runs before update model values phase, wherein JSF set all submitted, converted and validated values in the model (the backing bean's properties). So when you attempt to change the model value of a different field in the value change listener, then it would be overridden during the update model values phase.
This particular trick re-queues the value change event to the invoke application phase, which runs after update model values phase. So when you attempt to change the model value of a different field, then it won't be overriden.
In a nutshell: the validations phase is simply the wrong moment to manually manipulate the model values and the invoke application phase is the right moment to manually manipulate the model values.
Actually, the value change event is being abused here. You should rather be using an action event here, but this was not available for inputs in JSF 1.x. This was only available in JSF 2.x in flavor of <f:ajax listener>
.