PrimeFaces selectCheckboxMenu:toggleSelect actionListener中的旧值

stg*_*stg 6 primefaces jsf-2

在我的JSF视图中p:selectCheckboxMenu,我想要通过AJAX对所选值执行某些业务逻辑.

对于一个简单的change事件,它工作正常,但对于一个toggleSelect事件没有.在我的监听器方法中,我正在检索旧的选择,但我期待这里的新选择.

请参阅以下示例:

@ViewScoped
@Named
public class RequestBean implements Serializable {
    private List<String> list; // + getter/setter

    @PostConstruct
    private void init() {       
        list = new ArrayList<String>() {{
          add("one");  add("two"); add("three");
        }};
    }

    public void listener() {
        System.out.println("Current content of \"list\":");
        for(String s : list) {
            System.out.println(s);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

在JSF视图中:

<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>
Run Code Online (Sandbox Code Playgroud)

现在让我们考虑以下用例:您正在进入视图,选择"一个"和"两个".如果我单击"全选"复选框,结果为:

Info:   Current content of "list":
Info:   one
Info:   two
Run Code Online (Sandbox Code Playgroud)

但预期结果如下:

Info:   Current content of "list":
Info:   one
Info:   two
Info:   three
Run Code Online (Sandbox Code Playgroud)

对于常规更改事件,它按预期工作.在这里,我在听众中获得了新的选择.我该如何解决?或者我做错了什么?


GlassFish 4.1,在Java 1.8.0_45上运行

JSF 2.2.10(Mojarra)

PrimeFaces 5.1

OmniFaces 1.8.1

Xtr*_*ica 4

这个问题似乎与过早调用侦听器有关。通过进行一些基本的调试,我发现toggleSelect在更新模型值之前调用侦听器方法,而change事件在修改模型值之后执行此操作。这是我当前的代码:

请求Bean:

@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!");
    }
}
Run Code Online (Sandbox Code Playgroud)

页面.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>
Run Code Online (Sandbox Code Playgroud)

这就是您当前步骤的跟踪:

Values set: [one]
Listener called!
Values set: [one, two]
Listener called!
Listener called!
Values set: [one, two, three]
Run Code Online (Sandbox Code Playgroud)

最后一个是toogle 选择,您可以看到模型已正确更新,但之前调用了侦听器。

让我们多玩一点自定义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
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,模型值始终在UPDATE_MODEL_VALUES阶段中设置,而change事件INVOKE_APPLICATION按其应有的方式执行,toggleSelect监听器APPLY_REQUEST_VALUES在列表中之前执行。

这似乎是 Primefaces 的一个 bug,应该在他们的 GitHub 分支中通知。

也可以看看: