【问题标题】:Validate readonly components anyway on form submit在表单提交时验证只读组件
【发布时间】:2014-07-28 03:11:19
【问题描述】:

我们有一个实体的 UI,该实体要么拥有工具,要么拥有发行者,但从不拥有两者。您可以从弹出的搜索对话框中选择一个并将其分配给实体。

用户可以在“搜索...”按钮旁边看到两者的编号和名称。这两个必须都是不可编辑的,即我们各自的<p:inputText ... readonly="true" ... /> 将输入变灰。

我们现在的要求是,当没有选择或同时选择工具和发行者时,不仅应该显示验证消息,而且标有readonly="true" 的文本框也显示为红色(以及和他们的标签)。

添加时,按“保存”前:

添加时,按“保存”后:

我尝试了一些方法,然后最终选择了 OmniFaces <o:validateMultiple>,这似乎朝着正确的方向发展。但是,我随后注意到验证器没有启动,正如您从图像中看到的那样......(我刚刚删除了readonly="true" 让您看到效果)

以下是代码摘录:

<!-- this panel is insider a form, yes -->
<h:panelGroup id="subpanel"
              layout="block">
    <o:validateMultiple id="instrument-or-issuer-validator"
                        validator="#{barrierCrossingManager.validateInstrumentOrIssuer}"
                        components="instrument-isin instrument-description issuer-number issuer-name"
                        message="..." />
    <!-- some panel grid with the inputs -->
    ...
        <p:panelGrid id="issuer-subpanel">
            <p:row>
                <p:column>
                    <p:outputLabel for="issuer-number" value="#{msg['common.number.label']}:" />
                </p:column>
                <p:column colspan="3">
                    <p:inputText id="issuer-number"
                                 value="#{barrierCrossingManager.selectedIssuer.nbr}"
                                 readonly="false" />
                </p:column>
                ...
            </p:row>
        </p:panelGrid>
    ...
    <h:messages id="msgs"
                layout="list"
                styleClass="subcontent-validation-msg-wrapper"
                showDetail="false"
                showSummary="true" />
</h:panelGroup>

你是怎么解决这个问题的?

问题似乎是 OmniFaces 或 JSF(?) 不验证只读组件。我还查看了 &lt;o:validateMultiple&gt; 的 OmniFaces VDL,但没有像 allowReadOnlyComponentHighlighting 或类似的标志。

还有其他方法吗?

【问题讨论】:

    标签: validation jsf readonly


    【解决方案1】:

    出于安全原因,JSF 确实会从处理(转换、验证和模型更新)中跳过只读(和禁用)字段。您不希望黑客能够通过操纵请求参数来编辑这些值,对吧?出于明显的安全原因,OmniFaces 也会以同样的方式跳过它们。

    最好的办法是在readonly 属性中放置一个EL 表达式,该表达式在应用请求值和验证阶段(第二和第三阶段)评估false,但在所有其他阶段评估true。检查当前相位序数是否为 4 或更大就足够了。无论如何,这应该允许 JSF 对值执行验证。然后,您需要向rendered 属性添加一个EL 表达式,该表达式在更新模型值阶段(第四阶段)评估false,这样模型值就不会被更新,因为readonly 在此期间是false应用请求值和验证阶段(因此组件设置了其local value,这会触发模型更新)。

    您可以通过FacesContext#getCurrentPhaseId() 获得当前的JSF 阶段,它在EL 中也可以通过#{facesContext.currentPhaseId} 获得。 PhaseId 反过来有一个 getOrdinal() 方法返回阶段索引(标准阶段从 1 到 6)。

    总结,无论如何都应该这样做以验证它们,但要防止模型更新:

    <p:inputText
        readonly="#{facesContext.currentPhaseId.ordinal ge 4}" 
        rendered="#{facesContext.currentPhaseId.ordinal ne 4}" 
    />
    

    【讨论】:

    • 谢谢,我使用您的解决方案尝试了一些方法。问题是当我们提交带有只读输入&lt;o:validateMultiple&gt; 的面板时,命令按钮的操作被调用,导致调用创建或更新例程,这将失败,因为未设置某些内容。有没有办法让&lt;o:validateMultiple&gt; 不调用该操作?请注意,只要表单上有空的非只读必需&lt;p:inputText&gt;,就不会发生这种情况。
    猜你喜欢
    • 2021-04-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-02-12
    • 2016-01-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多