2014-09-09 6 views
10

Das Verhalten der ngModelController-Analyse-Pipeline scheint sich zwischen Angular 1.2 und 1.3 geändert zu haben. Ich sehe jetzt immer einen neuen Validierungsschlüssel mit dem Namen 'parse', der allen $error-Objekten hinzugefügt wurde, und wenn einer der Parser nicht definiert zurückkehrt, überschreibt/ersetzt er alle anderen Validierungsschlüssel, die möglicherweise bereits gesetzt wurden.Welchen Zweck hat der neue integrierte Parser-Validierungsschlüssel in Angular 1.3?

Zum Beispiel, hier ist ein funktionierendes Beispiel in Angular 1.2.23 - versuchen, eine Zahl außerhalb des zulässigen Bereichs eingeben:

http://jsfiddle.net/8doq0saf/5/

Das Gleiche unter 1.3-rc läuft ein anderes Ergebnis ergibt:

http://jsfiddle.net/1t52s9b2/4/

Ich konnte noch keine Dokumentation zu dieser Änderung finden. Was ist der Zweck des Syntaxschlüssels und wie ändere ich meinen Code, um das alte Verhalten wiederherzustellen?

angular.module('app', []).directive('number', function() { 
    return { 
     require: 'ngModel', 
     link: function (scope, elem, attrs, ctrl) { 

      // valid number 
      ctrl.$parsers.push(function (value) { 
       var valid = angular.isUndefined(value) || value === '' || isFinite(value); 
       ctrl.$setValidity('number', valid); 
       return valid 
        ? angular.isUndefined(value) || value === '' ? undefined : Number(value) 
        : undefined; 
      }); 

      ctrl.$parsers.push(function (value) { 
       if (!angular.isDefined(attrs.minNumber)) { 
        return value; 
       } 
       var valid = angular.isUndefined(value) || Number(value) >= Number(attrs.minNumber); 
       ctrl.$setValidity('minNumber', valid); 
       return valid ? value : undefined; 
      }); 

      ctrl.$parsers.push(function (value) { 
       if (!angular.isDefined(attrs.maxNumber)) { 
        return value; 
       } 
       var valid = angular.isUndefined(value) || Number(value) <= Number(attrs.maxNumber); 
       ctrl.$setValidity('maxNumber', valid); 
       return valid ? value : undefined; 
      }); 
     } 
    }; 
}); 

Antwort

27

Angular 1.3 rationalisiert Dinge eine saubere Unterscheidung zwischen und Validierung Parsen.

Parsing

Angular jetzt fügt automatisch einen ‚Parst‘ Schlüssel zu allen $error Sammlungen mit seinem Wert entsprechend eingestellt - true, wenn eine der Parser undefined, sonst false zurückgegeben.

Für einen unpaarbaren Wert (eingegebene Buchstaben für eine Zahl, schlecht formatiertes Datum, usw.), sollten wir undefined vom Parser zurückgeben. Dies führt dazu, dass Angular alle bereits gesetzten $error-Schlüssel entfernt und das gesamte Objekt durch nur ersetzt. Es werden keine weiteren Parser mehr ausgeführt. Das Modell wird nicht aktualisiert. Das Array $parsers sollte jetzt nur zum Parsen verwendet werden.

Validation

ngModelController hat eine neue $validators Eigenschaft, auf die wir Validierungsfunktionen zuweisen können. Diese werden nur ausgeführt, wenn die Parsing-Pipeline erfolgreich war. Geben Sie false von einer dieser Funktionen für einen Wert zurück, der als erforderlicher Datentyp analysiert werden kann, aber nur ungültig (Zeichenfolge zu lang, Nummer außerhalb des Bereichs usw.). Der Name der Validiererfunktion wird zum Validierungsschlüssel im Objekt $error. Alle Validatoren werden ausgeführt, auch wenn false zurückgegeben wird. Das Modell wird nur aktualisiert, wenn die Validierung erfolgreich ist.

Dies ist möglicherweise eine brechende Änderung für vorhandene Anwendungen, da Benutzer häufig undefined von Parsern für einen ungültigen Wert zurückgegeben haben.Hier ist, was ich hatte, was ein typisches Beispiel ist:

ctrl.$parsers.push(function (value) { 
    if (!angular.isDefined(attrs.minNumber)) { 
     return value; 
    } 
    var valid = angular.isUndefined(value) || Number(value) >= Number(attrs.minNumber); 
    ctrl.$setValidity('minNumber', valid); 
    return valid ? value : undefined; 
}); 

Im Rahmen dieser neuen Regelung sollte diese stattdessen auf eine Validierungsfunktion verschoben werden:

ctrl.$validators.minNumber = function (value) { 
    return !value || !angular.isDefined(attrs.minNumber) || (value >= Number(attrs.minNumber)); 
}); 

Hier ist die Richtlinie mit allem, was oben geregelt:

angular.module('app', []).directive('number', function() { 
    return { 
     require: 'ngModel', 
     link: function (scope, elem, attrs, ctrl) { 

      // valid number 
      ctrl.$parsers.push(function (value) { 
       if(value === '') return value; 
       return isFinite(value) ? Number(value) : undefined; 
      }); 

      ctrl.$validators.minNumber = function (value) { 
       return !value || !angular.isDefined(attrs.minNumber) || (value >= Number(attrs.minNumber)); 
      }; 

      ctrl.$validators.maxNumber = function (value) { 
       return !value || !angular.isDefined(attrs.maxNumber) || (value <= Number(attrs.maxNumber)); 
      }; 
     } 
    }; 
}); 

http://jsfiddle.net/snkesLv4/10/

ich mag diese neue Art und Weise wirklich - es ist m uch sauberer.

+2

Sie sollten tatsächlich die neue '$ validators' Pipeline für Dinge wie Ihr Beispiel verwenden. 'ctrl. $ validators.minNumber = function (val) {/ * ... * /}' – JJJ

+0

Danke, ich hatte keine Ahnung von dieser neuen Funktion. –