为什么即使有值,JSF表单仍保留验证样式? [英] Why JSF form maintain the validation styles even if has values on it?

查看:52
本文介绍了为什么即使有值,JSF表单仍保留验证样式?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have a form (frmAddPax) to add some users data. This data could be submited manual or vía a barcode reader. When the button "Escanear" is pressed this one calls a dialog with another form (frmScan).

此表单从条形码读取器读取一些数据,并且此数据在托管Bean中进行处理.数据将创建一个以原始格式(frmAddPax)使用的对象.

This form read some data from a barcode reader and this data is processed in the managed bean. The data creates an object that is used in the original form (frmAddPax).

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

The problem is all the form has the styling as there wasn't any data on it, all the mandatory fields have the required="true" attribute.

如果我再次按下"Escanear"按钮并扫描相同的数据,则显示表格就很好了.

If I press the "Escanear" button again and scan the same data it shows the form just fine.

我认为这可能是因为在准备好以验证表的形式更新数据之前已经发生了,但是正如我在某些问题中看到的那样, action actionListener 事件发生在更新流程之前,所以我一无所知.

I think this could be because before the data is ready updated in the form the validation process happend, but as I have seen in some questions the action and actionListener events happend before the update process so I have no clue.

这是以下形式的代码:

<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"按钮的呼叫的代码:

This is the code for the call that made the "Escanear" button:

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

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

And this is the code for the widtget that process the barcode read and updates the original form with the data processed.

<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的答案可以帮助我解决问题.

@alibttb answer get me to the solution.

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

I added a remoteCommand before the button that calls the dialog to listen the scanner.

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

然后在带有处理条形码表单的对话框中,我添加了一个 onHide 属性,称为remoteCommand. 我将对话框形式的外壳更改为表格对话框,如所建议的那样.

And in the dialog with the form that process the barcode I added a onHide attribute calling the remoteCommand. I change the enclouse of the dialog-form to form-dialog as was sugested.

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

推荐答案

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

What happens when you click the Escanear button is that you are processing the whole form, thus submitting all the fields with empty values, this will cause validation errors, your button is immediate so what happens is the following:

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

请注意,由于无效,提交的数据(空值)未应用到模型.

notice that the submitted data (empty values) is not applied to the model as it's not valid.

要解决此问题,只需在按钮上使用部分处理功能,然后删除"instant ="true",那是一个糟糕的设计.

to fix this, just use partial processing feature on your button, and remove the immediate="true", it's just a bad design.

只需在 Escanear 按钮中将process ="@ this"替换为Instant ="true".

just replace immediate="true" with process="@this" in the Escanear button.

如果您不熟悉JSF和primefaces的部分处理功能,则应该看一下.

If you're not familiar with partial processing feature of JSF and primefaces you should give it a look.

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

if you really need to submit the form for validation after the scan is complete then you need to use a p:remoteCommand that submits the form after the actionListener is complete:

    <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函数,可以在隐藏扫描对话框后重新调用它.

the name of the p:remoteCommand becomes a javascript function that can be called back once the scan dialog is hidden.

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

Note bring up the dev console in your browser and watch the two requests one for updating the form and closing the dialog and the other one caused by p:remoteCommand to validate the form.

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

Note 1 (not related to your question) that I used the frmScan to enclose p:dialog this is the right way to do it, the form should surround the dialog not the other way around.

这篇关于为什么即使有值,JSF表单仍保留验证样式?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆