【问题标题】:Failed validation should prevent closing of modal dialog验证失败应防止关闭模式对话框
【发布时间】:2020-03-23 11:50:38
【问题描述】:

我正在使用 Bootsfaces 来显示模式对话框。在模态对话框中有一个字段(实际上是b:inputTextarea)和一个使用Ajax 提交数据的命令按钮。我想确保用户在提交之前在文本字段中输入了一些内容。如果该字段为空,则不应关闭模式并且不应发生提交,如果该字段为非空,则应关闭对话框并且应以 Ajax 样式进行提交。

由于带有 Bootsfaces 1.4.2 的 issue,我不能使用 b:command 来执行 Ajax 部分。我必须使用h:commandButtonf:ajax 的标准方式。

我正在尝试这样解决我的问题:

<b:form>
    <!--  section that gets updated by ajax-request -->
    <b:panel id="updateSection">
        <h:outputText value="#{testBean.value1}" />
        <b:button value="open dialog" onclick="$('.pseudoClass').modal()" />
    </b:panel>
    <!-- modal dialog -->
    <b:modal title="model" styleClass="pseudoClass" closable="false" closeOnEscape="true">
        <b:panel id="modalOutput"><h:inputText value="#{testBean.value1}" /></b:panel>
        <f:facet name="footer">
            <!-- cancel button -->
            <b:button largeScreen="half" value="cancel" dismiss="modal" onclick="return false;" />
            <!-- submit button ajax-style -->
            <h:commandButton value="submit" action="#{testBean.save()}" onclick="validateModalDialog();">
                <f:ajax render="updateSection" execute="@this modalOutput" onevent="closeModalDialog" />
            </h:commandButton>
            <!-- scripts to close & validate modal dialog -->
            <h:outputScript>
                    function closeModalDialog(data) {
                        var status = data.status;
                        if (status === 'complete') { $('.pseudoClass').modal('hide'); }
                    }
                    function validateModalDialog() {
                        alert('i get called before closing dialog');
                        return false;
                    }    
            </h:outputScript>
        </f:facet>
    </b:modal>
</b:form>

脚本函数validateModalDialog 在模态对话框关闭之前被调用,但无论函数的返回值如何(true 或 false),对话框都会关闭。

我对 JavaScript 的了解相当有限。这也是我选择使用 JSF 和 Bootsfaces 的原因之一。但我很确定有办法进行验证并防止对话框关闭。

在使用标准组件 h:commandButtonf:ajax 时,如何模拟 Bootsfaces 功能(模式对话框中文本字段的客户端验证)?

解决方案:

为了实现客户端验证,防止 Ajax 请求触发和模式对话框关闭,与我的初始代码相比,需要进行以下更改:

<h:commandButton value="submit" action="#{testBean.save()}" onclick="return validateModalDialog();">
     <f:ajax render="updateSection" execute="@this modalOutput" onevent="closeModalDialog" />
</h:commandButton>

【问题讨论】:

标签: ajax jsf bootsfaces


【解决方案1】:

确实像

<h:commandButton>
    <f:ajax onevent="function(e){if(e.status == 'complete') doSomething();}"/>
</h:commandButton>

不等同于

<b:commandButton ajax="true" oncomplete="doSomething();"/>

只有当表单没有验证错误时,才能通过 h:commandButton 的 javascript 关闭模式对话框,您必须:

  1. 按照this post 中的建议将&lt;b:fetchBeanInfos/&gt; 组件添加到您的表单中,我最初建议将其作为您问题的副本。还要确保它随着每个 ajax 请求而更新。
  2. 不要检查data.status == 'complete',而是检查data.status == 'success'
  3. 完全删除onclick="validateModalDialog();"

只有当输入不为空 (required="true") 时才关闭对话框,这是为服务器端验证而更改的代码。请注意,testBean.save() 也只会在有效输入时被调用。

<b:form>
    <!--  section that gets updated by ajax-request -->
    <b:panel id="updateSection">
        <h:outputText value="#{testBean.value1}" />
        <b:button value="open dialog" onclick="$('.pseudoClass').modal()" />
    </b:panel>
    <!-- modal dialog -->
    <b:modal title="model" styleClass="pseudoClass" closable="false"
        closeOnEscape="true">
        <b:panel id="modalOutput">
            <h:inputText id="myInput" value="#{testBean.value1}" required="true" />
            <h:message for="myInput" />
            <b:fetchBeanInfos /> <!-- creates the validationFailed JavaScript variable 
                                  and must be within rendered components. -->
        </b:panel>
        <f:facet name="footer">
            <!-- cancel button -->
            <b:button largeScreen="half" value="cancel" dismiss="modal"
                onclick="return false;" />
            <!-- submit button ajax-style -->
            <h:commandButton value="submit" action="#{testBean.save()}">
                <f:ajax render="updateSection modalOutput"
                    execute="@this modalOutput" onevent="closeModalDialog" />
            </h:commandButton>
            <!-- scripts to close & validate modal dialog -->
            <h:outputScript>
                   function closeModalDialog(data) {
                       var status = data.status;
                       if (!validationFailed &amp;&amp; status === 'success') { $('.pseudoClass').modal('hide'); }
                   }
           </h:outputScript>
        </f:facet>
    </b:modal>
</b:form>

一个小示范:


如果你想在无效表单上完全阻止ajax表单提交并进行客户端验证,你必须按照:JSF ajax request is not fired when combined with JS client-side validation修改你的onclick

<h:commandButton value="submit" action="#{testBean.save()}" 
        onclick="if(!validateModalDialog()) return false;">
    <f:ajax render="updateSection" execute="@this modalOutput" onevent="closeModalDialog" />
</h:commandButton>

注意客户端验证不会阻止用户提交无效数据,例如简单地使用他们的浏览器开发工具。

【讨论】:

  • 当点击commandButton时,函数doSomethingIfValid被调用。但似乎没有办法阻止 Ajax 请求在验证失败时被触发。
  • 是的,doSomethingIfValid 在每个 ajax 请求中被调用 3 次:开始、成功和完成。没关系。 doSomething 仅在表单有效时才被调用。我不明白您所说的“停止 ajax 请求”是什么意思?它没有任何意义。需要完成 ajax 调用才能确定输入是否是有效的服务器端。还是你做纯粹的客户端表单验证?
  • @trane 我在帖子中添加了关于客户端验证的提示。
  • 是的,我想在客户端进行验证。猜猜我在最初的帖子中没有说得足够清楚。在客户端执行此操作的原因是验证应该在模式对话框中进行。如果验证失败,则不应关闭对话框。明天我会仔细看看你最新添加的内容。
  • @trane 没有理由在客户端执行此操作-您可以通过 AJAX 在服务器端执行此操作,并在验证失败时防止对话框关闭(javaScript 变量 validationFailed 为真,那么谢谢到b:fetchBeanInfos 组件)。查看我的编辑 - 我使它与您的示例代码匹配。
猜你喜欢
  • 1970-01-01
  • 2011-12-21
  • 1970-01-01
  • 1970-01-01
  • 2018-02-20
  • 2016-03-29
  • 1970-01-01
  • 2012-02-18
  • 1970-01-01
相关资源
最近更新 更多