【问题标题】:Why JSF form maintain the validation styles even if has values on it?为什么 JSF 表单即使有值也要保持验证样式?
【发布时间】:2020-01-02 01:24:02
【问题描述】:

我有一个表单 (frmAddPax) 来添加一些用户数据。这些数据可以手动提交,也可以通过条形码阅读器提交。当按下“Escanear”按钮时,此按钮将调用另一个表单 (frmScan) 的对话框。

此表单从条形码阅读器读取一些数据,这些数据在托管 bean 中进行处理。数据创建了一个以原始形式 (frmAddPax) 使用的对象。

问题是所有表单都有样式,因为上面没有任何数据,所有必填字段都有 required="true" 属性。

如果我再次按下“Escanear”按钮并扫描相同的数据,它会很好地显示表单。

我认为这可能是因为在表单中的数据准备好更新之前发生了验证过程,但正如我在某些问题中看到的那样 actionactionListener 事件发生在更新过程之前,所以我不知道。

这是表单的代码:

<h:form id="frmAddPax"
rendered="#{MB.renderStatus.isRenderFormAddPax()}">
<p:panelGrid styleClass="no-border">
    <p:row>
        <p:column>
            <h:outputText
                value="#{label['manageVipLoungeEntrance.addPassenger.firstName']} />
        </p:column>
        <p:column>
            <p:inputText required="true"
                value="#{manageVipLoungeEntranceExtMB.passenger.firstName}"
                style="text-transform: uppercase;" converter="upperCaseConverter">
                <f:ajax event="blur" update="@this" render="@this" />
            </p:inputText>
        </p:column>
        ...
        ...
        <!-- BOTON ESCANEAR AGREGAR PASAJERO -->
        <p:column>
            <p:commandButton inmediate="true"
                value="#{label['manageVipLoungeEntrance.addPassenger.button.scan']}"
                onclick="showLocalDate()" update=":frmScan"
                actionListener="#{manageVipLoungeEntranceExtMB.clear}"
                oncomplete="{wgvScan.show()}" />
        </p:column>
        <!-- BOTON ESCANEAR AGREGAR PASAJERO -->
    </p:row>
</p:panelGrid>

这是产生“Escanear”按钮的调用代码:

<p:commandButton inmediate="true"
    value="#{label['manageVipLoungeEntrance.addPassenger.button.scan']}"
    onclick="showLocalDate()" update=":frmScan"
    actionListener="#{manageVipLoungeEntranceExtMB.clear}"
    oncomplete="{wgvScan.show()}" />

这是处理条形码读取并使用处理过的数据更新原始表单的小部件的代码。

<p:dialog widgetVar="wgvScan" modal="true" showEffect="fade"
            closeOnEscape="true" resizable="false">
  <h:form id="frmScan">
        <p:graphicImage value="../resources/images/barCode.png"
            rendered="#{manageVipLoungeEntranceExtMB.showTablePassenger!=true}" />
        <p:inputText id="itbarcode"
            rendered="#{manageVipLoungeEntranceExtMB.showTablePassenger!=true}"
            value="#{manageVipLoungeEntranceExtMB.barCode}" onfocus="true"
            autocomplete="off" styleClass="insertData"
            style="background:#ffffff; position:absolute;left:-7000;" />
        <p:commandButton id="cmdReadBarcode" style="display:none"
            onclick="showLocalDate()"
            actionListener="#{manageVipLoungeEntranceExtMB.readBarCode}"
            update=":frmAddPax :growl">
        </p:commandButton>
        <p:defaultCommand target="cmdReadBarcode" />
        ...
    </h:form>

[编辑] @alibttb 回答让我找到解决方案。

我在调用对话框以监听扫描仪的按钮之前添加了一个 remoteCommand。

<p:remoteCommand name="refreshForm" process=":frmAddPax" update=":frmAddPax" />
    <p:commandButton
        value="#{label['manageVipLoungeEntrance.addPassenger.button.scan']}"
        onclick="showLocalDate()" process="@this" update=":frmScan"
        actionListener="#{manageVipLoungeEntranceExtMB.clear}"
        oncomplete="{wgvScan.show()}" />
</p:column>

在处理条形码的表单对话框中,我添加了一个调用remoteCommand 的onHide 属性。 我按照建议将对话框表单的外壳更改为表单对话框。

<h:form id="frmScan">
<p:dialog widgetVar="wgvScan" modal="true" showEffect="fade"
    closeOnEscape="true" resizable="false" onHide="refreshForm()">

【问题讨论】:

  • 嗨,下次请创建一个minimal reproducible example。缩小到一两个输入,没有对话框,没有 css,没有面板,没有 i18n vua 包等。为我们检查事情更容易(也许你甚至自己找到解决方案。另见 stackoverflow.com/tags/jsf/info
  • 感谢您的反馈,我将编辑帖子以使其更具可读性。给您带来不便深表歉意。

标签: primefaces jsf-2


【解决方案1】:

当您单击 Escanear 按钮时发生的情况是您正在处理整个表单,因此提交所有具有空值的字段,这将导致验证错误,您的按钮是即时的,所以会发生什么以下:

  1. actionListener 是即时的,因此首先调用它,托管 bean 填充来自条形码扫描仪的数据。
  2. 正在验证表单数据,但它无效,因此所有输入都设置了 inValid 标志。
  3. 在包含表单更新的服务器上创建响应,显示来自托管 bean 的新值以及验证过程中输入的 inValid 状态。

请注意,提交的数据(空值)未应用于模型,因为它无效。

要解决这个问题,只需在按钮上使用部分处理功能,并删除 immediate="true",这只是一个糟糕的设计。

只需将 Escanear 按钮中的 immediate="true" 替换为 process="@this"。

如果你不熟悉 JSF 和 primefaces 的部分处理功能,你应该看看。

如果您确实需要在扫描完成后提交表单进行验证,那么您需要使用 p:remoteCommand 在 actionListener 完成后提交表单:

    <p:remoteCommand name="validateForm" process="@form"/>

    <p:commandButton value="#{label['manageVipLoungeEntrance.addPassenger.button.scan']}"
    onclick="showLocalDate()" update=":frmScan" process="@this"
    actionListener="#{manageVipLoungeEntranceExtMB.clear}" 
    oncomplete="{wgvScan.show()}" />

另一种形式 frmScan 做:

<h:form id="frmScan">
<p:dialog widgetVar="wgvScan" modal="true" showEffect="fade"
        closeOnEscape="true" resizable="false" onHide="validateForm()">
....
....complete your code

p:remoteCommand 的名称成为一个 javascript 函数,一旦扫描对话框被隐藏,就可以回调该函数。

注意在您的浏览器中打开开发控制台并观察两个请求,一个用于更新表单并关闭对话框,另一个由p:remoteCommand 引起以验证表单。

注意 1(与您的问题无关)我使用 frmScan 包围 p:dialog 这是正确的做法,表单应该围绕对话框而不是其他方式周围。

【讨论】:

  • 我已经进行了更改,现在没有任何情况下的验证样式(当未从扫描仪检测到任何内容或所有数据都正常时)
  • 正如我所说,您需要在其他地方验证扫描仪输入,填充模型然后将数据发送到表单然后提交表单进行验证不是正确的选择,但如果这是您想要的要做到这一点,您可以使用 ap:remoteCommand 在 actionListener 使用按钮的 onComplete 完成更新表单后实现提交表单。如果您需要,我可以发布编辑。 @JuanEnriqueRiquelme
  • 感谢您的帮助,我需要做的是:调用接收扫描仪字符串的表单(当您按下扫描仪按钮时,会出现一个条形码 png 等待扫描仪读取)。当用户使用 frmScan 的 actionListener readBarCode 方法读取条形码时。最后,我更新了 frmAddPax 以呈现读取的值。如果您可以编辑并添加有关 p:remoteCommand 的信息会很棒。如果我不能很好地解释我很抱歉我对 jsf/primefaces 很陌生,我必须在这个网站上做一些改变。
  • p:remoteCommand 就像一个魅力!我必须对 remoteCommand 的进程进行更改并为其添加更新属性。非常感谢!!
猜你喜欢
  • 2010-10-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-04-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多