3

我有一个表单,其中包含用户用价格(数字)填充的输入字段列表。我已将他们的 css 类设置为“必需”和“数字”,以便 jQuery 验证插件相应地验证它们。所有这些都运行良好。当每个字段不是数字或缺少值等时会显示错误。

整个表单实际上位于 nyroModal(jQuery 插件)模型弹出窗口中。但这不重要,它只是一个 .aspx 网络表单。其中,我还使用了一个 UpdatePanel 并将所有内容都放入其中,因为我的表单本质上是一个 2 阶段过程。用户必须在表单的第一个“页面”上完成一些基本步骤。当验证并工作时,我只是在 UpdatePanel 中隐藏/显示一些元素,以向用户显示表单的下一个“页面”,即如上所述的所有价格文本框输入字段。

我使用 ImageButton 作为验证表单的触发点。默认情况下,如果您只保留 ImageButton 的原样,.Net 将触发回发,在我的情况下是 AJAX 回发,因为它全部发生在 UpdatePanel 中。这又是需要的。出于明显的原因,我不想要丑陋的完整回发。

经过大量阅读后,我需要一种在 javascript 中附加到 .Net 的 PageRequestManager 的方法,以便我可以根据 jQuery 是否成功验证表单来拦截 .Net 想要进行回发的时间。所以我的逻辑是:默认情况下,不允许回发,但是当 jQuery 成功验证表单时,设置一个变量表示现在允许回发,然后下次回发尝试发生时,它将通过。因此向用户显示成功。

这一切都运行得相当好,但还有一个最后一个问题。

jQuery 验证插件的 validate({success}) 选项似乎在每个单独的字段验证成功后被错误地触发,而不是整个表单。即,如果我在任何一个价格输入字段中输入一个数字,此成功选项将触发并将我的 cancelPostback 变量设置为 false,这反过来意味着表单现在提交,即使它尚未经过验证,只是因为一个字段是有效的。我本来希望这个 validate({success}) 选项只有在整个表单被验证后才会触发。

我是否错误地解释了这一点,实际上它在做它应该做的事情?如果是这样,我如何才能仅在验证整个表单时才将我的 cancelPostback 变量设置为 true?

非常感谢您提供任何见解或提醒。

我实现验证并拦截 .Net 回发事件的 jQuery 代码如下:

<script type="text/javascript">
    // By default, don't allow Postback until we've successfully validated our form on the client-side.
    var cancelPostback=true;

    // Every single time the page loads, including every single AJAX partial postback
    function pageLoad()
    {
        // Reset the value to say that "We don't allow Postbacks at this stage"..
        cancelPostback=true;

        // Attach client-side validation to the main form
        $("#<%= form1.ClientID %>").validate({ success: function() { alert('validation succeeded!'); cancelPostback = false; } });

        // Grab a reference to the Page Request Manager
        var prm = Sys.WebForms.PageRequestManager.getInstance();
        prm.add_initializeRequest(onEachRequest);

        alert("Page Load");
    }

    // Our own custom method to be attached to each new/future page request..
    function onEachRequest(sender, args)
    {
        alert("About to cancel? " + cancelPostback);
        // Check to see if we need to Cancel this Postback based on Conditional Logic within this page..
        args.set_cancel(cancelPostback);
    }
</script>
4

3 回答 3

3

我的解决方案有问题,因为除了 IE 之外的所有浏览器都在 jQuery 验证器的 submitHandler() 函数之前触发了“onEachRequest”函数。我想出了一个更优雅的解决方案,如果验证失败,它会简单地取消回发,而不是依赖预设变量。

  Sys.Application.add_init(function() {
    var prm = Sys.WebForms.PageRequestManager.getInstance();
    prm.add_initializeRequest(onEachRequest);
  }); 

  function onEachRequest(sender, args) {
    if (args.get_postBackElement().id == <%= [YourSubmitButton].ClientID %>) {
      args.set_cancel(!$('#aspnetForm').valid());
    }
  }
于 2010-06-30T16:02:09.203 回答
1

感谢 heaps tvanfosson 的及时帮助。

好的更新:

我关注了越来越多的链接,最终找到了“成功”的文档。插件自己主页上的文档很糟糕,并且省略了许多关键功能:) 但在官方 jQuery 页面上它“更好”。“成功”选项旨在每次成功验证单个字段时触发。所以这是按设计工作的,我错误地假设它只会在整个表单有效时触发。

我试过你的 invalidHandler 想法。我喜欢这个主意。我遇到的一个问题是 ImageButton 的回发仍然会首先触发,因此它会在 invalidHandler 代码运行之前开始回发。所以回发仍然会继续,然后,invalidHandler 将禁用未来的回发,不幸的是它们以错误的顺序触发。但除此之外,它还显示出完美解决方案的所有其他迹象。

然后我又尝试了 submitHandler 方式,即相反的方式。再次,这遇到了一些顺序问题,因为回发会再次首先触发,但被阻止,然后 submitHandler 将允许以后的回发,但已经太晚了,所以这个回发被错过了。您必须再次单击该按钮两次才能启动它。

所以最终的半杂乱无章的解决方案,说实话还不错,是:

我将此行更改为: // 将客户端验证附加到主表单 $("#<%= form1.ClientID %>").validate({ submitHandler: function() { PreventPostback = false; __doPostBack('UpdatePanel1' , ''); } });

如您所见,它首先切换了 PreventPostback 变量,然后手动触发了新的回发,因为第一次回发已经被阻止并终止了。因此,此手动 __doPostBack 调用可确保根据 PreventPostback 的新值触发新的回发。

我从 ImageButtons 后面删除了事件方法,并在服务器端代码中创建了一个名为“DoPostBackLogic()”的新方法,该方法仅在页面回发时调用,我知道这一定来自此验证逻辑,因为那是我的表单上唯一可能发生的回发。然后所有的隐藏/显示/保存逻辑都在那里发生。这意味着当我手动调用 __doPostBack 时,我可以简单地使用 UpdatePanel 的 ID,而不必担心模仿特定的 ImageButton 等。

这样它就可以完美地工作。默认情况下禁用回发,当表单有效时,允许回发,但随后手动触发回发以使新值生效。

所以这基本上是您的第二个解决方案,再次感谢您的聆听和分享!:)

于 2009-05-12T04:55:18.753 回答
1

我建议查看 submitHandler 和 invalidHandler 选项。一个或另一个应该为你想要的工作。我认为最好的方法是默认允许回发,并在 invalidHandler 中将 cancelPostback 设置为 true。或者,您可以编写自己的 submitHandler 直接调用 __doPostBack 并通过 ImageButton 替换提交。

于 2009-05-12T02:27:59.493 回答