Angular предоставляет директивы проверки для основных входных данных HTML5 (обязательно, шаблон, минимальная длина, максимальная длина, минимальная, максимальная). Но из персонализированной директивы можно добавить собственную валидацию. Для этого достаточно добавить функцию в объект $validators ngModelController. Чтобы манипулировать контроллером, мы просто помещаем требование со значением ngModel в нашу директиву.
Преимущество этого в том, что любая функция объекта $validators имеет в качестве параметров viewValue и modelValue. Функции проверки запускаются каждый раз при изменении входных данных или модели. После этого Angular вызовет функцию setValidity(result) внутри с возвращаемым значением нашей функции (true или false). Эта последняя функция отвечает за изменение объекта $error в случае, если наша форма не была проверена.
Пример такого решения:
Директива, которая проверяет, является ли то, что записано во входных данных, целым числом.
var app = angular.module('form-example1', []); var INTEGER_REGEXP = /^\-?\d+$/; app.directive('integer', function() { return { require: 'ngModel', link: function(scope, elm, attrs, ctrl) { ctrl.$validators.integer = function(modelValue, viewValue) { if (ctrl.$isEmpty(modelValue)) { // consider empty models to be valid return true; } if (INTEGER_REGEXP.test(viewValue)) { // it is valid return true; } // it is invalid return false; }; } }; });
<input type="number" ng-model="size" name="size" min="0" max="10" integer />
Функция integer, созданная в объекте $validators, проверяет с помощью регулярного выражения, что то, что записано во входных данных, на самом деле является целым числом. Если модель пуста, она считается действительной.
Иногда этот вариант может не сработать (у меня так случилось по неизвестным причинам), но есть и другие варианты. Отличие этих опций в том, что они используют объекты $parsers и $formatters вместо $validators. Объект $parsers используется для проверки того, что уже есть в модели, то есть фактической модели. Таким образом, когда ввод обновляется, проверенным значением будет предыдущее, а не последнее вмененное значение. Может показаться, что это не так уж полезно, но может оказаться полезным для частного случая, когда это сработает.
Тогда у нас остается альтернатива объекту $formatters, его преимущество в том, что он предоставляет возможность проверки значения, которое находится в DOM. В этих двух последних вариантах мы отвечаем за вызов функции setValidity, Angular на этот раз не будет делать это сам :(. Чтобы сделать его использование более понятным (выглядит как выше), я оставляю пример:
app.directive('dateValidator', function () { return { require: 'ngModel', link: function (scope, elm, attrs, ctrl) { //add a formatter that will process each time the value is //formatted into the model when the user updates it. ctrl.$formatters.unshift(function (value) { var valid = false; if (value) { // test and set the validity after update. var viewDate = new Date(parseInt(value, 10)); var actualDate = new Date(); if (viewDate <= actualDate) { // it is valid valid = true; } ctrl.$setValidity('date', valid); } // if it's valid, return the value to the model, // otherwise return undefined. return valid ? value : undefined; }); } }; });
Вместо того, чтобы создавать функцию в объекте $formatters, мы «редактируем» функцию unshift объекта и оттуда вызываем setValidity. Параметры, которые мы передаем функции setValidity, — это те, которые появятся в объекте $error, например «ключ: значение», что позволит нам выбрать этот ключ и это значение, чтобы позже мы могли проверить, чтобы сделать решения.
Одним из основных преимуществ использования этих методов является то, что их можно повторно использовать для любой формы, которая есть в нашем приложении, и в зависимости от нашей проверки мы можем выполнять различные действия.
Первоначально опубликовано на сайте blog.bixlabs.com 12 января 2016 г.