当前位置: 首页 > 知识库问答 >
问题:

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

岳杜吟
2023-03-14

我有两个PrimeFaces SelectOne菜单组件。当第一个组件设置为某个值时,我需要第二个组件成为必需的。我使用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更新

显然,这是工作,因为它应该每个JSF。然而,我担心这会导致用户没有注意到问题,并意外地提交了bean.bar的值,而他并不打算这样做。这是一种边缘情况,但是用户可以在foo中选择“选择一个”,然后选择除“值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的值,因此在验证失败时将bar突出显示为红色。我不希望这种情况发生。当foo被提交时,我只希望“*”出现在酒吧旁边。我不希望它被强调为验证失败。

我已经尝试了侦听器和客户验证器来解决这个问题,但是到目前为止没有什么工作是完全正确的。resetValue也不完全做我想要的,因为我不喜欢简单地重新选择用户刚刚取消选择的值。

我用的是PrimeFaces 6

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

共有1个答案

哈翔
2023-03-14

你的要求是不是有点愚蠢?如果selectOneMenu foo是必需的,那么selectOneMenu栏在任何情况下也是必需的。那么,如果选择了foo,为什么不干脆让bar也是必需的,而不是更新它呢?无论如何都要选择它。如果您包含您的需求,那么在选择项目后不显示“选择一个”选项怎么样,因为用户无论如何都必须选择一个选项。如果您仍然由您的观点组成,您可以尝试将bar的模型值设置为null,如果bar验证失败,使用像这样的PostValidateEventListener:

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);
}

为bar注册PostValidateEventListener:

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

然而,我认为这个解决方案并不能解决你所有的问题。

 类似资料:
  • 我的项目中有:https://www.primefaces.org/primereact/#/fullcalendar 我一天有2个事件,我通过以下代码找到了第一个事件: 我需要找到第二个或更多的事件。 UPD如何在第二天工作//div[@class='fc-entent-bone eton'][.//td[@data-date='2019-09-03']]//tbody/tr/td[计数(//t

  • 我的用户控件上有两个组合框。我的目标是,当第一个被选中(里面有一个项目)时,第二个应该处于活动状态。以下是代码片段: 当第一个是项目选择时,如何激活第二个组合框?

  • 本文向大家介绍怎么定时更新一个组件?相关面试题,主要包含被问及怎么定时更新一个组件?时的应答技巧和注意事项,需要的朋友参考一下 Creating a timer in , and recycle it in . For react hooks, creating a timer in useEffect function with as the useEffect check condition

  • 我有三张桌子,桌子A,桌子B和桌子C 我想将数据从TableA列DateA迁移到TableB列DateB,仅当表B中的date字段为空时(我不想覆盖任何现有数据) 我需要使用TableC连接TableA和TableB,以匹配应按其RobotNumber更新的A行和B行。 表格a 表格c 我尝试连接这些表并执行如下更新,但查询超时:

  • 问题内容: 我想通过按下JFrame中的按钮来启动另一个JFrame。但是,如果按Button,它将显示JFrame,但其中不显示Buttons和Sliders。 } 第二个具有完全相同的构造函数。滑块和按钮不是静态的。在应显示“按钮”的位置,屏幕为黑色。 希望你能帮我 :) 编辑: 问题答案: 做你最后一件事… 另外,在添加新组件时,使用和鼓励容器更新其布局。 建议: 确保您的用户界面在EDT上

  • 我有一个数据集(汽车): 我想按年份分组并返回金额的总和,即: 并将其输出到列表框中。 我可以在没有买入/卖出条件的情况下求和: