2013-03-07 25 views
11

MVC 4'ü KnockoutJS ile kullanma. Özel bir nakavt onaylama ile göze batmayan doğrulama bağlayabilir miyim? Şu anda, afterRender ile bir şablon kullanarak doğrulama işlemini yeniden yapıyorum. Otomatik olarak eklemeyle eklenmiş olmayı çok isterim. Bunun gibi:Özel KnockoutJS bağlamasıyla benzersiz onaylama işlemini bağlama

ko.bindingHandlers.egtZipRep = { 
    init: function (element, valueAccessor, allBindingsAccessor, context) { 
     $(element).inputmask("99999", { "placeholder": " " }); 
     egtUniqueNameBinding(element, ++ko.bindingHandlers['uniqueName'].currentIndex); 

     applyValidationRules(element); // Is it possible to do this here? 

     ko.bindingHandlers.value.init(element, valueAccessor, allBindingsAccessor, context); 
    } 
}; 

Bütün gün bununla uğraştım. Son derece verimsiz olarak yapamam.

Şu anda yaptığım gibi, aşağıda. Belki de bundan mutlu olmalıyım. Ama sanırım insanlar bunu daha önce denediler.

self.ReferenceAfterRender = function (element) { 
    bindUnobtrusiveValidation(element); 
} 

// Bind validation on new content 
function bindUnobtrusiveValidation(element) { 
    // Bind to fields - must be called everytime new field is created 
    $.validator.unobtrusive.parseDynamicContent(element); 
} 

$.validator.unobtrusive.parseDynamicContent = function (selector) { 
// Use the normal unobstrusive.parse method 
$.validator.unobtrusive.parse(selector); 

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

// Get the collections of unobstrusive validators, and jquery validators 
// and compare the two 
var unobtrusiveValidation = form.data('unobtrusiveValidation'); 
var validator = form.validate(); 

if (typeof (unobtrusiveValidation) != "undefined") { 
    $.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); 
     } 
     }); 
    } 
    }); 
} 
+0

Bunu düşünmek zorundaydım, belki de buna nasıl yaklaştığımı anlayabiliyorum. – kamranicus

+0

Tamam, hiçbir zaman hiçbir özel doğrulama bağlaması oluşturmak zorunda kalmamıştım, MVC'nin onaylama nitelikleri çıktıları için özniteliklerini kullandık ve aynı zamanda AJAX çağrıları yaparken 'parseDynamicContent' yardımcı yöntemini kullandık. jquery.unobtrusive.js dosyasını inceleyin ve eminim ki kuralları dinamik olarak eklemek için arayabileceğiniz bir yöntem var. – kamranicus

cevap

3

İlginç soru! İşte bir saf KnockoutJS + VanillaJS çözümü. Bazı kırışıklıklar, çapraz tarayıcı maddeleri (size, IE'ye bakıyorum!) Ve pürüzlü kenarlar olabilir. İsterseniz yorumlarda bana bildirin ya da cevabın güncellenmesini önerin.


ViewModel & Doğrulama Kuralları:
doğrulama kuralları çok .NET nitelikler gibi, ViewModel özelliklerinde yakın olmalıdır. KnockoutJS belgeleri, bu amaç için extenders kullanılmasını önerir. Kullanımı şu şekilde görünecektir:

self.name = ko.observable("Bob-Martin"); 
self.name = self.name.extend({ regex: { pattern: "^[^0-9]*$", message: "No digits plz!" } }) 
self.name = self.name.extend({ regex: { pattern: "^[^-]*$", message: "No dashes plz!" } }); 

Kod Extender: belgelerinden
genişletici güzel ve basittir. doğrulama mesajları için

ko.extenders.regex = function(target, options) { 
    options = options || {}; 
    var regexp = new RegExp(options.pattern || ".*"); 
    var message = options.message || "regex is mad at you, bro!"; 

    // Only create sub-observable if it hasn't been created yet 
    target.errors = target.errors || ko.observableArray(); 

    function validate(newValue) { 
     var matched = regexp.test(newValue); 

     if (!matched && target.errors.indexOf(message) == -1) { 
      target.errors.push(message); 
     } 
     else if (matched && target.errors.indexOf(message) >= 0) { 
      // TODO: support multiple extender instances with same 
      // message yet different pattern. 
      target.errors.remove(message); 
     } 
    } 

    validate(target()); //initial validation 
    target.subscribe(validate); //validate whenever the value changes 
    return target; //return the original observable 
}; 

Şablon:
Görünüm DRY yapmak ve doğrulama mütevazi ben eklemek istiyorum İşte bir (aynı mesajın birden fazla kurallar için bazı iş olsa da) birden doğrulama hatalarını işleme alternatiftir böyle doğrulama hataları için bir şablon tanımlayın:

<script type="text/html" id="validation"> 
    <span data-bind="foreach: $data" class="errors"> 
     <span data-bind='text: $data'> </span>  
    </span> 
</script> 

Görünüm:
gerçek görünümü çok basit olabilir:

<p>Name: <input data-bind='valueWithValidation: name' /></p> 

doğrulama mesajları ile burada hiçbir biçimlendirme olduğundan, Mütevazi ve KURU. (Gerçi sizin doğrulama için özel işaretlemeyi istiyorsanız, sadece value bağlayıcı kullanmak ve name.errors için ayrı işaretlemeyi yaratabilir.)

Custom bağlayıcı:
Ve custom binding adil düzen içinde, yapardın:

  1. Şablonu giriş alanından sonra enjekte edin.
  2. Veri olarak görüntülenebilir olan name ile doğru şablon bağını uygulayın.
  3. Geri kalanını value ve valueUpdate bağlantı noktalarına geçirin.İşte

(yani bazı üstlenmeden gerekebilir ve olsa jQuery/javascript lovin') bağlayıcıdır:

ko.bindingHandlers.valueWithValidation = { 
    init: function (element, valueAccessor, allBindingsAccessor) { 
     // Interception! Add validation markup to the DOM and 
     // apply the template binding to it. Some of this code 
     // can be more elegant, especially if you use jQuery or 
     // a similar library. 
     var validationElement = document.createElement("span"); 
     element.parentNode.insertBefore(validationElement, element.nextSibling); 
     ko.applyBindingsToNode(validationElement, { template: { name: 'validation', data: valueAccessor().errors } }); 

     // The rest of this binding is handled by the default 
     // value binding. Pass it on! 
     ko.applyBindingsToNode(element, { value: valueAccessor(), valueUpdate: 'afterkeydown' }); 
    } 
}; 

Demo:
, eylem tüm bu bkz bir göz at sahip olmak this jsfiddle.