validation - 当为空时,有条件地跳过验证 f :selectItem in p/h:selectOneMenu is selected

标签 validation jsf primefaces selectonemenu

家长:

<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>

child :

<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",子列表将被阻止更新。从技术上讲没有什么问题,但是没有 parent 的 child 的存在可能会给最终用户带来糟糕的体验。

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

执行此操作的一种方法是检查 selectedChildchildrenList 本身是否为 null/空。比如,

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

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

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

最佳答案

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

不幸的是,在 View 中声明这一点确实不简单。有几个技巧/解决方法。最常用的方法是仅检查特定操作是否被调用。

例如通过确定HTTP request parameter map中是否存在其客户端ID来检查是否调用了所需的保存按钮。由 implicit EL object 提供#{param} :

<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 是否不等于具有预定义名称 javax.faces.source 的 HTTP 请求参数来调用表示 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() 引用表单而不绑定(bind)表单(如果您知道组件树中的位置;如果形式例如是 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>

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

另请参阅:

关于validation - 当为空时,有条件地跳过验证 f :selectItem in p/h:selectOneMenu is selected,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31624969/

相关文章:

java - 将参数传递给 PrimeFaces 星级评分组件?

validation - Symfony2 验证过滤器

xml - 在输出地址节点之前检查 5 行中至少有 2 行存在于 XSL 1.0 中的地址上

C#限制代码量

javascript - 将 onclick 事件添加到禁用字段

jsf - 当 p :fileUpload? 中的多个上传完成时

java - PrimeFaces 4.0 selectOneMenu-ajax-call 适用于 GlassFish 4.0,但不适用于 Tomcat 7.0.27?

javascript - PrimeFaces 每页行数模板

angularjs - AngularUI datepicker-popup - 手动输入日期和最小/最大日期

在通过 Ajax 更新 JSF 组件后,JavaScript/jQuery 事件监听器不起作用