jquery.validate.unobtruser không hoạt động với các phần tử được chèn động


99

Tôi đang làm việc với ASP.Net MVC3, cách dễ dàng hơn để sử dụng xác thực ứng dụng sẽ là kích hoạt jquery.validate.unobtrusive. Mọi thứ hoạt động tốt, đối với những thứ ngay từ máy chủ.

Nhưng khi tôi cố gắng đưa một số 'đầu vào' mới bằng javascript và tôi biết rằng tôi cần gọi $.validator.unobtrusive.parse()để gắn lại các xác thực. Tuy nhiên, tất cả các trường được tiêm động đó không hoạt động.

Thậm chí tệ hơn, tôi cố gắng liên kết thủ công bằng cách sử dụng jquery.validatevà nó cũng không hoạt động. Có suy nghĩ gì không?


1
Nếu bạn truy cập vào đây từ google, bạn có thể đang tìm câu trả lời của @Sundara Prabu vì những câu trả lời khác được ủng hộ ồ ạt đã cũ.
The Muffin Man

Câu trả lời:


65

Tôi đã tạo một tiện ích mở rộng cho thư viện jquery.validate.unobtrraction để giải quyết vấn đề này cho tình huống của tôi - nó có thể được quan tâm.

http://xhalent.wordpress.com/2011/01/24/applying-unobtrusing-validation-to-dynamic-content/


Tôi nghĩ tôi nên bình chọn câu trả lời của bạn là đúng. BTW, thư viện của bạn có hoạt động với MVC RC mới nhất không? hoặc họ chỉ sửa điều đó?
xandy

1
Khi sử dụng mã được liên kết ở trên, hãy đảm bảo bạn cập nhật mã để đưa mã vào nhận xét nếu không mã có thể bị hỏng. Cụ thể, thay đổi hai dòng bộ chọn để báo giá gấp đôi id.
Ryan O'Neill

1
Cuối cùng đã có thể làm cho điều này hoạt động cho kịch bản của tôi sau một số gỡ lỗi. Nó dường như không được chuyển vào bộ chọn đầu vào, mà là cha hoặc biểu mẫu của đầu vào, do lệnh gọi tới $.validator.unobtrusive.parse(). Ngoài ra, nó dường như chỉ thêm các quy tắc mới chứ không nhận cập nhật cho các quy tắc hiện có?
lambinator

5
Câu trả lời này ít nhất phải chứa xương gấu của bài đăng trên blog. Liên kết duy nhất câu trả lời nói chung là off topic cho SO
Liam

8
Mặc dù câu trả lời này đã hơn 3 năm tuổi nhưng sẽ cực kỳ hữu ích nếu bạn có thể đăng các phần quan trọng của câu trả lời ở đây, trên trang web này hoặc bài đăng của bạn có nguy cơ bị xóa. Xem Câu hỏi thường gặp trong đó đề cập đến các câu trả lời 'hầu như không nhiều hơn một liên kết '. Bạn vẫn có thể bao gồm liên kết nếu bạn muốn, nhưng chỉ như một 'tài liệu tham khảo'. Câu trả lời sẽ tự đứng mà không cần liên kết.
Taryn

159

Tôi đã thử cách tiếp cận của Xhalent nhưng tiếc là nó không hiệu quả với tôi. Cách tiếp cận của Robin có hiệu quả và không hiệu quả. Nó hoạt động hiệu quả đối với các phần tử được thêm động, nhưng nếu bạn cố gắng sử dụng JQuery để xóa tất cả các thuộc tính và khoảng xác thực khỏi DOM, thì thư viện xác thực vẫn sẽ cố gắng xác thực chúng.

Tuy nhiên, nếu bạn xóa dữ liệu "unsbtrectsValidation" của biểu mẫu ngoài "validationData", thì dữ liệu này hoạt động giống như một sự quyến rũ để thêm và xóa động các phần tử mà bạn muốn xác thực hoặc chưa xác thực.

$("form").removeData("validator");
$("form").removeData("unobtrusiveValidation");
$.validator.unobtrusive.parse("form");

2
Xhalent's lúc đầu cũng không hoạt động với tôi, sau đó tôi nhận thấy rằng phân tích cú pháp phải được chuyển qua một vùng chứa cho các phần tử mới, KHÔNG PHẢI bản thân các phần tử - sửa chữa nhanh sẽ là chuyển toàn bộ biểu mẫu thay vì (các) phần tử - sau đó nó làm việc như người ở.
Per Hornshøj-Schierbeck

1
bất kỳ ý tưởng tại sao nó nói validatorlà không được xác định? Tôi đã tham chiếu đến cả xác nhận và xác nhận hợp lệ. Xác thực hoạt động cho đến khi tôi gọi những mã này
Shawn Mclean

4
Cảm ơn. Nó hoạt động đối với nội dung được thêm vào trang trong các dạng xem từng phần ASP.MVC được thêm vào qua lệnh gọi AJAX.
Maksym Kozlenko

Cảm ơn điều này đã giúp. Nhưng tôi đang phải đối mặt với một vấn đề trong đó tôi đang sử dụng đàn accordion trên trang và nếu đàn accordion bị sập, nó không kích hoạt xác thực. Làm thế nào tôi có thể sửa lỗi này? Tôi biết nếu tôi đã sử dụng plugin xác thực jquery bình thường thay vì MVC3 không phô trương, tôi phải nói$('#form').validate({ignore: ""})
parsh

1
Nó làm việc cho tôi trong PHP. chỉ cần thêm thông tin này vì mọi nhận xét đều trỏ tới .NET MVC. : P
finnTheHumin,

42

Tôi thực sự thích sự đơn giản của giải pháp @viggity và @Robins, vì vậy tôi đã biến nó thành một plugin nhỏ nhanh chóng:

(function ($) {

    $.fn.updateValidation = function () {
        var $this = $(this);
        var form = $this.closest("form")
            .removeData("validator")
            .removeData("unobtrusiveValidation");

        $.validator.unobtrusive.parse(form);

        return $this;
    };
})(jQuery);

Ví dụ sử dụng:

$("#DischargeOutcomeNumberOfVisits")
    .attr("data-val-range-min", this.checked ? "1" : "2")
    .updateValidation();

thay thế $ .validator.unobtrusing.parse ("#" + form.attr ("id")); với $ .validator.unobtrusing.parse (biểu mẫu);
Softlion

bạn cũng có thể xóa .first () một cách an toàn vì gần nhất chỉ trả về 1 phần tử.
Softlion

Nice, tôi giống như phương pháp đơn giản này
nixon

Tác phẩm đẹp mắt cho cả các thuộc tính thêm và loại bỏ dữ liệu val
Julian Dormon

33

Im có cùng một vấn đề. Tôi phát hiện ra rằng không thể gọi $ .validator.unobtrusing.parse () trên cùng một biểu mẫu hai lần. Khi tải biểu mẫu ban đầu từ máy chủ, biểu mẫu được phân tích cú pháp tự động bởi thư viện kín đáo. Khi bạn thêm động một phần tử đầu vào vào biểu mẫu và gọi lại $ .validator.unobtrusing.parse (), nó sẽ không hoạt động. Tương tự với parseElement ().

Lib không phô trương gọi phương thức xác thực của plugin xác thực jquery để đặt tất cả các quy tắc và thông báo. Vấn đề là, khi được gọi lại, plugin không cập nhật bộ quy tắc mới mà nó đưa ra.

Tôi đã tìm thấy một giải pháp thô thiển: Trước khi gọi phương thức phân tích cú pháp trên lib không bắt buộc, tôi đã loại bỏ trình xác thực biểu mẫu:

$('yourForm').removeData("validator");

Bây giờ, khi phương thức xác thực được gọi bằng lib kín đáo, tất cả các quy tắc và thông báo được tạo lại bao gồm các đầu vào được thêm động.

Hi vọng điêu nay co ich


Xứng đáng là một 1 - đó là một giải pháp thô như bạn nói cho mình, nhưng nó khá rõ ràng những gì nó làm và những gì nêu bạn đang còn lại trong sau đó
mỗi Hornshøj-Schierbeck

2
Từ blog của Brad Wilsons: "Bạn cũng có thể gọi hàm jQuery.validator.unobtrusing.parseElement () để phân tích cú pháp một phần tử HTML." Bất kỳ giúp đỡ?
jamesfm

@Per Hornshøj-Schierbeck: @Robin van der Knaap: Tôi đã dành 2-3 giờ qua để tìm ra điều này !! Dù sao thì - điều này đã hoạt động HOÀN TOÀN. Sự thô thiển khiến tôi cảm thấy mình không nên sử dụng nó- tại sao tôi không muốn làm điều này?
KTF

2
Giải pháp hơi thô thiển vì tất cả trình xác thực đều bị xóa và phục hồi lại, bao gồm cả trình xác thực được thêm động. Sẽ tốt hơn nếu chỉ có trình xác thực được thêm động được cập nhật. @Xhalent cung cấp giải pháp rõ ràng hơn trong câu trả lời của anh ấy, nhưng về cơ bản thì thư viện kín đáo từ MS nên được cập nhật cho trường hợp này.
Robin van der Knaap

9

Tôi đang sử dụng MVC 4 và JQuery 1.8, có vẻ như đoạn mã sau là cần thiết để cho phép Jquery xác thực nội dung được đưa động qua Ajax hoặc Jquery vào DOM.

Tôi đã tạo một hàm mô-đun chấp nhận đối tượng Jquery của phần tử mới được thêm vào. Nếu bạn đã sao chép một bảng mới có id tblContactsbằng Jquery khi nhấp vào nút, thì hãy bao gồm hàm bên dưới trong tệp js của bạn

function fnValidateDynamicContent(element) {
    var currForm = element.closest("form");
    currForm.removeData("validator");
    currForm.removeData("unobtrusiveValidation");
    $.validator.unobtrusive.parse(currForm);
    currForm.validate(); // This line is important and added for client side validation to trigger, without this it didn't fire client side errors.
}

và gọi nó như thế này:

fnValidateDynamicContent("#tblContacts")

currform.validate (); thực sự phải là currForm.validate (); (lỗi đánh máy). Cám ơn chia sẻ mặc dù, điều này làm việc cho tôi
John Mc

1
@JohnMc đã sửa lỗi chính tả ngay bây giờ
Sundara Prabu

Đây là cái duy nhất phù hợp với tôi (mvc 4 và jquery 1.10)
The Muffin Man

4

Tại sao không sử dụng hàm quy tắc trực tiếp từ tài liệu xác thực jquery. Như thế này:

$('#newField0').rules('add', {
    required: true,
    minlength: 2
});
//use Html.ValidationMessage will renders a span element, unobtrusive need it to display errors
$('@Html.ValidationMessage("newField0")').insertAfter('#newField0');

2

Lấy từ giải pháp của Xhalent được đánh dấu là câu trả lời ở trên, tôi đã mở rộng nó một chút.

$.validator.unobtrusive.parseDynamicContent = function (selector) {
    var $selector = $(selector),
        $jqValUnob = $.validator.unobtrusive,
        selectorsDataValAttr = $selector.attr('data-val'),
        $validationInputs = $selector.find(':input[data-val=true]');

    if ((selectorsDataValAttr !== 'true') && 
        ($validationInputs.length === 0)) { 
        return; 
    }

    if (selectorsDataValAttr === 'true') {
        $jqValUnob.parseElement(selector, true);
    }

    $validationInputs.each(function () {
        $jqValUnob.parseElement(this, true);
    });

    //get the relevant form
    var $form = $selector.first().closest('form');

    $jqValUnob.syncValdators($form);
};

/* synchronizes the unobtrusive validation with jquery validator */
$.validator.unobtrusive.syncValdators = function ($form) {
    if ($.hasData($form[0])) {
        var unobtrusiveValidation = $form.data('unobtrusiveValidation'),
            validator = $form.validate();

        // add validation rules from unobtrusive to jquery
        $.each(unobtrusiveValidation.options.rules, function (elname, elrules) {
            if (validator.settings.rules[elname] == undefined) {
                var args = {};
                $.extend(args, elrules);
                args.messages = unobtrusiveValidation.options.messages[elname];
                $("[name='" + elname + "']").rules("add", args);
            } else {
                $.each(elrules, function (rulename, data) {
                    if (validator.settings.rules[elname][rulename] == undefined) {
                        var args = {};
                        args[rulename] = data;
                        args.messages = unobtrusiveValidation.options.messages[elname][rulename];
                        $("[name='" + elname + "']").rules("add", args);
                    }
                });
            }
        });
        // remove all validation rules from jquery that arn't in unobtrusive
        $.each(validator.settings.rules, function (elname, elrules) {
            if (unobtrusiveValidation.options.rules[elname] === undefined) {
                delete validator.settings.rules[elname];
            } else {
                $.each(elrules, function (rulename, data) {
                    if (rulename !== "messages" && unobtrusiveValidation.options.rules[elname][rulename] === undefined) {
                        delete validator.settings.rules[elname][rulename];
                    }
                });
            }
        });
    }        
};

$.validator.unobtrusive.unparseContent = function (selector) {
    var $selector = $(selector);

    // if its  a text node, then exit
    if ($selector && $selector.length > 0 && $selector[0].nodeType === 3) {
        return;
    }

    var $form = $selector.first().closest('form'), 
        unobtrusiveValidation = $form.data('unobtrusiveValidation');

    $selector.find(":input[data-val=true]").each(function () {
        removeValidation($(this), unobtrusiveValidation);
    });
    if ($selector.attr('data-val') === 'true') {
        removeValidation($selector, unobtrusiveValidation);
    }
    $.validator.unobtrusive.syncValdators($form);
};

function removeValidation($element, unobtrusiveValidation) {
    var elname = $element.attr('name');
    if (elname !== undefined) {
        $element.rules('remove');
        if (unobtrusiveValidation) {
            if (unobtrusiveValidation.options.rules[elname]) {
                delete unobtrusiveValidation.options.rules[elname];
            }
            if (unobtrusiveValidation.options.messages[elname]) {
                delete unobtrusiveValidation.options.messages[elname];
            }
        }
    }
}

Vì vậy, về cơ bản nó vẫn hoạt động giống như giải pháp của Xhalent ở trên nhưng tôi đã thêm khả năng xóa quy tắc cho các phần tử bạn xóa khỏi dom. Vì vậy, khi bạn xóa các phần tử khỏi Dom và bạn muốn các quy tắc xác thực đó cũng bị xóa thì hãy gọi:

$.validator.unobtrusive.unparseContent('input.something');

1

Tôi đã tìm thấy tập lệnh mã của @ Xhalent trong mã của mình và định xóa nó vì tôi không sử dụng nó, điều này dẫn tôi đến câu hỏi SO này.

Mã này khá rõ ràng và đơn giản:

jQuery.fn.unobtrusiveValidationForceBind = function () {
    //If you try to parse a form that is already parsed it won't update
    var $form = this
       .removeData("validator") /* added by the raw jquery.validate plugin */
            .removeData("unobtrusiveValidation");  /* added by the jquery     unobtrusive plugin */

    $form.bindUnobtrusiveValidation();
}

Sau đó, để gọi phần mở rộng jQuery này, chỉ cần sử dụng một bộ chọn để lấy biểu mẫu của bạn:

$('#formStart').unobtrusiveValidationForceBind();

Viola!


1

Tôi đã thử câu trả lời của viggity và lúc đầu mọi thứ dường như hoạt động. Nhưng sau một thời gian, tôi nhận thấy rằng việc xác thực trở nên chậm một cách đáng kể khi tôi thêm các mục động hơn. Lý do là giải pháp của anh ấy không hủy liên kết các trình xử lý sự kiện, mà thêm các trình xử lý mới mỗi lần. Vì vậy, nếu bạn thêm 5 mục, xác thực được thực hiện 6 lần thay vì chỉ một lần. Để khắc phục điều này, bạn phải hủy liên kết các sự kiện với các cuộc gọi removeData.

$("form").removeData("validator")
         .removeData("unobtrusiveValidation")
         .off("submit.validate click.validate focusin.validate focusout.validate keyup.validate invalid-form.validate");
$.validator.unobtrusive.parse("form");

1

Trong trường hợp nội dung động, bạn cần cập nhật Xác thực không phô trương như bên dưới và kiểm tra xem Formcó hợp lệ hay không khi gửi.

function UpdateUnobtrusiveValidations(idForm) {
    $(idForm).removeData("validator").removeData("unobtrusiveValidation");
    $.validator.unobtrusive.parse($(idForm));
};


$('#idDivPage').on('click', '#idSave', function (e) {
    e.preventDefault();
    if (!$('#idForm').valid()) {
        // Form is invalid … so return
        return false;
    }
    else {
        // post data to server using ajax call
        // update Unobtrusive Validations again
        UpdateUnobtrusiveValidations('#idForm');
    }
});

0

Tôi đã loay hoay với điều này trong một thời gian, loại bỏ các giải pháp và thử lại sau (khi tôi có chút thời gian rảnh rỗi, tin hay không).

Tôi không chắc liệu hành vi này có thay đổi trong các phiên bản jquery mới hơn (chúng tôi đang sử dụng 1.7.2) kể từ khi luồng này được tạo hoặc nhận xét lần cuối hay không, nhưng tôi thấy rằng điều đó .parseElement(inputElement)hoạt động tốt khi tôi cố gắng thêm các phần tử được tạo động vào biểu mẫu đã có trình xác thực được tải. Điều này đã được đề xuất bởi @jamesfm (15 tháng 2 '11) trong một trong các nhận xét ở trên, nhưng tôi đã bỏ qua nó trong vài lần đầu tiên tôi làm việc này. Vì vậy, tôi thêm nó như một câu trả lời riêng để làm cho nó rõ ràng hơn và bởi vì tôi nghĩ rằng đó là một giải pháp tốt và không đòi hỏi quá nhiều chi phí. Nó có thể không liên quan đến tất cả các vấn đề được nêu trong các câu trả lời tiếp theo nhưng tôi nghĩ nó sẽ là một giải pháp cho câu hỏi ban đầu. Đây là cách tôi làm việc của tôi:

//row & textarea created dynamically by an async ajax call further up in the code
var row = ...; //row reference from somewhere
var textarea = row.find("textarea");
textarea.val("[someValue]");

//add max length rule to the text area
textarea.rules('add', {
    maxlength: 2000
});
//parse the element to enable the validation on the dynamically added element
$.validator.unobtrusive.parseElement(textarea);

0

Đầu tiên, tôi nghĩ rằng cuộc gọi phải là .validator, không xác thực, sau đó bạn cần phải chuyển vào id của biểu mẫu

$.validator.unobtrusive.parse("#id");

Tôi giả sử bạn đã tải cả hai tập lệnh jquery.validate & jquery.validate.unobtrilities và gọi các phương thức Html.EnableClientValidation () và Html.EnableUnobtrusingJavaScript ()? Bạn có thể đăng một mẫu mã cho trang cơ sở của mình và có thể là biểu mẫu được tải động không?
Chris Allmark

0

Nếu bạn cần thêm và xóa mọi thứ với khả năng một số lỗi đã được hiển thị, đây là những gì tôi đã đến. Nó chủ yếu dựa trên các ý tưởng khác nhau trên trang câu hỏi này. Tôi sử dụng cài sẵn destroy()thay vì chỉ xóa thuộc tính dữ liệu cho JQuery validate.

function resetValidator($form: JQuery) {
    $form.validate().destroy();

    //reset unobtrusive validation summary, if it exists
    $form.find("[data-valmsg-summary=true]")
        .removeClass("validation-summary-errors")
        .addClass("validation-summary-valid")
        .find("ul").empty();

    //reset unobtrusive field level, if it exists
    $form.find("[data-valmsg-replace]")
        .removeClass("field-validation-error")
        .addClass("field-validation-valid")
        .empty();

    $form.removeData("unobtrusiveValidation");
}

Bạn gọi nó trước khi sửa đổi động các đầu vào trong biểu mẫu. Sau đó, bạn bắt đầu lại xác thực sau.

resetValidator($form);
//add or remove inputs here ...
$.validator.unobtrusive.parse($form);

Lưu ý: Nếu một số hoặc tất cả đầu vào đã được xác thực và có lỗi, những lỗi đó sẽ được đặt lại ... nhưng chúng sẽ trở lại chính xác vào lần xác thực tiếp theo.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.