JSF - 1 个组件中的验证错误,导致表单中的所有其他组件失败

JSF - Validation error in 1 component, leads all others in the form to fail

大家好

我使用 JSF Mojarra 实现,版本 JSF 2.2

我急需帮助。

  1. 我有一个页面片段。
  2. 我在页面中使用了自定义组件“example_result.xhtml”。
  3. 我有我的BackingBean.java 请注意,此代码不是我编写的真实代码。如果你 运行 它,它会非常丑陋,可能是因为我删除了所有 css 类 并且我只保留了我需要向你展示我的问题的热门内容。

一切都在 1 个表格中。

5个“h:selectManyCheckbox”(在我的代码中我有8个或9个)

在表单中,我有 5 个“h:selectManyCheckbox”,它们在不同情况下使用“value”属性中的值(javaFrameworks2Values、javaFrameworks3Values,...),以及“f:selectItems”使用为这些不同情况创建的“SelectItem”数组(javaFrameworksSelectItems2、javaFrameworksSelectItems3...),只是为了让我了解所有 selectOne 和 select许多组件工作。 关于不同案例的想法来自这些链接: “https://whosebug.com/tags/selectonemenu/info”和 "https://mkyong.com/jsf2/jsf-2-checkboxes-example".

在我有 2 个命令按钮后

1 个用于提交,1 个用于重置值。

显示值

在我通过“example_result.xhtml”显示“h:selectManyCheckbox”的值的结果后。

您可以看到第 4 个“h:selectManyCheckbox”,这是唯一不同的,因为它具有属性“required”和属性“requiredMessage”。它有一个“h:message”来显示验证错误。

在 BackingBean(它是 Spring Bean,但它工作得很好 - 抱歉我不想要 ejbs 3.x), 我已经初始化:

  1. SelectItems 的值和
  2. “value”属性的值,其中将存储“h:selectManyCheckbox”的值以供稍后显示。 [代码完全阉割,使其成为可读片段]。

呈现页面时,我从所有“h:selectManyCheckbox”中选择 select 个复选框(例如,最后两个,因为前两个是首字母)。 当我说 select from all 时,我是认真的。从 4 号开始,具有“必需”属性。我尝试在按钮中(参见代码)“努力 1”或“努力 2”或“努力 3”(在按钮中的“f:ajax”中)并将结果输出到最后一部分像糖果一样显示和更新。没有任何问题。为了用复合组件实现这一点,我在谷歌上搜索并尝试了很多。但是我做到了。

然后是时候尝试第 4 次,看看“required”属性的验证错误。

我select 再次从所有像以前一样,但不是从所有。这次不是来自第 4 个“h:selectManyCheckbox”。我 select 没有从第 4 个“h:selectManyCheckbox”中检查验证程序错误消息(“requiredMessage”)。 结果是: 它显示错误消息(到目前为止还不错),但是这次它没有将其他“h:selectManyCheckbox”中的任何内容更新到最后的输出结果,也没有重置值就像以前一样(当我 select 从所有和第 4 次开始编辑时)。

我知道它说:只要在表单中第 4 个因验证错误而失败,所有其他“h:selectManyCheckbox”将不会更新输出结果(类似于想要全部失败其他人也是)。

但是这里到底发生了什么?

  1. 它没有为要更新到输出的“h:selectManyCheckbox”提供值?
  2. 它通常将值提供给“h:selectManyCheckbox”,但它只是不更新​​输出?

按钮中“f:ajax”的其他努力,可能只是为了解决问题而努力,但在这些情况下,它们甚至不显示第 4 种情况下的错误消息他们也不会(再次)更新其他输出结果。但是也没有消息错误。

不知道你是否清楚这个问题。我可以在讨论中更好地解释,这样我就可以更好地澄清情况。 [老实说,我花了1个半小时才写完这些东西]

提前致谢

========== 来自我页面的片段 ==========

<h:form>
    <h:panelGrid id="smcb" columns="1">
         
        <h:selectManyCheckbox id="smcb1" value="#{myBackingBean.javaFrameworksHardCodedValues}">
            <f:selectItem itemLabel="Java Label" itemValue="Java Value"/>
            <f:selectItem itemLabel="Spring Framework Label" itemValue="Spring Framework Value"/>
            <f:selectItem itemLabel="Hibernate Label" itemValue="Hibernate Value"/>
            <f:selectItem itemLabel="JSF Framework Label" itemValue="JSF Framework Value"/>
        </h:selectManyCheckbox>
         
        <h:selectManyCheckbox id="smcb2" value="#{myBackingBean.javaFrameworks2Values}">
            <f:selectItems value="#{myBackingBean.javaFrameworksSelectItems2}"/>
        </h:selectManyCheckbox>
 
        <h:selectManyCheckbox id="smcb3" value="#{myBackingBean.javaFrameworks3Values}">
            <f:selectItems value="#{myBackingBean.javaFrameworksSelectItems3}"/>
        </h:selectManyCheckbox>
 
        <p><h:message for="smcb4" styleClass="error_messages"/></p>
        <h:selectManyCheckbox id="smcb4" value="#{myBackingBean.javaFrameworks4Values}"
                            required="true"
                            requiredMessage="The 'h:selectManyCheckbox' must have a value. Please select an item from the list!">
            <f:selectItems value="#{myBackingBean.javaFrameworksSelectItems4}"/>
        </h:selectManyCheckbox>
 
        <h:selectManyCheckbox id="smcb5" value="#{myBackingBean.javaFrameworks5Values}">
            <f:selectItems value="#{myBackingBean.javaFrameworksSelectItems5}"/>
        </h:selectManyCheckbox>
         
    </h:panelGrid>
    <br/>
 
    <h:commandButton value="Display Java Frameworks values">
        <!--
        Effort 1 - works perfectly good if I select from all the "h:selectManyCheckbox"
        <f:ajax execute="smcb1 smcb2 smcb3 smcb4 smcb5 smcb6 smcb7 smcb8"
                render="outputId1 outputId2 outputId3 outputId4 outputId5 smcb1 smcb2 smcb3 smcb4 smcb5"/>
        -->
         
        <!--
        Effort 2 - works perfectly good if I select from all the "h:selectManyCheckbox"
        <f:ajax execute="smcb" render="outputId smcb"/>
        -->
         
        <!--
        Effort 3 - works perfectly good if I select from all the "h:selectManyCheckbox"
        <f:ajax execute="@form" render="@form"/>
        -->
         
        <!--
        Not working efforts to solve my problem - but are not solving it
        <f:ajax execute="@form" render="outputId"/>-->
        <f:ajax execute="@form"
                render="outputId1 outputId2 outputId3 outputId4 outputId5 smcb1 smcb2 smcb3 smcb4 smcb5"/>
                Other combinations with the @form and the ids...
        -->
    </h:commandButton>
    <h:commandButton value="Reset Java Frameworks values" action="#{myBackingBean.resetValues}">
        <!--
        Effort 1 - works perfectly good if I select from all the "h:selectManyCheckbox"
        <f:ajax execute="smcb1 smcb2 smcb3 smcb4 smcb5"
                render="outputId1 outputId2 outputId3 outputId4 outputId5 smcb1 smcb2 smcb3 smcb4 smcb5"/>
        -->
         
        <!--
        Effort 2 - works perfectly good if I select from all the "h:selectManyCheckbox"
        <f:ajax execute="smcb" render="outputId smcb"/>
        -->
         
        <!--
        Effort 3 - works perfectly good if I select from all the "h:selectManyCheckbox"
        <f:ajax execute="@form" render="@form"/>
        -->
    </h:commandButton>
    <br/>
 
    <h:panelGrid columns="1" id="outputId">
        <mc:example_result id="outputId1"
                           example_label="1. Java Frameworks hardcoded with 'f:selectItem': "
                           example_result="#{myBackingBean.displayItemValues()}"/>
 
        <mc:example_result id="outputId2"
                           example_label="2. Java Frameworks 2: "
                           example_result="#{myBackingBean.displayItemValues()}"/>
 
        <mc:example_result id="outputId3"
                           example_label="3. Java Frameworks 3: "
                           example_result="#{myBackingBean.displayItemValues()}"/>
 
        <mc:example_result id="outputId4"
                           example_label="4. Java Frameworks 4: "
                           example_result="#{myBackingBean.displayItemValues()}"/>
 
        <mc:example_result id="outputId5"
                           example_label="5. Java Frameworks 5: "
                           example_result="#{myBackingBean.displayItemValues()}"/>
    </h:panelGrid>
</h:form>

========== 我的组件:“example_result.xhtml” ==========

<ui:composition ...
    xmlns:mc="http://xmlns.jcp.org/jsf/composite/mc_components">
 
    <cc:interface>
        <cc:attribute name="example_label" type="java.lang.String" required="true"/>
        <cc:attribute name="example_result" type="java.lang.String" required="true"/>
    </cc:interface>
 
    <cc:implementation>
        <div id="#{cc.clientId}">
            <h:outputText value="#{cc.attrs.example_label}" .../>
            <h:outputText value="#{cc.attrs.example_result}" .../>
        </div>
    </cc:implementation>
</ui:composition>

========== 我的 BackingBean:“我的BackingBean.java” ==========

@org.springframework.stereotype.Component(value = "myBackingBean")
public class MyBackingBean implements Serializable {
 
    // Variables used in the "value" attribute of "HtmlSelectMany" components
    private String[] javaFrameworks2Values; // + Getters-Setters
    // All the others: javaFrameworks3Values, ...
 
    // The "HtmlSelects" components' "SelectItems" are generated by an array of "SelectItem"
    private SelectItem[] javaFrameworksSelectItems2; // +Getters
    // All the others: javaFrameworksSelectItems3, ...
     
 
    @PostConstruct
    protected void initLabelValueMapAndLabelValueArray() {
     
        // Pre-selected values of "HtmlSelectMany" components
        javaFrameworks2Values = new String[]{"Java Value", "Spring Framework Value"};
 
        // Initialization of the array of "SelectItem"
        javaFrameworksSelectItems2 = new SelectItem[4];
        javaFrameworksSelectItems2[0] = new SelectItem("Java Value", "Java Label");
        javaFrameworksSelectItems2[1] = new SelectItem("Spring Framework Value", "Spring Framework Label");
        javaFrameworksSelectItems2[2] = new SelectItem("Hibernate Value", "Hibernate Label");
        javaFrameworksSelectItems2[3] = new SelectItem("JSF Framework Value", "JSF Framework Label");
         
        // Initialization of all the others: javaFrameworks3Values, ..., javaFrameworksSelectItems3, ...
    }
     
    public String displayItemValues() {
        // return array of the result values;
    }
     
    public void resetValues() {
        // Reset the values to the initials
    }
}

在与这里唯一想帮助解决我的问题的人进行大量讨论后(我非常感谢他@WoAiNii),我决定 post 我的解决方案:

我将使用 5 组按钮制作 5 种不同的表单 (submit/reset),以升级此问题,因为表单中有 5 个如此多的相关组件。

但我的问题是开放的: 为什么会发生这种情况,在这种情况下,JSF 中的什么规则正在发生并造成这种情况。 任何有解释的人,例如:

  • 这是 JSF 中的规则,或者
  • 是一个 JSF 错误,或者
  • 在这些情况下会发生这种情况,或者...无论如何...,

我很高兴在这里阅读它,这样我会学得更好,其他人也会从你的这些想法中学习。 非常感谢