当p/h:selectOneMenu中的f:selectItem为空时,有条件跳过验证



父母:

<p:selectOneMenu id="parentList"
                 value="#{bean.selectedParent}"
                 converter="#{parentConverter}"
                 required="true">
        <f:selectItem itemLabel="Select" itemValue="#{null}"/>
        <f:selectItems var="parent"
                       value="#{bean.parentList}"
                       itemLabel="#{parent.parentName}"
                       itemValue="#{parent}"/>
        <p:ajax update="childrenList" listener="#{bean.setchildren}"/>
</p:selectOneMenu>

孩子:

<p:selectOneMenu id="childrenList"
                     value="#{bean.selectedchild}"
                     converter="#{childConverter}"
                     required="true">
        <f:selectItem itemLabel="Select" itemValue="#{null}"/>
        <f:selectItems var="child"
                       value="#{bean.childrenList}"
                       itemLabel="#{child.childName}"
                       itemValue="#{child}"/>
</p:selectOneMenu>

被管理bean:

@Named
@ViewScoped
public class Bean implements Serializable {
    @Inject
    private Service service;
    private Parent selectedParent;
    private Child selectedChild;
    private List<Parent> parentList;
    private List<Child> childrenList;
    private static final long serialVersionUID = 1L;
    public Bean() {}
    @PostConstruct
    private void init() {
        parentList = service.getParentList();
        // Not necessary unless selectedParent is already available in edit mode.
        if(selectedParent != null) {
            childrenList = service.getChildrenListByParent(selectedParent);
        }
    }
    public void setChildren() {
        if(selectedParent != null) {
            childrenList = service.getChildrenListByParent(selectedParent);
        } else {
            childrenList = null;
        }
    }
    // Getters and setters.
}

子列表将根据它们的父列表填充,即子列表应该只包含与特定父列表关联的子列表。

当父列表中的第一个父列表被选中时,子列表应该被重置为空,即如果没有父列表,子列表不应该可见。

由于父列表有一个必需的字段验证器,它导致验证。当父列表中的第一项被选中时,子列表将因为required="true"而被阻止更新。这在技术上没有什么问题,但是没有父母的孩子可能会给最终用户带来不好的体验。

应该发生的是,当父列表中的第一项被选中时,它不应该导致验证,即验证将有条件地跳过。

这样做的一种方法是检查selectedChildchildrenList本身是null/empty。例如,

required="#{empty selectedChild or empty childrenList}"

但是在这种情况下,这似乎不是有条件跳过验证的规范方式。

是否存在更好的跳过验证的方法,当父列表中的第一个项目被选中时,子列表可以与父列表一起被清空(验证应该在所有其他情况下引起)。例如,当表单本身以同步或异步方式提交时?

基本上,您需要依赖于操作的验证。例如,当调用特定的<p:ajax>操作时跳过验证,而不是在其他操作上跳过验证。

不幸的是,在视图中声明

确实不容易。有几个技巧/变通方法。最常用的一种是检查特定的操作是否被调用。

。检查是否调用了所需的保存按钮,方法是通过隐式EL对象#{param}:

确定其客户端ID在HTTP请求参数映射中的存在情况。
<h:form>
    <p:selectOneMenu ... required="#{not empty param[save.clientId]}">
        ...
        <p:ajax ... />
    </p:selectOneMenu>
    <p:selectOneMenu ... required="true">
        ...
    </p:selectOneMenu>
    <p:commandButton binding="#{save}" ... />
</h:form>

或者检查组件自己的<p:ajax>是否没有被调用,通过确定组件自己的客户端ID是否不等于HTTP请求参数的预定义名称javax.faces.source,表示ajax请求的来源(下面的#{component}是一个隐式EL变量,表示当前的UIComponent):

<h:form>
    <p:selectOneMenu ... required="#{param['javax.faces.source'] ne component.clientId}">
        ...
        <p:ajax ... />
    </p:selectOneMenu>
    <p:selectOneMenu ... required="true">
        ...
    </p:selectOneMenu>
    <p:commandButton ... />
</h:form>

或者检查父表单是否由UIForm#isSubmitted()提交,它只会在"完整表单提交"时评估true;与process="@form"中的使用相同(<p:ajax process>默认为@this,不会触发"完整表单提交";<p:commandButton process>默认为@form,因此会触发"完整表单提交"):

<h:form binding="#{form}">
    <p:selectOneMenu ... required="#{form.submitted}">
        ...
        <p:ajax ... />
    </p:selectOneMenu>
    <p:selectOneMenu ... required="true">
        ...
    </p:selectOneMenu>
    <p:commandButton ... />
</h:form>

或者通过UIComponent#getNamingContainer()引用表单而不绑定表单(如果你知道它在组件树中的位置;如果表单是例如2命名容器父返回,那么使用#{component.namingContainer.parent.namingContainer.submitted}):

<h:form>
    <p:selectOneMenu ... required="#{component.namingContainer.submitted}">
        ...
        <p:ajax ... />
    </p:selectOneMenu>
    <p:selectOneMenu ... required="true">
        ...
    </p:selectOneMenu>
    <p:commandButton ... />
</h:form>

随你挑。第一个解决方案之前已经提供了几次,因为它最容易被初学者理解和调整。

参见:

    如何让验证依赖于按下的按钮?
  • Primefaces dependent selectonmenu and required="true"
  • 如何禁用所需的标签在一个selectOneMenu当p:ajax事件=变化?

相关内容

  • 没有找到相关文章

最新更新