jquery.validate.unobtrusive dinamik enjekte edilmiş öğelerle çalışmıyor


99

İle çalışıyorum ASP.Net MVC3, istemci doğrulamasını kullanmanın daha kolay yolu jquery.validate.unobtrusive. Sunucudan gelen şeyler için her şey yolunda gidiyor.

Ancak javascript ile bazı yeni 'girişler' enjekte etmeye çalıştığımda $.validator.unobtrusive.parse()ve doğrulamaları yeniden bulmak için aramam gerektiğini biliyordum . Ancak yine de, tüm bu dinamik enjekte edilmiş alanlar çalışmıyor.

Daha da kötüsü, kullanarak elle bağlamaya jquery.validateçalışıyorum ve o da çalışmıyor. Düşüncesi olan var mı?


1
Buraya google'dan geldiyseniz, büyük ölçüde olumlu oy alan diğerleri eski olduğundan, muhtemelen @Sundara Prabu'nun cevabını arıyorsunuz.
Kek Adam

Yanıtlar:


65

Durumum için bu sorunu çözen jquery.validate.unobtrusive kitaplığı için bir uzantı oluşturdum - ilgi çekici olabilir.

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


Sanırım cevabınızı doğru cevap olarak oylamalıyım. BTW, kitaplığınız en son MVC RC ile çalışıyor mu? yoksa bunu düzelttiler mi?
xandy

1
Yukarıda bağlantısı verilen kodu kullanırken, kodu yorumlara dahil etmek için güncellediğinizden emin olun, aksi takdirde kırılabilir. Özellikle, kimliği çift tırnak içine alacak şekilde iki seçici satırını değiştirin.
Ryan O'Neill

1
Bazı hata ayıklamalardan sonra nihayet senaryom için bu çalışmayı başardım. Görünüşe göre, bir giriş seçiciye geçmemeli, ancak yapılan çağrı nedeniyle girdinin ebeveyni veya formu geçmelidir $.validator.unobtrusive.parse(). Ayrıca, yalnızca yeni kurallar ekliyor ancak mevcut kuralların güncellemelerini almıyor mu?
lambinator

5
Bu cevap, en azından blog gönderisinin ayı kemiklerini içermelidir. Yalnızca bağlantı yanıtları genellikle SO için konu dışıdır
Liam

8
Bu cevap 3+ yaşında iken bu sitede, burada cevabın temel kısımlarını sonrası olabilir veya yayın silinmiş olma riski ise son derece yararlı olacaktır bunun bir link ancak daha fazla' uygun yanıtları bahseder SSS bölümüne bakın '. İsterseniz bağlantıyı yine de ekleyebilirsiniz, ancak yalnızca bir 'referans' olarak. Cevap, bağlantıya ihtiyaç duymadan kendi başına kalmalıdır.
Taryn

159

Xhalent'in yaklaşımını denedim ama maalesef benim için işe yaramadı. Robin'in yaklaşımı işe yaradı ve işe yaramadı. Dinamik olarak eklenen öğeler için harika çalıştı, ancak tüm doğrulama özniteliklerini ve aralıklarını DOM'dan kaldırmak için JQuery'yi kullanmaya çalıştıysanız, doğrulama kitaplığı yine de bunları doğrulamaya çalışır.

Ancak, "validationData" nın yanı sıra formun "göze batmayanValidation" verilerini kaldırırsanız, doğrulanmasını veya doğrulanmamasını istediğiniz öğeleri dinamik olarak eklemek ve kaldırmak için bir cazibe işlevi gördü.

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

2
Xhalent benim için de ilk başta işe yaramadı, sonra ayrıştırmanın yeni öğeler için bir kap geçirilmesi gerektiğini fark ettim, öğelerin kendileri DEĞİL - hızlı düzeltme, öğe (ler) yerine tüm formu geçirmektir - sonra bir cazibe gibi çalıştı.
Hornshøj-Schierbeck başına

1
neden validatortanımlanmadığını söylediği hakkında bir fikriniz var mı? Hem validation hem de validation.unobtrusive referanslarım var. Doğrulama, ben bu kodu arayana kadar çalışıyor
Shawn Mclean

4
Teşekkürler. AJAX çağrısı aracılığıyla eklenen ASP.MVC kısmi görünümlerinde sayfaya eklenen içerik için çalışır.
Maksym Kozlenko

Teşekkürler bu yardımcı oldu. Ancak sayfada akordeon kullandığım bir sorunla karşı karşıyayım ve akordeon çökerse, doğrulamaları ateşlemiyor. Bunu nasıl düzeltebilirim? Göze batmayan MVC3 yerine normal jquery doğrulama eklentisine gitmiş olsaydım, şunu söylemeliydim$('#form').validate({ignore: ""})
parsh

1
PHP'de benim için çalıştı. sadece bu bilgiyi eklemek çünkü her yorum .NET MVC'ye işaret ediyor. : P
finnTheHumin

42

Aslında @viggity ve @Robins çözümünün basitliğini gerçekten seviyorum, bu yüzden onu hızlı bir eklentiye dönüştürdüm:

(function ($) {

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

        $.validator.unobtrusive.parse(form);

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

Örnek kullanım:

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

$ .validator.unobtrusive.parse ("#" + form.attr ("id")); $ .validator.unobtrusive.parse (form) ile;
Softlion

En yakın yalnızca 1 öğe döndürdüğü için .first () öğesini güvenli bir şekilde kaldırabilirsiniz.
Softlion

Güzel, bu basit yaklaşımı beğendim
nixon

Veri-değer özniteliklerinin eklenmesi ve kaldırılması için güzel çalışıyor
Julian Dormon

33

Bendede aynı sorun var. Aynı formda $ .validator.unobtrusive.parse () öğesini iki kez çağırmanın mümkün olmadığını keşfettim. Form sunucudan başlangıçta yüklenirken, form göze batmayan kitaplık tarafından otomatik olarak ayrıştırılır. Forma dinamik olarak bir giriş öğesi eklediğinizde ve $ .validator.unobtrusive.parse () öğesini tekrar çağırdığınızda, çalışmaz. Aynı şey parseElement () için de geçerli.

Göze batmayan kitaplık, tüm kuralları ve mesajları ayarlamak için jquery validate eklentisinin validate yöntemini çağırır. Sorun, tekrar çağrıldığında eklentinin verildiği yeni kurallar kümesini güncellememesidir.

Ham bir çözüm buldum: Göze batmayan kitaplıkta ayrıştırma yöntemini çağırmadan önce, form doğrulayıcısını atıyorum:

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

Şimdi, validate yöntemi göze batmayan kitaplık tarafından çağrıldığında, dinamik olarak eklenen girdiler dahil tüm kurallar ve mesajlar yeniden oluşturulur.

Bu yardımcı olur umarım


Bir + 1'i hak ediyor - bu sizin söylediğiniz gibi kaba bir çözüm, ancak ne yaptığı ve sonrasında ne durumda
kalacağınız

2
Brad Wilsons blogundan: "Tek bir HTML öğesini ayrıştırmak için jQuery.validator.unobtrusive.parseElement () işlevini de çağırabilirsiniz." Herhangi bir yardım?
jamesfm

@Per Hornshøj-Schierbeck: @Robin van der Knaap: Bunu çözmek için son 2-3 saatimi harcadım !! Her neyse - bu harika çalıştı. Kaba bana bunu kullanmamam gerektiğini hissettiriyor - neden bunu yapmak istemeyeyim?
KTF

2
Çözüm biraz kaba çünkü dinamik olarak eklenen doğrulayıcı da dahil olmak üzere tüm doğrulayıcılar kaldırılır ve yeniden etkinleştirilir. Yalnızca dinamik olarak eklenen doğrulayıcının güncellenmesi daha iyi olur. @Xhalent cevabında daha temiz bir çözüm sunuyor, ancak temelde MS'in göze batmayan kütüphanesi bu senaryo için güncellenmelidir.
Robin van der Knaap

9

Ben kullanıyorum , MVC 4 ve JQuery 1.8 aşağıdaki kod parçası gibi görünüyor DOM içine Ajax veya jQuery yoluyla doğrulama dinamik enjekte içeriğe jQuery sağlamak için gereklidir.

Yeni eklenen elemanın Jquery nesnesini kabul eden modüler bir işlev yaptım. tblContactsBir düğmeye tıklayarak Jquery kullanarak id ile yeni bir tablo klonladıysanız , aşağıdaki işlevi js dosyanıza ekleyin

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.
}

ve şöyle diyelim:

fnValidateDynamicContent("#tblContacts")

currform.validate (); aslında currForm.validate () olmalıdır; (yazım hatası). Paylaştığınız için teşekkürler, bu benim için çalıştı
John Mc

1
@JohnMc yazım hatasını şimdi düzeltti
Sundara Prabu

Bu benim için çalışan tek kişi (mvc 4 ve jquery 1.10)
The Muffin Man

4

Neden kurallar işlevini doğrudan jquery doğrulama belgesinden kullanmıyorsunuz ? Bunun gibi:

$('#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

Xhalent'in yukarıdaki cevap olarak işaretlenen çözümünden yola çıkarak, biraz genişlettim.

$.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];
            }
        }
    }
}

Yani temelde hala yukarıdaki Xhalent çözümüyle aynı şekilde çalışıyor, ancak domtan kaldırdığınız öğelerin kurallarını kaldırma özelliğini ekledim. Dolayısıyla, Dom'dan öğeleri kaldırdığınızda ve bu doğrulama kurallarının da kaldırılmasını istiyorsanız, şu çağrıyı yapın:

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

1

Kodumda @ Xhalent'in kod betiğini buldum ve onu kullanmadığım için silecektim, bu da beni bu SO sorusuna yönlendirdi.

Bu kod oldukça temiz ve basittir:

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();
}

Ardından, bu jQuery uzantısını çağırmak için, formunuzu almak için bir seçici kullanın:

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

Viyola!


1

Viggity'nin cevabını denedim ve ilk başta her şey işe yarıyor gibiydi. Ancak bir süre sonra, eklediğim daha dinamik öğeler arttıkça doğrulamanın acı verici bir şekilde yavaşladığını fark ettim. Bunun nedeni, çözümünün olay işleyicilerini çözmemesi, her seferinde yenilerini eklemesiydi. Yani 5 öğe eklerseniz, doğrulama yalnızca bir kez yerine 6 kez yürütülür. Bunu düzeltmek için, olayları ek olarak removeData çağrılarına bağlamanız gerekir.

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

1

Dinamik içerik olması durumunda, Göze batmayan Doğrulamaları aşağıdaki gibi güncellemeniz ve Formgönderirken geçerli olup olmadığını kontrol etmeniz gerekir .

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

Bir süredir bununla uğraşıyordum, çözümleri hurdaya çıkarıyorum ve daha sonra tekrar deniyorum (biraz boş zamanım olduğunda, ister inan ister inanma).

Bu iş parçacığı en son oluşturulduğundan veya yorumlandığından bu yana jquery'nin yeni sürümlerinde bu davranışın değişip değişmeyeceğinden emin değilim (1.7.2 kullanıyoruz), ancak .parseElement(inputElement)bir forma dinamik olarak oluşturulmuş öğeler eklemeye çalıştığımda bunun iyi çalıştığını gördüm. zaten yüklenmiş bir doğrulayıcı var. Bu, yukarıdaki yorumlardan birinde @jamesfm (Şubat 15 '11) tarafından zaten önerilmişti, ancak bunun üzerinde çalıştığım ilk birkaç seferde bunu göz ardı ettim. Bu yüzden, daha açık hale getirmek için ayrı bir cevap olarak ekliyorum ve çünkü bunun iyi bir çözüm olduğunu ve çok fazla ek yük gerektirmediğini düşünüyorum. Sonraki cevaplarda ortaya konulan tüm konularla alakalı olmayabilir, ancak bence bu orijinal soruya bir çözüm olacaktır. İşte benimkini nasıl çalıştırdım:

//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

İlk olarak, çağrı .validator olmalı, validate değil, sonra formun kimliğini iletmeniz gerektiğini düşünüyorum.

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

Hem jquery.validate & jquery.validate.unobtrusive komut dosyalarını yüklediğinizi hem de Html.EnableClientValidation () ve Html.EnableUnobtrusiveJavaScript () yöntemlerini aradığınızı varsayıyorum. Temel sayfanız ve dinamik olarak yüklenen form için bir kod örneği gönderebilir misiniz?
Chris Allmark

0

Bazı hataların zaten görüntülenme olasılığı ile bir şeyler eklemeniz ve kaldırmanız gerekirse, bu benim geldiğim şey. Esas olarak bu soru sayfasındaki farklı fikirlere dayanmaktadır. destroy()Sadece JQuery doğrulaması için veri özniteliğini kaldırmak yerine yerleşik olanı kullanıyorum .

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");
}

Formdaki girişleri dinamik olarak değiştirmeden önce çağırırsınız. Daha sonra doğrulamayı yeniden başlatırsınız.

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

Not: Girişlerin bazıları veya tümü doğrulandıysa ve hatalar varsa, bu hatalar sıfırlanacak ... ancak bir sonraki doğrulamada doğru bir şekilde geri gelecekler.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.