2012-11-28 10 views
5

Próbuję eksperymentować i sprawdzać, czy istnieją sprytne rozwiązania do tworzenia niestandardowych weryfikatorów, które można wyodrębnić ze zgrabności i ponownego użycia.Sprawdzanie poprawności obiektu obserwowalnego względem warunku.

W poniższym jsfiddle po prostu ułożyłem prosty model macierzysty, który przechowuje i zawiera tablicę pomiarów (tylko wartość i data). W tym przykładzie wprowadziłem dwa wymagania.

  1. Każdy pomiar zawiera oba pola lub nie trzeba ich dostarczać.
  2. Musi być co najmniej jeden prawidłowy (spełnia poprzedni warunek) pomiar w macierzy nadrzędnej.

    Idealnie, chcę logiki sprawdzania poprawności dla tego, co określa się jako ważne, przechowywane w obiekcie Measurement, jak to zrobiłem poniżej. Ale rzeczą, z której jestem bardzo niesmaczny, jest "ręczna" walidacja, którą muszę wykonać w modelu nadrzędnym w atLeastOne().

walidacja Knockout automatycznie zweryfikować poszczególne pola dla liczb i dat ale muszę wkroczyć i sprawdzania poprawności przeciwko władzy na tablicy.

Pytanie: Czy jakieś metody, które pozwalają mi setup walidacji KO sprawdzić tablicę dla tego wymaganego warunku nadal mając metoda HasValues nadal mieszkają w modelu pomiaru ??? Tj. Chcę streścić koncepcję wyszukiwania "co najmniej jednego" w niestandardowym walidatorze, który może obsłużyć to zadanie dla mnie, a następnie po prostu powiedzieć temu walidatorowi "hej, oto funkcja, którą chcę, abyś użył do sprawdzenia poprawności każdy element w tablicy. "

Z góry dziękuję!

function Model(data) 
    { 
     var self = this; 
     self.Measurements = ko.observableArray(); 

     for(var i = 0; i < data.length; i++) 
      self.Measurements.push(new Measurement(data[i])); 

     function hasAtLeastOne(){ 
      var atLeastOne = false; 
      $.each(self.Measurements(), function(i, item) { 
       if (item.HasValues()) { 
        atLeastOne = true; 
        return; 
       } 
      }); 
      return atLeastOne; 
     } 

     self.Save = function() {    
      if (self.canSave() && atLeastOne()) 
       alert('save'); 
      else 
       alert('arg!'); 
     }; 

     self.errors = ko.validation.group(self); 
     self.canSave = ko.computed(function() { 
      return self.errors().length == 0; 
     }); 
    } 

    function Measurement(data) 
    { 
     var self = this; 
     self.Value = ko.observable(data.val); 
     self.Date = ko.observable(data.date); 

     self.Value.extend({ required: { onlyIf: isRequired }, number: true }); 
     self.Date.extend({ required: { onlyIf: isRequired }, date: true }); 

     self.HasValues = function() { 
      return ko.utils.isNotNullUndefOrEmpty(self.Value()) && 
        self.Date() && self.Date().length > 0; 
     }; 

     function isRequired() { 
      return ko.utils.isNotNullUndefOrEmpty(self.Value()) || 
        (self.Date() && self.Date().length > 0); 
     } 
    } 

    ko.utils.isNotNullUndefOrEmpty = function (value) { 
     return (typeof value === 'string' && value.length > 0) || 
       (typeof value !== 'string' && value); 
    }; 

Oto jsfiddle do zabawy, która ma moim przykładem: http://jsfiddle.net/cACZ9/

Odpowiedz

7

I zostały mucking źródła biblioteki, aby zobaczyć, czy mogę odkryć coś, co mogłoby być realną opcją. Oto, co znalazłem do tej pory.

Dwa różne opcje zarówno plusy/minusy (oczywiście):

pomocą Custom walidatora:

ko.validation.rules['AtLeastOne'] = { 
     validator: function (array, predicate) { 
      var self = this; 
      self.predicate = predicate; 
      return ko.utils.arrayFirst(array, function (item) { 
       return self.predicate.call(item); 
      }) != null; 
     }, 
     message: 'The array must contain at least one valid element.' 
    }; 


    function Modal() { 
    var self = this; 
    self.Measurements = ko.observableArray().extend({ AtLeastOne: function() { 
     return this && this.HasValues(); 
    } 

    ...//refer to OP 
    ... 
    ... 

    self.Save() = function() { 
     if (self.errors().length == 0) 
      alert('Everything is valid, we can save!'); 
     else if (!self.Measurements.isValid()) 
      alert('You must have at least one valid item in the pot!'); 
    }; 
    }); 

Podejście to dość dużo zajmuje walidacji z rąk programista i jest bardzo wielokrotnego użytku . Zauważyłem jednak, że potencjalny con jest taki, że wywoła niestandardową regułę walidacji za każdym razem, gdy jakakolwiek z wartości zapisanych w tablicy (obiektach lub w inny sposób) ulegnie mutacji. Może nie być problemem dla większości.

Korzystanie fabrykę validator:

var KoValidationFactory = { 
     AtLeastOne: function (measurements, validator) { 
      return function() { 
       var self = this; 
       self.validator = validator; 
       return ko.utils.arrayFirst(measurements, function (measurement) { 
          return self.validator.call(measurement); 
         }) != null; 
      }; 
     } 

    }; 

    function Modal() { 
     var self = this; 
     self.Measurements = ko.observableArray(); 

    ...//refer to OP 
    ... 
    ... 

     self.Save = function() { 
      var atLeastOneArrayValidator = KoValidationFactory.AtLeastOne(self.Measurements(), function() { 
       return this && this.HasValues(); 
     }); 
      var arrayWasValid = atLeastOneArrayValidator(); 
      if (arrayWasValid && self.errors() == 0) 
      alert('everything is good, we can save'); 
      else if (!arrayWasValid) 
      alert('You must have at least one item in the pot!'); 
     }; 
    } 

Takie podejście może zapewnić tylko sprawdzić całą tablicę, gdy jawnie wybrać, aby to zrobić. Na dole jest to, że masz więcej praktycznych zadań i nie w pełni korzystasz z biblioteki sprawdzania poprawności nokautu. Musisz konkretnie walidować tablicę i wszystkie/wszystkie inne obserwowalne, które przyjmują takie podejście, które mogłyby stać się nieporządne, gdyby było ich wiele.

Zachęcam do edycji i sugestii dotyczących tych metod.

Powiązane problemy