jQuery Validation - 一个 asp.net 表单上的多个提交按钮,不同的验证组?

Posted

技术标签:

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

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

【问题讨论】:

【参考方案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 类名将附加在现有类名之后而不覆盖它们。)

【讨论】:

方式方式太复杂了。我什至不想为如此简单但不需要复杂的东西考虑服务器端代码。

以上是关于jQuery Validation - 一个 asp.net 表单上的多个提交按钮,不同的验证组?的主要内容,如果未能解决你的问题,请参考以下文章

jquery-validation JQ 表单验证

如何在 jQuery.validation 中添加不等于规则

jQuery 插件 validation

jquery.validation .netCore 6

jquery.validation校验

jquery-validation 使用