仅在第一个组件通过验证时才有条件地更新第二个组件

时间:2018-04-04 21:13:38

标签: jsf primefaces

我有两个PrimeFaces selectOneMenu组件。当第一个组件设置为某个值时,我需要第二个组件。我使用Ajax和绑定在第一个组件提交时更新第二个组件,以便用户在第二个组件的标签旁边看到所需的'*'。那部分很容易。

这是(稍微简化)的代码:

<p:outputLabel id="foolbl" for="foo"
    value="Foo" />
<p:selectOneMenu id="foo" required="true"
    value="#{bean.foo}" binding="#{foobnd}">
<f:selectItem itemLabel="Select One" itemValue="" />
<f:selectItems
    value="#{bean.foovalues}" />
<p:ajax
    update="@this foolbl bar barlbl"
    process="@this"/> 
</p:selectOneMenu>

<p:outputLabel id="barlbl" for="bar"
    value="Bar" />
<p:selectOneMenu id="bar"
    required="#{foobnd.valid and foobnd.value eq 'value1'}"
    value="#{bean.bar}">
<f:selectItem itemLabel="Select One" itemValue="" />
<f:selectItems
    value="#{bean.barValues}" />
<p:ajax update="@this barlbl" process="@this" />
</p:selectOneMenu>

它工作正常,但有以下例外:

  1. 用户从foo中选择“值1”。结果:Bean更新为foo&amp;酒吧变得必需;
  2. 用户从栏中选择一些值。结果:bean用bar更新;
  3. 用户取消选择条形图中的值(选择“选择一个”)。结果:验证失败,因为需要栏。 Bean未更新;
  4. 用户取消选择foo中的值(选择“Select One”)。结果:Bean使用foo更新。 Bar使用先前提交的bean.bar值(“值1”)进行更新。
  5. 显然,这是按照JSF的原则运行的。但是,我担心这会导致用户没有注意到问题,并且在他不打算的时候意外地提交了bean.bar的值。这是一种边缘情况,但用户可以在foo中选择“Select One”,然后选择“value 1”以外的某个值,从而导致出现问题。

    为避免这种情况,我可以在foo的ajax调用的process属性中添加bar,如下所示:

    <p:selectOneMenu id="foo" required="true"
        value="#{bean.foo}" binding="#{foobnd}">
    <f:selectItem itemLabel="Select One" itemValue="" />
    <f:selectItems
        value="#{bean.foovalues}" />
    <p:ajax
        update="@this foolbl bar barlbl"
        process="@this bar"/> 
    </p:selectOneMenu>
    

    这可以防止前面描述的问题,但它也会在初始选择foo时提交bar的值,从而突出显示条为红色以便验证失败。我不希望这种情况发生。当提交foo时,我只希望'*'出现在bar旁边。我不希望它被突出显示为验证失败。

    我已经尝试过听众和客户验证器来解决这个问题,但到目前为止,没有什么能够正常运作。 resetValues也不能完全按我的意愿行事,因为我不喜欢它只是重新选择用户刚刚取消选择的值。

    我正在使用PrimeFaces 6

    实现这一目标的最佳方法是什么?

1 个答案:

答案 0 :(得分:0)

难道你的要求没有任何意义吗?如果需要selectOneMenu foo,则还需要selectOneMenu栏 在任何情况下。那么为什么不选择使用bar而不是在选择foo时更新它?它必须被选中 无论如何。如果您包含您的要求,那么如何不显示&#34;选择一个&#34;选择项目后的选项, 因为用户无论如何都必须选择一个选项。如果你仍然包含你的观点,你可以尝试设置 如果条形图验证失败并且使用类似的PostValidateEventListener,则bar的模型值为null:

bean中的

方法:

public void resetModelValue(ComponentSystemEvent event) throws AbortProcessingException {
    UIInput input = (UIInput) event.getSource();
    if (input.isValid()) {
        return;
    }
    input.getValueExpression("value").setValue(FacesContext.getCurrentInstance().getELContext(), null);
}

为条形码注册PostValidateEventListener:

<p:selectOneMenu id="bar" ...>
    ...
    <f:event type="postValidate" listener="#{bean.resetModelValue}" />
</p:selectOneMenu>

但是我认为这个解决方案并不能解决你所有的问题。