jquery.validate失去了阿贾克斯更换和只显示最后的错误 [英] jquery.validate lost on ajax replacement and only showing last error

本文介绍了jquery.validate失去了阿贾克斯更换和只显示最后的错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用MVC 2 MicrosoftMvcJQueryValidation jquery.validate。我有,然后被翻译成jQuery的验证我的模型数据注解。我使用由<作为一个概述了修改MicrosoftMvcJQueryValidation href=\"http://geekswithblogs.net/stun/archive/2010/02/27/asp.net-mvc-client-side-validation-summary-with-jquery-validation-plugin.aspx\"相对=nofollow>梭吞来让我的错误信息出现在验证摘要,而不是控制旁边。

I am using jquery.validate in MVC 2 with MicrosoftMvcJQueryValidation. I have data annotations on my model which is then being translated into jquery validators. I am using a modification to MicrosoftMvcJQueryValidation as outlined by Soe Tun to allow my error messages to appear in a validation summary instead of beside the controls.

在页面加载后,一切正常。问题是,我使用ajax的形式和替换模式改写形式。当我这样做,我失去了我所有的客户端验证的。

When the page loads, everything works as expected. The problem is that I am using ajax forms with replace mode to rewrite the form. When I do this, I lose all of my client side validation.

验证仍然发生服务器端,并有错误的字段正确报错CSS类来改变自己的风格。然而,被显示在我的验证摘要只有最后一条错误消息。

Validation still happens server side, and the fields that have errors are correctly being given the css classes to change their style. However, only the last error message is being shown in my validation summary.

该控制器是没有什么特别的。如果该模型是有效的,做的工作,否则返回相同的模型回视图。

The controller isn't anything special. If the model is valid, do work, otherwise return the same model back into the view.

下面是我的ajax形式的样本

Here's a sample of my ajax form

<% using (Ajax.BeginForm("AddCreditCard", "Dashboard",
       new { },
       new AjaxOptions() { 
           HttpMethod = "Post",
           InsertionMode = InsertionMode.Replace,
           UpdateTargetId = "quickpay-wrapper",
           OnSuccess = "newPaymentSetup",
           LoadingElementId = "loading-pane"
            }, new { id="new-credit-card-form" })) { %>

下面是修改后的JavaScript。

Here is the modified javascript.

jQuery.validator.addMethod("regex", function(value, element, params) {
    if (this.optional(element)) {
        return true;
    }

    var match = new RegExp(params).exec(value);
    return (match && (match.index == 0) && (match[0].length == value.length));
});

// glue

function __MVC_ApplyValidator_Range(object, min, max) {
    object["range"] = [min, max];
}

function __MVC_ApplyValidator_RegularExpression(object, pattern) {
    object["regex"] = pattern;
}

function __MVC_ApplyValidator_Required(object) {
    object["required"] = true;
}

function __MVC_ApplyValidator_StringLength(object, maxLength) {
    object["maxlength"] = maxLength;
}

function __MVC_ApplyValidator_Unknown(object, validationType, validationParameters) {
    object[validationType] = validationParameters;
}

function __MVC_CreateFieldToValidationMessageMapping(validationFields) {
    var mapping = {};

    for (var i = 0; i < validationFields.length; i++) {
        var thisField = validationFields[i];
        mapping[thisField.FieldName] = "#" + thisField.ValidationMessageId;
    }

    return mapping;
}

function __MVC_CreateErrorMessagesObject(validationFields) {
    var messagesObj = {};

    for (var i = 0; i < validationFields.length; i++) {
        var thisField = validationFields[i];
        var thisFieldMessages = {};
        messagesObj[thisField.FieldName] = thisFieldMessages;
        var validationRules = thisField.ValidationRules;

        for (var j = 0; j < validationRules.length; j++) {
            var thisRule = validationRules[j];
            if (thisRule.ErrorMessage) {
                var jQueryValidationType = thisRule.ValidationType;
                switch (thisRule.ValidationType) {
                    case "regularExpression":
                        jQueryValidationType = "regex";
                        break;

                    case "stringLength":
                        jQueryValidationType = "maxlength";
                        break;
                }

                thisFieldMessages[jQueryValidationType] = thisRule.ErrorMessage;
            }
        }
    }

    return messagesObj;
}

function __MVC_CreateRulesForField(validationField) {
    var validationRules = validationField.ValidationRules;

    // hook each rule into jquery
    var rulesObj = {};
    for (var i = 0; i < validationRules.length; i++) {
        var thisRule = validationRules[i];
        switch (thisRule.ValidationType) {
            case "range":
                __MVC_ApplyValidator_Range(rulesObj,
                    thisRule.ValidationParameters["minimum"], thisRule.ValidationParameters["maximum"]);
                break;

            case "regularExpression":
                __MVC_ApplyValidator_RegularExpression(rulesObj,
                    thisRule.ValidationParameters["pattern"]);
                break;

            case "required":
                var fieldName = validationField.FieldName.replace(".", "_");
                if ($("#" + fieldName).get(0).type !== 'checkbox') {
                    // only apply required if the input control is NOT a checkbox.
                    __MVC_ApplyValidator_Required(rulesObj);
                }
                break;

            case "stringLength":
                __MVC_ApplyValidator_StringLength(rulesObj,
                    thisRule.ValidationParameters["maximumLength"]);
                break;

            default:
                __MVC_ApplyValidator_Unknown(rulesObj,
                    thisRule.ValidationType, thisRule.ValidationParameters);
                break;
        }
    }

    return rulesObj;
}

function __MVC_CreateValidationOptions(validationFields) {
    var rulesObj = {};
    for (var i = 0; i < validationFields.length; i++) {
        var validationField = validationFields[i];
        var fieldName = validationField.FieldName;
        rulesObj[fieldName] = __MVC_CreateRulesForField(validationField);
    }

    return rulesObj;
}

function __MVC_EnableClientValidation(validationContext) {
    // this represents the form containing elements to be validated
    var theForm = $("#" + validationContext.FormId);

    var fields = validationContext.Fields;
    var rulesObj = __MVC_CreateValidationOptions(fields);
    var fieldToMessageMappings = __MVC_CreateFieldToValidationMessageMapping(fields);
    var errorMessagesObj = __MVC_CreateErrorMessagesObject(fields);

    var options = {
        errorClass: "input-validation-error",
        errorElement: "span",
        errorPlacement: function(error, element) {
            var messageSpan = fieldToMessageMappings[element.attr("name")];
            $(messageSpan).empty();
            $(messageSpan).removeClass("field-validation-valid");
            $(messageSpan).addClass("field-validation-error");
            error.removeClass("input-validation-error");
            error.attr("_for_validation_message", messageSpan);
            error.appendTo(messageSpan);
        },
        messages: errorMessagesObj,
        rules: rulesObj,
        success: function(label) {
            var messageSpan = $(label.attr("_for_validation_message"));
            $(messageSpan).empty();
            $(messageSpan).addClass("field-validation-valid");
            $(messageSpan).removeClass("field-validation-error");
        }
    };

    var validationSummaryId = validationContext.ValidationSummaryId;
    if (validationSummaryId) {
        // insert an empty <ul> into the validation summary <div> tag (as necessary)
        $("<ul />").appendTo($("#" + validationSummaryId + ":not(:has(ul:first))"));

        options = {
            errorContainer: "#" + validationSummaryId,
            errorLabelContainer: "#" + validationSummaryId + " ul:first",
            wrapper: "li",

            showErrors: function(errorMap, errorList) {
                var errContainer = $(this.settings.errorContainer);
                var errLabelContainer = $("ul:first", errContainer);

                // Add error CSS class to user-input controls with errors
                for (var i = 0; this.errorList[i]; i++) {
                    var element = this.errorList[i].element;
                    var messageSpan = $(fieldToMessageMappings[element.name]);
                    var msgSpanHtml = messageSpan.html();
                    if (!msgSpanHtml || msgSpanHtml.length == 0) {
                        // Don't override the existing Validation Message.
                        // Only if it is empty, set it to an asterisk.
                        //messageSpan.html("*");
                    }
                    messageSpan.removeClass("field-validation-valid").addClass("field-validation-error");
                    $("#" + element.id).addClass("input-validation-error");
                }
                for (var i = 0; this.successList[i]; i++) {
                    // Remove error CSS class from user-input controls with zero validation errors
                    var element = this.successList[i];
                    var messageSpan = fieldToMessageMappings[element.name];
                    $(messageSpan).addClass("field-validation-valid").removeClass("field-validation-error");
                    $("#" + element.id).removeClass("input-validation-error");
                }

                if (this.numberOfInvalids() > 0) {
                    errContainer.removeClass("validation-summary-valid").addClass("validation-summary-errors");
                }

                this.defaultShowErrors();

                // when server-side errors still exist in the Validation Summary, don't hide it
                var totalErrorCount = errLabelContainer.children("li:not(:has(label))").length + this.numberOfInvalids();
                if (totalErrorCount > 0) {
                    $(this.settings.errorContainer).css("display", "block").addClass("validation-summary-errors").removeClass("validation-summary-valid");
                    $(this.settings.errorLabelContainer).css("display", "block");
                }
            },
            messages: errorMessagesObj,
            rules: rulesObj
        };
    }

    // register callbacks with our AJAX system
    var formElement = document.getElementById(validationContext.FormId);
    var registeredValidatorCallbacks = formElement.validationCallbacks;
    if (!registeredValidatorCallbacks) {
        registeredValidatorCallbacks = [];
        formElement.validationCallbacks = registeredValidatorCallbacks;
    }
    registeredValidatorCallbacks.push(function() {
        theForm.validate();
        return theForm.valid();
    });

    theForm.validate(options);
}

// need to wait for the document to signal that it is ready
$(document).ready(function() {
    var allFormOptions = window.mvcClientValidationMetadata;
    if (allFormOptions) {
        while (allFormOptions.length > 0) {
            var thisFormOptions = allFormOptions.pop();
            __MVC_EnableClientValidation(thisFormOptions);
        }
    }
}); 

我试过移动在文件准备进入我的onSuccess方法底部的电话,但没有做到这一点。

I've tried moving the calls at the bottom in the document ready into my OnSuccess method, but that didn't do it.

所以,我如何获得客户端验证,当我做重新初始化我的AJAX替代,以及如何得到我所有的错误在验证摘要说明了什么?我希望,如果我解决一个问题,它会纠正对方。

So, how do I get client side validation to reinitialize when I do my ajax replace, and how do I get all my errors to show in the validation summary? I'm hoping that if I fix one issue, it will correct the other.

编辑:

下面是一些更多的信息约我在做什么。

Here's a little more info about what I am doing

下面是包装

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<QuickPayModel>" %>

<div id="quickpay-wrapper">
<% if (Model.NewPaymentMethod) { %>
    <% Html.RenderAction<DashboardController>(x => x.QuickPayNewMethod()); %>
<% } else { %>
    <% Html.RenderPartial("QuickPayMakePayment", Model); %>
<% } %>
</div>

下面是付款面板。

<%= Html.ClientValidationSummary(new { id = "valSumContainer" })%>
<% Html.EnableClientValidation(); %>

<% using (Ajax.BeginForm("QuickPay", "Dashboard",
       new { },
       new AjaxOptions() { 
           HttpMethod = "Post",
           InsertionMode = InsertionMode.Replace,
           UpdateTargetId = "quickpay-wrapper",
           OnSuccess = "updatePaymentHistory",
           LoadingElementId = "loading-pane"
            }, new { }))
   { %>
    <div class="horizontalline"><%= Html.Spacer() %></div>
    <% ViewContext.FormContext.ValidationSummaryId = "valSumContainer"; %>

    <p>
    <%: Html.LabelFor(x => x.PaymentMethods)%>

    <% if (Model.HasOnePaymentMethod) { %>
            <%: Html.DisplayFor(x => x.SelectedPaymentMethodName) %>
            <%: Html.HiddenFor(x => x.SelectedPaymentMethodId) %>

    <% } else { %>
        <%: Html.DropDownListFor(x => x.SelectedPaymentMethodId, Model.PaymentMethodsSelectList, "Select a Payment Method", new { })%>
            <%: Html.HiddenFor(x => x.SelectedPaymentMethodName)%>
        <script type="text/javascript">
            $(function () {
                $("#PaymentMethods").change(function () {
                    $("#SelectedPaymentMethodId").val($(this).val());

                    $("#SelectedPaymentMethodName").val($('option:selected', this).text());
                });
            });
        </script>

    <% } %>
    <%: Html.Spacer(12, 1) %><%: Ajax.ActionLink("New Payment Method", "QuickPayNewMethod", 
                                 new AjaxOptions() { InsertionMode = InsertionMode.Replace,
                                                     UpdateTargetId = "quickpay-wrapper",
                                                     OnSuccess = "newPaymentSetup",
                                                     LoadingElementId = "loading-pane"
                                 })%> 
    <%: Html.ValidationMessageFor(x => x.SelectedPaymentMethodId)%>

    </p>

    <p>
    <%: Html.LabelFor(x => x.Amount)%>
    <%: Html.TextBoxFor(x => x.Amount, new { disabled = Model.UseInvoicing ? "disabled" : String.Empty, 
    title = Model.UseInvoicing ? "the total payment amount of all selected invoices" : String.Empty,
    @class = "small" })%>
    <%: Html.ValidationMessageFor(x => x.Amount)%>
    </p>

    <p>
    <%: Html.LabelFor(x => x.PayDate)%>
    <%: Html.TextBox("PayDate", Model.PayDate.ToShortDateString(), new { @class = "medium" })%>
    <%: Html.ValidationMessageFor(x => x.PayDate)%>
    </p>

    <script type="text/javascript">
        $(function () {
            quickPaySetup();
        });
    </script>

    <div class="horizontalline"><%= Html.Spacer() %></div>
    <%= FTNI.Controls.Submit("Submit Payment") %>
    <%: Html.AntiForgeryToken() %>

    <%: Html.ValidationMessage("Payment-Result")%>
<% } %>

现在我的新的付款方式面板

And now my new payment method panel

<script type="text/javascript">
    $(function () {
        newPaymentSetup();
    });
    </script>

    <h4>New Payment Method</h4> 

    <% if(Model.HasPaymentMethods) { %>
        <span style="float:right;">
            <%: Ajax.ActionLink("Cancel", "QuickPay", 
                                 new AjaxOptions() { 
                                     HttpMethod = "Get",
                                     InsertionMode = InsertionMode.Replace,
                                     UpdateTargetId = "quickpay-wrapper",
                                     OnSuccess = "quickPaySetup",
                                     LoadingElementId = "loading-pane"
                                 })%>
        </span>
    <% } %>

    <div>Enter the information below to create a new payment method.</div><br />

    <%= Html.ClientValidationSummary(new { id = "valSumContainer" })%>
    <% Html.EnableClientValidation(); %>
<div id="new-payment-method-tabs">
    <ul>
        <li><a href="#new-credit-card">Credit Card</a></li>
        <li><a href="#new-ach">E-Check</a></li>
    </ul>
    <div id="new-credit-card">
        <% Html.RenderPartial("NewCreditCard", Model.CreditCardModel); %>
    </div>
    <div id="new-ach">
        <% Html.RenderPartial("NewACH", Model.ACHModel); %>
    </div>
</div>

每个形式开始了与像这样

Each form starts off with something like this

<% using (Ajax.BeginForm("AddCreditCard", "Dashboard",
       new { },
       new AjaxOptions() { 
           HttpMethod = "Post",
           InsertionMode = InsertionMode.Replace,
           UpdateTargetId = "quickpay-wrapper",
           OnSuccess = "newPaymentSetup",
           LoadingElementId = "loading-pane"
            }, new { id="new-credit-card-form" })) { %>
    <% ViewContext.FormContext.ValidationSummaryId = "valSumContainer"; %>

初​​始负载的作品。所有Ajax取代导致丢失的形式背景和不重新初始化,无论我做什么。该表格​​回发,验证发生服务器端。所有无效的字段被改变(添加CSS错误类),但在摘要中只显示最后一个错误。

Initial load works. Any ajax replaces cause the form context to be lost and not reinitialize no matter what I do. The form posts back, validation occurs server side. All invalid fields are changed (css error classes added), but only the last error is shown in the summary.

推荐答案

我要告诉你,我怎么没短短数天前。请看看到<一个href=\"http://stackoverflow.com/questions/4172319/inline-client-side-validation-with-mvc-and-jquery\">this问题了解详情。

I am going to tell you how I did just a few days ago. Please have a look to this question for details.

在我来说,我是表示一种使用jQuery的对话框内的Ajax调用的形式内容。当调用完成我刚刚更换了与内容的对话框的内容发送从控制器回来。

In my case I was showing the content of the form using an ajax call inside a jquery dialog. When the call complete I just replace the dialog content with the content sent back from the controller.

在我的问题描述,然后叫上文件准备init方法我已经修改了code中的微软脚本中。这应该为你的情况下工作太...

I have modified the code inside the Microsoft script as described in my question and then called the init method on document ready. This should work for your case too...

对于第二个错误(我怎么得到我所有的错误在验证摘要说明了什么?)我只是修改了code在你指的是相同的源岗位描述,并没有出现过任何问题。

For the second error (how do I get all my errors to show in the validation summary?) I have simply modified the code as described in the same source post you are referring to and did not experienced any problem.

希望它帮助!

这篇关于jquery.validate失去了阿贾克斯更换和只显示最后的错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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