This problem seems to be due to the fact that the listener is called too early. While doing some basic debugging, I found that toggleSelect calls the listener method before updating the model values, and the change event does this after modifying them. What is my current code:
RequestBean:
@ViewScoped @ManagedBean public class RequestBean implements Serializable { public List<String> getList() { return list; } public void setList(List<String> list) { this.list = list; System.out.println("Values set: " + list); } private List<String> list; @PostConstruct private void init() { list = new ArrayList<String>() { { add("one"); add("two"); add("three"); } }; } public void listener() { System.out.println("Listener called!"); } }
page.xhtml:
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:h="http://xmlns.jcp.org/jsf/html" xmlns:f="http://xmlns.jcp.org/jsf/core" xmlns:p="http://primefaces.org/ui" xmlns:comp="http://java.sun.com/jsf/composite/comp" xmlns:ui="http://java.sun.com/jsf/facelets"> <h:head /> <h:body> <h:form> <p:selectCheckboxMenu value="#{requestBean.list}" label="List"> <f:selectItem itemValue="one" itemLabel="one" /> <f:selectItem itemValue="two" itemLabel="two" /> <f:selectItem itemValue="three" itemLabel="three" /> <p:ajax event="toggleSelect" listener="#{requestBean.listener}" /> <p:ajax event="change" listener="#{requestBean.listener}" /> </p:selectCheckboxMenu> </h:form> </h:body> </html>
And what a trace for your current steps:
Values set: [one] Listener called! Values set: [one, two] Listener called! Listener called! Values set: [one, two, three]
The final option is Google’s choice, as you can see that the model is updated correctly, but the listener is called earlier.
Let's play a little with a custom PhaseListener :
Entering RESTORE_VIEW 1 Entering APPLY_REQUEST_VALUES 2 Entering PROCESS_VALIDATIONS 3 Entering UPDATE_MODEL_VALUES 4 Values set: [one] Entering INVOKE_APPLICATION 5 Listener called! Entering RENDER_RESPONSE 6 Entering RESTORE_VIEW 1 Entering APPLY_REQUEST_VALUES 2 Entering PROCESS_VALIDATIONS 3 Entering UPDATE_MODEL_VALUES 4 Values set: [one, two] Entering INVOKE_APPLICATION 5 Listener called! Entering RENDER_RESPONSE 6 Entering RESTORE_VIEW 1 Entering APPLY_REQUEST_VALUES 2 Listener called! Entering PROCESS_VALIDATIONS 3 Entering UPDATE_MODEL_VALUES 4 Values set: [one, two, three] Entering INVOKE_APPLICATION 5 Entering RENDER_RESPONSE 6
As you can see, the model values are always set in the UPDATE_MODEL_VALUES phase, and the change event is executed in INVOKE_APPLICATION , as you would expect, the toggleSelect listener executes in APPLY_REQUEST_VALUES , which is up to the list.
This seems to be a Primefaces bug that should be notified in their GitHub branch .
See also: