Как добавить специальную проверку в форму AngularJS?

У меня есть форма с полями ввода и установкой проверки, добавив required атрибуты и т. Д. Но для некоторых полей мне нужно сделать дополнительную проверку. Как я могу «нажать» на проверку, FormController контролирует FormController ?

Пользовательская проверка может быть чем-то вроде «если эти 3 поля заполнены, тогда это поле требуется и должно быть отформатировано определенным образом».

В FormController.$setValidity есть метод FormController.$setValidity но это не похоже на публичный API, поэтому я предпочитаю его не использовать. Создание пользовательской директивы и использование NgModelController выглядит как другой вариант, но в основном потребует от меня создать директиву для каждого пользовательского правила проверки, которого я не хочу.

Фактически, FormController поля из controllerа как недействительное (в то же время сохраняющее синхронизацию FormController ) может быть тем, что мне нужно в простейшем сценарии, чтобы выполнить эту работу, но я не знаю, как это сделать.

Изменить: добавлена ​​информация о ngMessages (> = 1.3.X) ниже.

Стандартные сообщения проверки формы (1.0.X и выше)

Поскольку это один из лучших результатов, если вы Google «Угловая форма проверки», в настоящее время я хочу добавить еще один ответ на этот вопрос для всех, кто приходит оттуда.

В FormController есть метод $ setValidity, но это не похоже на публичный API, поэтому я предпочитаю его не использовать.

Это «публично», не беспокойтесь. Используй это. Вот для чего это. Если бы это не предназначалось для использования, Угловые разработчики приватизировали бы его в закрытии.

Чтобы выполнить выборочную проверку, если вы не хотите использовать Angular-UI в качестве другого предлагаемого ответа, вы можете просто свернуть свою собственную директиву проверки.

 app.directive('blacklist', function (){ return { require: 'ngModel', link: function(scope, elem, attr, ngModel) { var blacklist = attr.blacklist.split(','); //For DOM -> model validation ngModel.$parsers.unshift(function(value) { var valid = blacklist.indexOf(value) === -1; ngModel.$setValidity('blacklist', valid); return valid ? value : undefined; }); //For model -> DOM validation ngModel.$formatters.unshift(function(value) { ngModel.$setValidity('blacklist', blacklist.indexOf(value) === -1); return value; }); } }; }); 

И вот пример использования:

 
The phrase "{{data.fruitName}}" is blacklisted required

Примечание: в 1.2.X, вероятно, предпочтительнее заменить ng-if для ng-show выше

Вот обязательная ссылка на плункер

Кроме того, я написал несколько записей в блогах только по этой теме, которая идет немного подробнее:

Угловая проверка формы

Пользовательские директивы по валидации

Изменить: использование ngMessages в 1.3.X

Теперь вы можете использовать модуль ngMessages вместо ngShow для отображения сообщений об ошибках. Он действительно будет работать с чем угодно, это не должно быть сообщение об ошибке, но вот основные сведения:

  1. Включить
  2. Ссылки ngMessages в объявлении модуля:

     var app = angular.module('myApp', ['ngMessages']); 
  3. Добавьте соответствующую разметку:

     
    required
    invalid email

В вышеупомянутой разметке ng-message="personForm.email.$error" основном указывает контекст для дочерних директив ng-message . Затем ng-message="required" и ng-message="email" указывают свойства в этом контексте для просмотра. Самое главное, они также определяют порядок их проверки . Первый, который он находит в списке, который является «правдивым», выигрывает, и он покажет это сообщение и ни одно из других.

И плункер для примера ngMessages

Проект Angular-UI включает в себя директиву ui-validate, которая, вероятно, поможет вам в этом. Это позволит вам указать функцию вызова для проверки.

Посмотрите демо-страницу: http://angular-ui.github.com/ , ищите до заголовка Validate.

На демо-странице:

  This e-mail is black-listed! 

затем в вашем controllerе:

 function ValidateCtrl($scope) { $scope.blackList = ['[email protected]','[email protected]']; $scope.notBlackListed = function(value) { return $scope.blackList.indexOf(value) === -1; }; } 

Вы можете использовать ng-required для вашего сценария проверки («если эти 3 поля заполнены, то это поле необходимо»:

 

Вы можете использовать Angular-Validator .

Пример: использование функции для проверки поля

  

Тогда в вашем controllerе у вас будет что-то вроде

 $scope.myCustomValidationFunction = function(firstName){ if ( firstName === "John") { return true; } 

Вы также можете сделать что-то вроде этого:

  

(где field1 field2 и field3 являются переменными области видимости. Также вы можете проверить, не совпадают ли поля с пустой строкой)

Если поле не пройдет проверку, то поле будет помечено как недопустимое, и пользователь не сможет отправить форму.

Дополнительные примеры использования и примеры см. По адресу : https://github.com/turinggroup/angular-validator

Отказ от ответственности: я являюсь автором Angular-Validator

Вот крутой способ выполнить пользовательские проверки шаблонов подстановки в форме (из: Расширенная проверка формы с помощью AngularJS и фильтров ):

 
 app.directive('ensureExpression', ['$http', '$parse', function($http, $parse) { return { require: 'ngModel', link: function(scope, ele, attrs, ngModelController) { scope.$watch(attrs.ngModel, function(value) { var booleanResult = $parse(attrs.ensureExpression)(scope); ngModelController.$setValidity('expression', booleanResult); }); } }; }]); 

jsFiddle demo (поддерживает именование выражений и несколько выражений)

Он похож на ui-validate , но вам не нужна специальная функция проверки масштаба (это работает в целом), и, конечно, вам не нужно ui.utils таким образом.

Недавно я создал директиву, позволяющую использовать недействительность входных сигналов угловой формы на основе выражений. Любое допустимое угловое выражение может использоваться, и оно поддерживает специальные ключи проверки, используя нотацию объекта. Протестировано с угловым v1.3.8

  .directive('invalidIf', [function () { return { require: 'ngModel', link: function (scope, elm, attrs, ctrl) { var argsObject = scope.$eval(attrs.invalidIf); if (!angular.isObject(argsObject)) { argsObject = { invalidIf: attrs.invalidIf }; } for (var validationKey in argsObject) { scope.$watch(argsObject[validationKey], function (newVal) { ctrl.$setValidity(validationKey, !newVal); }); } } }; }]); 

Вы можете использовать его следующим образом:

  

@synergetic Я думаю, @blesh предположим, что функция проверяется как ниже

 function validate(value) { var valid = blacklist.indexOf(value) === -1; ngModel.$setValidity('blacklist', valid); return valid ? value : undefined; } ngModel.$formatters.unshift(validate); ngModel.$parsers.unshift(validate); 

Обновить:

Улучшенная и упрощенная версия предыдущей директивы (одна вместо двух) с одинаковой функциональностью:

 .directive('myTestExpression', ['$parse', function ($parse) { return { restrict: 'A', require: 'ngModel', link: function (scope, element, attrs, ctrl) { var expr = attrs.myTestExpression; var watches = attrs.myTestExpressionWatch; ctrl.$validators.mytestexpression = function (modelValue, viewValue) { return expr == undefined || (angular.isString(expr) && expr.length < 1) || $parse(expr)(scope, { $model: modelValue, $view: viewValue }) === true; }; if (angular.isString(watches)) { angular.forEach(watches.split(",").filter(function (n) { return !!n; }), function (n) { scope.$watch(n, function () { ctrl.$validate(); }); }); } } }; }]) 

Пример использования:

   

Результат: Взаимозависимые тестовые выражения, в которых валидаторы выполняются при изменении директивной модели другого и текущей модели.

Тестное выражение имеет локальную переменную $model которую вы должны использовать для сравнения с другими переменными.

Ранее:

Я попытался улучшить код @Plantface, добавив дополнительную директиву. Эта дополнительная директива очень полезна, если наше выражение должно выполняться, когда изменения производятся более чем в нескольких переменных ngModel.

 .directive('ensureExpression', ['$parse', function($parse) { return { restrict: 'A', require: 'ngModel', controller: function () { }, scope: true, link: function (scope, element, attrs, ngModelCtrl) { scope.validate = function () { var booleanResult = $parse(attrs.ensureExpression)(scope); ngModelCtrl.$setValidity('expression', booleanResult); }; scope.$watch(attrs.ngModel, function(value) { scope.validate(); }); } }; }]) .directive('ensureWatch', ['$parse', function ($parse) { return { restrict: 'A', require: 'ensureExpression', link: function (scope, element, attrs, ctrl) { angular.forEach(attrs.ensureWatch.split(",").filter(function (n) { return !!n; }), function (n) { scope.$watch(n, function () { scope.validate(); }); }); } }; }]) 

Пример использования его для создания перекрестных подтвержденных полей:

    

ensure-expression выполняется для проверки модели при изменении ng-model или любой из ensure-watch переменных.

В AngularJS лучшим местом для определения Custom Validation является директива Cutsom. AngularJS предоставляет модуль ngMessages.

ngMessages – это директива, предназначенная для отображения и скрытия сообщений на основе состояния объекта key / value, который он прослушивает. Сама директива дополняет отчет об ошибках с объектом ошибки ngModel $ (который хранит состояние ключа / значения ошибок проверки).

Для выборочной проверки формы. Следует использовать модули ngMessages с настраиваемой директивой. Если у меня есть простая проверка, которая будет проверять, если длина номера меньше 6, отобразите ошибку на экране

  
Too Short

Вот как создать настраиваемую директиву проверки

 angular.module('myApp',['ngMessages']); angular.module('myApp',['ngMessages']).directive('customValidation',function(){ return{ restrict:'A', require: 'ngModel', link:function (scope, element, attr, ctrl) {// 4th argument contain model information function validationError(value) // you can use any function and parameter name { if (value.length > 6) // if model length is greater then 6 it is valide state { ctrl.$setValidity('invalidshrt',true); } else { ctrl.$setValidity('invalidshrt',false) //if less then 6 is invalide } return value; //return to display error } ctrl.$parsers.push(validationError); //parsers change how view values will be saved in the model } }; }); 

$setValidity – встроенная функция для установки состояния модели на действительный / недействительный

Я расширил ответ @Ben Lesh с возможностью указать, является ли проверка чувствительной к регистру или нет (по умолчанию)

использовать:

  

код:

 angular.module('crm.directives', []). directive('blacklist', [ function () { return { restrict: 'A', require: 'ngModel', scope: { 'blacklist': '=', }, link: function ($scope, $elem, $attrs, modelCtrl) { var check = function (value) { if (!$attrs.casesensitive) { value = (value && value.toUpperCase) ? value.toUpperCase() : value; $scope.blacklist = _.map($scope.blacklist, function (item) { return (item.toUpperCase) ? item.toUpperCase() : item }) } return !_.isArray($scope.blacklist) || $scope.blacklist.indexOf(value) === -1; } //For DOM -> model validation modelCtrl.$parsers.unshift(function (value) { var valid = check(value); modelCtrl.$setValidity('blacklist', valid); return value; }); //For model -> DOM validation modelCtrl.$formatters.unshift(function (value) { modelCtrl.$setValidity('blacklist', check(value)); return value; }); } }; } ]); 

Пользовательские проверки, вызывающие сервер

Используйте API ngModelController $asyncValidators который обрабатывает асинхронную проверку, например, делает запрос $http на бэкэнд. Функции, добавленные к объекту, должны возвращать promise, которое должно быть разрешено, если оно допустимо или отклонено, когда оно недействительно. ngModelController.$pending асинхронные проверки сохраняются ключом в ngModelController.$pending . Дополнительную информацию см. В Руководстве разработчика AngularJS – Forms (Custom Validation) .

 ngModel.$asyncValidators.uniqueUsername = function(modelValue, viewValue) { var value = modelValue || viewValue; // Lookup user by username return $http.get('/api/users/' + value). then(function resolved() { //username exists, this means validation fails return $q.reject('exists'); }, function rejected() { //username does not exist, therefore this validation passes return true; }); }; 

Для получения дополнительной информации см.

  • API nnModelController $asyncValidators

  • Руководство разработчика AngularJS – формы (пользовательская проверка) .

В этой теме представлены отличные примеры и библиотеки, но у них не было того, что я искал. Мой подход: угловая-валидность – основанная на обещании lib для асинхронной проверки, с опциональным стилем Bootstrap.

Решение угловой валидности для варианта использования ОП может выглядеть примерно так:

  

Вот скрипка , если вы хотите взять ее за спину. Библиотека доступна на GitHub , имеет подробную документацию и множество живых демоверсий.

  • Каков наилучший способ условного применения атрибутов в AngularJS?
  • Как получить элемент по имени classа или идентификатору
  • Невозможно найти подходящую версию для установки углового крепления
  • Rails CSRF Protection + Angular.js: protect_from_forgery заставляет меня выйти на POST
  • Какой метод следует использовать для ручной загрузки моего AngularJS?
  • В чем разница между $ routeProvider и $ stateProvider?
  • Мне нужно два экземпляра услуги AngularJS $ http или что?
  • Как / когда использовать ng-click для вызова маршрута?
  • Почему свойство «replace» устарело в директивах AngularJS?
  • localStorage vs sessionStorage vs cookie
  • Как перебирать ключи и значения с помощью ng-repeat в AngularJS?
  • Давайте будем гением компьютера.