【问题标题】:jQuery Validation - Multiple submit buttons on one asp.net form, different validation groups?jQuery Validation - 一个 asp.net 表单上的多个提交按钮,不同的验证组?
【发布时间】:2010-12-08 20:14:14
【问题描述】:

我有一个带有登录部分和注册部分的 asp.net 表单。有两个提交按钮对应于相应的部分,登录或注册。我正在使用 jquery 验证,但是我找不到像使用普通 asp.net 验证那样指定验证组的方法。当我点击注册按钮时,现在它要求填写登录字段。有人对此有任何想法吗?谢谢!

【问题讨论】:

    标签: asp.net jquery validation


    【解决方案1】:

    我猜你正在使用这个验证插件:JQuery Validation。该插件使用表单标记作为验证组,因此要完成您想要的操作,您需要根据用户按下的按钮删除规则。此外,您需要为验证失败然后用户决定单击另一个按钮的情况添加规则。

    这是一个例子:

    $(document).ready(function()
    {
        $("#form").validate({
            invalidHandler: addRules 
        });        
    
        addRules();        
    
        $("#submit1").click(function(){
            $(".group2").each(function(){
                $(this).rules("remove");
            });
        });
        $("#submit2").click(function(){
            $(".group1").each(function(){
                $(this).rules("remove");
            });
        });
    
    });
    var addRules = function(){
        $("#input1").rules("add", {required:true});
        $("#input2").rules("add", {required:true});
    }
    

    这种方法允许您为每个输入添加一个类属性(group1 或 group2),作为验证组。

    【讨论】:

    • 要是这么简单就好了。在 asp.net 中,您可能只有一个
      标记。因此,我需要知道是否有validationgroups(正常的asp.net验证使用)之类的东西。
    • @Jataro 你知道如何为一个提交按钮禁用 jquery 验证吗?我的表单上有两个提交按钮:提交和取消。我需要禁用“取消”按钮的验证。
    【解决方案2】:

    您可以使用以下库,而不必编写特定于页面的代码来解决此问题:

    https://github.com/bbraithwaite/JQueryValidationForWebForms

    NB 源代码在下方,但 Github 链接将始终具有最新的源代码。

    它位于 jQuery Validation Framework 之上,并通过使用类名作为约定来抽象出这个问题。

    您注册验证事件的方式与 jQuery 验证相同(只是名称不同):

    $(function() {
        $("#aspForm").validateWebForm();
    });
    

    .ASPX 示例

    具有两个验证组的基本 .aspx 示例可能如下所示。您只需包装每个逻辑部分并给它一个“form”类名,并在应该触发验证事件的操作上添加类“submit”:

     <fieldset class="form">
     <div class="something">
     <ul></ul>
     </div>
     <legend>Sign Up</legend>
     <p>
     <asp:Label ID="uiFirstName" runat="server" AssociatedControlID="uxFirstName" Text="First name:"></asp:Label>
     <asp:TextBox ID="uxFirstName" runat="server" CssClass="required"></asp:TextBox>
     </p>
     <p>
     <asp:Button ID="uxRegister" runat="server" Text="Sign Up" CssClass="submit signup" />
     <asp:Button ID="uxCancelRegister" runat="server" Text="Cancel" />
     </p>
     </fieldset>
     <fieldset class="form">
     <legend>Login</legend>
     <p>
     <asp:Label ID="uiUserName" runat="server" AssociatedControlID="uxUserName" Text="User name:"></asp:Label>
     <asp:TextBox ID="uxUserName" runat="server" CssClass="required email"></asp:TextBox>
     </p>
     <p>
     <asp:Button ID="uxLogin" runat="server" Text="Login" CssClass="submit login" />
     <asp:Button ID="uxCancelSignUp" runat="server" Text="Cancel" />
     </p>
     </fieldset>
    

    源代码

    (function ($) {
    
        $.extend($.fn, {
            validateWebForm: function (options) {
    
                var form = $(this[0]),
                    formExists = (form.length) && form.is('form');
    
                if (formExists) {
                    if (!options) {
                        options = {};
                    }
    
                    // stop the validation from firing on the form submit
                    options.onsubmit = false;
    
                    // wire up the default jquery validation event to the form
                    this.validate(options);
    
                    // Select any input[type=text] elements within a validation group
                    // and attach keydown handlers to all of them.
                    $('.form :text').keydown(function (event) {
                        // Only execute validation if the key pressed was enter.
                        if (event.keyCode == 13) {
                            $(event.currentTarget).closest(".form").find(".submit").click();
                        }
                    });
    
                    // find the submit buttons and override the click event
                    form.getSumbitControls().click(this.validateAndSubmit);
    
                    return this;
                }
    
                return undefined;
            },
            getSumbitControls: function () {
                return $(this).find('.form .submit');
            },
            getValidationContainer: function (submitControl) {
                return $(submitControl).closest('.form');
            },
            validateAndSubmit: function (event) {
                // Ascend from the button that triggered this click event 
                // until we find a container element flagged with 
                // .validationGroup and store a reference to that element.
                var group = $(this).getValidationContainer(event.currentTarget),
                    isValid = true;
    
                // Descending from that .form element, find any input
                // elements within it, iterate over them, and run validation on 
                // each of them.
                group.find(':input').each(function (i, item) {
                    if (!$(item).valid()) {
                        isValid = false;
                    }
                });
    
                // If any fields failed validation, prevent the button's click 
                // event from triggering form submission.
                if (!isValid) {
                    event.preventDefault();
                }
            }
        });
    
    })(jQuery);
    

    Nuget 用户

    PM> 安装包 JQuery.Validation.WebForms

    这是从阅读 Dave Ward 的以下帖子演变而来的:

    http://encosia.com/asp-net-webforms-validation-groups-with-jquery-validation/

    【讨论】:

      【解决方案3】:

      您始终可以使用一些简单的 jquery/javascript 来删除 asp 按钮 OnClientClick 上的“validate[required]”类,然后将其重新添加到其他按钮 OnClientClick 上,这比更改验证引擎文件或替换它们更容易。这方面的一个例子是:

      <div id="Login">
          <asp:TextBox ID="txtUser" runat="server" CssClass="validate[required]"></asp:TextBox>
          <asp:TextBox ID="txtPass" runat="server" CssClass="validate[required]"></asp:TextBox>
          <asp:Button ID="btnLogin" runat="server" OnClientClick="disableReg();" OnClick="btnLogin_Click" />
      </div>
      <div id="Register">
          <asp:TextBox ID="txtName" runat="server" CssClass="validate[required]"></asp:TextBox>
          <asp:TextBox ID="txtEmail" runat="server" CssClass="validate[required]"></asp:TextBox>
          <asp:Button ID="btnReg" runat="server" OnClientClick="disableLogin();" OnClick="btnReg_Click" />
      </div>
      

      javascript 将是:

      function disableReg() {
          $('#<%=txtName.ClientID%>').removeClass("validate[required]");
          $('#<%=txtEmail.ClientID%>').removeClass("validate[required]");
          $('#<%=txtUser.ClientID%>').addClass("validate[required]");
          $('#<%=txtPass.ClientID%>').addClass("validate[required]");
          return true;
      }
      
      function disableLogin() {
          $('#<%=txtUser.ClientID%>').removeClass("validate[required]");
          $('#<%=txtPass.ClientID%>').removeClass("validate[required]");
          $('#<%=txtName.ClientID%>').addClass("validate[required]");
          $('#<%=txtEmail.ClientID%>').addClass("validate[required]");
          return true;
      }
      

      【讨论】:

        【解决方案4】:

        跟踪验证对象并直接删除/替换规则。适用于 v1.13.0

        var validation = $('#form1').validate(); //Keep track of validation object
        
        //Rule set 1
        var validationRulesLogin = {
            headerEmail: {
                required: true,
                email: true
            },
            headerPassword: "required"
        };
        var validationMessagesLogin = {
            headerEmail: {
                required: "Please enter your email address.",
                email: "Not a valid email address."
            },
            headerPassword: "Please enter your password."
        };
        
        //Rule set 2
        var validationRulesSignup = {
            signupEmail: {
                required: true,
                email: true
            },
            signupPassword: "required",
            signupPassword2: {
                equalTo: "#phBody_txtNewPassword"
            }
        };
        var validationMessagesSignup = {
            signupEmail: {
                required: "Please enter your email address.",
                email: "Not a valid email address."
            },
            signupPassword: "Please enter your password.",
            signupPassword2: "Passwords are not the same."
        };
        
        //Toggle rule sets on form focus, button click or other event.
        function validatingLoginForm(){
            validation.resetForm();
            validation.settings.rules = validationRulesLogin;
            validation.settings.messages = validationMessagesLogin;
        }
        function validationSignupForm(){
            validation.resetForm();
            validation.settings.rules = validationRulesSignup;
            validation.settings.messages = validationMessagesSignup;
        }
        

        【讨论】:

          【解决方案5】:

          如果您使用不显眼的 jquery 验证,或者您可以使用这个:

          $(document).ready(function () {
          
              var formValidator = $("form").validate();
          
              $("#btnLogin").click(function () {
                  formValidator.settings.ignore = "#registerSection *";
              });
          
              $("#btnRegister").click(function () {
                  formValidator.settings.ignore = "#loginSection *";
              });
          });
          

          【讨论】:

            【解决方案6】:

            通过将特殊的 CSS 类名称附加到代表服务器端验证控件的 HTML 元素上,使 ASP.NET 服务器验证逻辑可用于客户端/jQuery。

            生成的 CSS 类名称将代表验证组。因此,例如,某些文本框将被标记为一个验证组的类名,而其他文本框将被标记为不同的验证组。

            例如,在页面 PreRender 处理程序中或在渲染页面之前编写并调用此 C# 函数,以便为服务器控件注入特殊的 CSS。

            /// <summary>
            /// Makes the server validation logic knowledge available to the client side
            /// by appending css class names to validators and html elements being validated.
            /// The generated css classes can be targeted by jQuery in the DOM.
            /// </summary>
            /// <param name="cssPrefixValidator">prefix string for validator css names</param>
            /// <param name="cssPrefixTarget">prefix string for target element css names</param>
            /// <remarks>
            /// The css prefix arguments to this function help distinguish between what is a 
            /// validation control and what is an html element being targeted by said validation control.
            /// </remarks>
            /// 
            void TagValidationWithCss(string cssPrefixValidator, string cssPrefixTarget) {
            
                List<string> valClasses = new List<string>();
                List<string> targetClasses = new List<string>();
            
                // iterate over validator server controls
                foreach (BaseValidator val in Page.Validators) {
            
                    // keep a unique list of generated validator css class names
                    string classnameVal = cssPrefixValidator + val.ValidationGroup;
                    if (!valClasses.Contains(classnameVal))
                        valClasses.Add(classnameVal);
                    // ..and mark the validator element with the generated css class name
                    val.CssClass += (string.IsNullOrEmpty(val.CssClass) ? "" : " ") + classnameVal;
            
                    // keep a unique list of generated target element css class names
                    string classnameTarg = cssPrefixTarget + val.ValidationGroup;
                    if (!targetClasses.Contains(classnameTarg))
                        targetClasses.Add(classnameTarg);
                    // ..and mark the target element with the generated css class name
                    Control target = FindControl(val.ControlToValidate);
                    if (target is HtmlControl)
                        ((HtmlControl)target).Attributes["class"] += (string.IsNullOrEmpty(val.CssClass) ? "" : " ") + classnameTarg;
                    else if (target is WebControl)
                        ((WebControl)target).CssClass += (string.IsNullOrEmpty(val.CssClass) ? "" : " ") + classnameTarg;
                }
            
                // output client script having array of validator css names representing validation groups
                string jscriptVal = string.Format("<script>window['{1}'] = ['{0}'];</script>", string.Join("','", valClasses.ToArray()), cssPrefixValidator);
                ClientScript.RegisterStartupScript(this.GetType(), "val", jscriptVal);
            
                //output client script having array of html element class names representing validation groups
                string jscriptTarg = string.Format("<script>window['{1}'] = ['{0}'];</script>", string.Join("','", targetClasses.ToArray()), cssPrefixTarget);
                ClientScript.RegisterStartupScript(this.GetType(), "targ", jscriptTarg);
            }
            

            该函数在服务端Page中调用:

            protected override void OnPreRender(EventArgs e) {
                base.OnPreRender(e);
            
                TagValidationWithCss("validator-", "target-");
            }
            

            ASPX 页面的声明性语法可能有两个部分,如下所示:

            <div>
            
            Login Section
                <asp:TextBox ValidationGroup="vg1" ID="TextBox1" runat="server"></asp:TextBox><asp:TextBox
                    ValidationGroup="vg1" ID="Textbox2" runat="server"></asp:TextBox><asp:Button ID="Button1"
                        ValidationGroup="vg1" runat="server" Text="Button" />
                <asp:RequiredFieldValidator ID="RequiredFieldValidator3" runat="server" ControlToValidate="TextBox1"
                    ErrorMessage="RequiredFieldValidator" ValidationGroup="vg1"></asp:RequiredFieldValidator>
                <asp:RequiredFieldValidator ID="RequiredFieldValidator4" runat="server" ControlToValidate="Textbox2"
                    ErrorMessage="RequiredFieldValidator" ValidationGroup="vg1"></asp:RequiredFieldValidator>
            
                <hr />
            
            Registration Section
                <asp:TextBox ValidationGroup="vg2" ID="TextBox4" runat="server"></asp:TextBox><asp:TextBox
                    ValidationGroup="vg2" ID="Textbox5" runat="server"></asp:TextBox><asp:Button ID="Button3"
                        ValidationGroup="vg2" runat="server" Text="Button" />
            </div>
            

            现在转到渲染页面查看结果.....

            页面 HTML 源代码包含一组生成的 CSS 名称表示验证组,一组用于验证器 (validator-),另一组用于验证目标 (target-)

            <script>window['validator-'] = ['validator-vg1','validator-vg2'];</script>
            <script>window['target-'] = ['target-vg1','target-vg2'];</script> 
            

            这些 CSS 名称也会呈现在 html 元素上。注意此处文本框上的“target-vg1”CSS 类,代表验证组 #1。文本框代表页面上的登录屏幕/界面(两个 UI 部分之一):

            <input name="TextBox1" type="text" id="TextBox1" class=" target-vg1" /><input name="Textbox2" type="text" id="Textbox2" class=" target-vg1" /><input type="submit" name="Button1" value="Button" onclick="javascript:WebForm_DoPostBackWithOptions(new WebForm_PostBackOptions(&quot;Button1&quot;, &quot;&quot;, true, &quot;vg1&quot;, &quot;&quot;, false, false))" id="Button1" /> 
            

            第二组文本框位于同一个 ASP.NET 页面(在同一个 ASP.NET 表单中),代表用户注册屏幕/界面(第二个 UI 部分)。请注意,这些文本框通过 css 类使用名为“target-vg2”的不同验证组进行标记。

             <input name="TextBox4" type="text" id="TextBox4" class=" target-vg2" /><input name="Textbox5" type="text" id="Textbox5" class=" target-vg2" /><input type="submit" name="Button3" value="Button" onclick="javascript:WebForm_DoPostBackWithOptions(new WebForm_PostBackOptions(&quot;Button3&quot;, &quot;&quot;, true, &quot;vg2&quot;, &quot;&quot;, false, false))" id="Button3" /> 
            

            因此,我们将特殊的 Css 名称注入到 ASP.NET 流中,而不会中断或破坏它。

            最终,这个专门的输出允许您针对它编写自定义脚本(即使用 jQuery)来获取那些特殊的 CSS 类名称并区分客户端的验证组。

            这个简单的示例会提醒客户端验证组的名称,以证明它们被看到和知道。哇!

            <script>
                // Tell the CSS names of the available validation groups assigned to target elements.
                var strGroups = 'css validation groups are: ' + window['target-'].join(', ');
                alert(strGroups);
            </script>
            

            jQuery 也可以用来定位特殊的 css 类。

            这并不涵盖所有情况。它可能真的出去吃午饭,但做起来很有趣。服务器端和客户端代码需要根据个人或项目的喜好进行调整。

            (您还希望依靠这样一个事实,即较新的浏览器可以使用“class”属性将多个 CSS 类应用于一个元素,方法是使用空格分隔类名,例如 - class="vg1 animated bright myclass your class"。这允许生成的 css 类名将附加在现有类名之后而不覆盖它们。)

            【讨论】:

            • 方式方式太复杂了。我什至不想为如此简单但不需要复杂的东西考虑服务器端代码。
            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2019-08-23
            • 1970-01-01
            • 2012-07-13
            • 2013-08-25
            • 1970-01-01
            • 2017-04-28
            • 2014-12-11
            相关资源
            最近更新 更多