С помощью AngularJS я могу использовать ng-pristine
или, ng-dirty
чтобы определить, ввел ли пользователь это поле. Однако я хочу выполнять проверку на стороне клиента только после того, как пользователь покинул область поля. Это связано с тем, что, когда пользователь вводит такое поле, как электронная почта или телефон, он всегда будет получать сообщение об ошибке до тех пор, пока он не завершит ввод своего электронного письма полностью, и это не является оптимальным для пользователя.
ОБНОВИТЬ:
Angular теперь поставляется с настраиваемым событием размытия: https://docs.angularjs.org/api/ng/directive/ngBlur
Ответы:
Angular 1.3 теперь имеет ng-model-options, и вы можете установить эту опцию,
{ 'updateOn': 'blur'}
например, и вы даже можете отклонить, когда используется либо слишком быстрый ввод, либо вы хотите сэкономить несколько дорогостоящих операций DOM (например, написание модели в несколько мест DOM, и вы не хотите, чтобы цикл $ digest происходил при каждом нажатии клавиши)https://docs.angularjs.org/guide/forms#custom-triggers и https://docs.angularjs.org/guide/forms#non-immediate-debounced-model-updates.
И отрицают
источник
ng-change
события до того, как пользователь покинет поле. Например, в моем случае я запрашиваю новые данные из своего API, как только поле ввода становится действительным, но я не хочу показывать сообщение об ошибке, если оно недействительно - я хочу сделать это только тогда, когда оно недопустим, и произошло событие размытия.1.3.0 rc-3
и он не срабатывает,change
пока не сработаетblur
, проверьте это: plnkr.co/edit/RivVU3r7xfHO1hUybqMu?p=previewНачиная с версии 1.3.0 это можно легко сделать
$touched
, что верно после того, как пользователь покинул поле.<p ng-show="form.field.$touched && form.field.$invalid">Error</p>
https://docs.angularjs.org/api/ng/type/ngModel.NgModelController
источник
updateOn: 'default'
что означает, что для входов, ключа вверх и для выбора, при измененииЯ решил это, расширив то, что предложил @jlmcdonald. Я создал директиву, которая будет автоматически применяться ко всем элементам ввода и выбора:
var blurFocusDirective = function () { return { restrict: 'E', require: '?ngModel', link: function (scope, elm, attr, ctrl) { if (!ctrl) { return; } elm.on('focus', function () { elm.addClass('has-focus'); scope.$apply(function () { ctrl.hasFocus = true; }); }); elm.on('blur', function () { elm.removeClass('has-focus'); elm.addClass('has-visited'); scope.$apply(function () { ctrl.hasFocus = false; ctrl.hasVisited = true; }); }); elm.closest('form').on('submit', function () { elm.addClass('has-visited'); scope.$apply(function () { ctrl.hasFocus = false; ctrl.hasVisited = true; }); }); } }; }; app.directive('input', blurFocusDirective); app.directive('select', blurFocusDirective);
Это добавит
has-focus
иhas-visited
классы к различным элементам , как пользователь фокусирует / визиты элементов. Затем вы можете добавить эти классы в свои правила CSS, чтобы отображать ошибки проверки:input.has-visited.ng-invalid:not(.has-focus) { background-color: #ffeeee; }
Это хорошо работает, поскольку элементы по-прежнему получают недействительные свойства и т. Д., Но CSS можно использовать, чтобы улучшить взаимодействие с пользователем.
источник
formName.inputName.$dirty
. Я бы предложил отредактировать директиву, чтобы написать подобное логическое значениеformName.inputName.$focused
, вместо того, чтобы использовать имена классов для размытия и логические значения для проверки.Мне удалось сделать это с помощью довольно простого CSS. Это действительно требует, чтобы сообщения об ошибках были братьями и сестрами входных данных, к которым они относятся, и чтобы они имели класс
error
.:focus ~ .error { display:none; }
После выполнения этих двух требований это скроет любое сообщение об ошибке, относящееся к сфокусированному полю ввода, что, я думаю, angularjs все равно должен делать. Похоже на недосмотр.
источник
Кажется, это стандартно реализовано в новых версиях angular.
Классы ng-untouched и ng-touched устанавливаются соответственно до и после того, как пользователь сфокусировался на проверенном элементе.
CSS
input.ng-touched.ng-invalid { border-color: red; }
источник
Что касается решения @ lambinator ... Я получал следующую ошибку в angular.js 1.2.4:
Я не уверен, что я сделал что-то не так или это изменение в Angular, но удаление
scope.$apply
операторов решило проблему, и классы / состояния все еще обновляются.Если вы также видите эту ошибку, попробуйте следующее:
var blurFocusDirective = function () { return { restrict: 'E', require: '?ngModel', link: function (scope, elm, attr, ctrl) { if (!ctrl) { return; } elm.on('focus', function () { elm.addClass('has-focus'); ctrl.$hasFocus = true; }); elm.on('blur', function () { elm.removeClass('has-focus'); elm.addClass('has-visited'); ctrl.$hasFocus = false; ctrl.$hasVisited = true; }); elm.closest('form').on('submit', function () { elm.addClass('has-visited'); scope.$apply(function () { ctrl.hasFocus = false; ctrl.hasVisited = true; }); }); } }; }; app.directive('input', blurFocusDirective); app.directive('select', blurFocusDirective);
источник
Возможно, вам удастся написать специальную директиву, которая обертывает метод javascript blur () (и запускает функцию проверки при срабатывании); есть проблема Angular, которая имеет образец (а также общую директиву, которая может связываться с другими событиями, которые изначально не поддерживаются Angular):
https://github.com/angular/angular.js/issues/1277
Если вы не хотите идти по этому пути, другим вариантом будет установка $ watch в поле, снова запускающая проверку при заполнении поля.
источник
Чтобы продолжить изучение данных ответов, вы можете упростить тегирование ввода, используя псевдоклассы CSS3 и отмечая только посещенные поля классом, чтобы отложить отображение ошибок проверки до тех пор, пока пользователь не потеряет фокус на поле:
(Для примера требуется jQuery)
JavaScript
module = angular.module('app.directives', []); module.directive('lateValidateForm', function () { return { restrict: 'AC', link: function (scope, element, attrs) { $inputs = element.find('input, select, textarea'); $inputs.on('blur', function () { $(this).addClass('has-visited'); }); element.on('submit', function () { $inputs.addClass('has-visited'); }); } }; });
CSS
input.has-visited:not(:focus):required:invalid, textarea.has-visited:not(:focus):required:invalid, select.has-visited:not(:focus):required:invalid { color: #b94a48; border-color: #ee5f5b; }
HTML
<form late-validate-form name="userForm"> <input type="email" name="email" required /> </form>
источник
на основе ответа @nicolas .. Чистый CSS должен помочь, он покажет только сообщение об ошибке при размытии
<input type="email" id="input-email" required placeholder="Email address" class="form-control" name="email" ng-model="userData.email"> <p ng-show="form.email.$error.email" class="bg-danger">This is not a valid email.</p>
CSS
.ng-invalid:focus ~ .bg-danger { display:none; }
источник
Вот пример использования ng-messages (доступно в angular 1.3) и настраиваемой директивы.
Сообщение проверки отображается при размытии впервые, когда пользователь покидает поле ввода, но когда он исправляет значение, сообщение проверки немедленно удаляется (больше не размытие).
JavaScript
myApp.directive("validateOnBlur", [function() { var ddo = { restrict: "A", require: "ngModel", scope: {}, link: function(scope, element, attrs, modelCtrl) { element.on('blur', function () { modelCtrl.$showValidationMessage = modelCtrl.$dirty; scope.$apply(); }); } }; return ddo; }]);
HTML
<form name="person"> <input type="text" ng-model="item.firstName" name="firstName" ng-minlength="3" ng-maxlength="20" validate-on-blur required /> <div ng-show="person.firstName.$showValidationMessage" ng-messages="person.firstName.$error"> <span ng-message="required">name is required</span> <span ng-message="minlength">name is too short</span> <span ng-message="maxlength">name is too long</span> </div> </form>
PS. Не забудьте загрузить и включить ngMessages в свой модуль:
var myApp = angular.module('myApp', ['ngMessages']);
источник
Параметры ng-model в AngularJS 1.3 (бета-версия на момент написания) задокументированы для поддержки {updateOn: 'blur'}. Для более ранних версий у меня работало что-то вроде следующего:
myApp.directive('myForm', function() { return { require: 'form', link: function(scope, element, attrs, formController) { scope.validate = function(name) { formController[name].isInvalid = formController[name].$invalid; }; } }; });
С таким шаблоном:
<form name="myForm" novalidate="novalidate" data-my-form=""> <input type="email" name="eMail" required="required" ng-blur="validate('eMail')" /> <span ng-show="myForm.eMail.isInvalid">Please enter a valid e-mail address.</span> <button type="submit">Submit Form</button> </form>
источник
Использовать состояние поля $ touched Для этого было изменено поле, как показано в примере ниже.
<div ng-show="formName.firstName.$touched && formName.firstName.$error.required"> You must enter a value </div>
источник
Вы можете динамически установить класс css has-error (при условии, что вы используете bootstrap), используя ng-class и свойство в области связанного контроллера:
plunkr: http://plnkr.co/edit/HYDlaTNThZE02VqXrUCH?p=info
HTML:
<div ng-class="{'has-error': badEmailAddress}"> <input type="email" class="form-control" id="email" name="email" ng-model="email" ng-blur="emailBlurred(email.$valid)"> </div>
Контроллер:
$scope.badEmailAddress = false; $scope.emailBlurred = function (isValid) { $scope.badEmailAddress = !isValid; };
источник
Если вы используете bootstrap 3 и lesscss, вы можете включить проверку размытия с помощью следующего фрагмента less:
:focus ~ .form-control-feedback.glyphicon-ok { display:none; } :focus ~ .form-control-feedback.glyphicon-remove { display:none; } .has-feedback > :focus { & { .form-control-focus(); } }
источник
outЯ использовал директиву. Вот код:
app.directive('onBlurVal', function () { return { restrict: 'A', link: function (scope, element, attrs, controller) { element.on('focus', function () { element.next().removeClass('has-visited'); element.next().addClass('has-focus'); }); element.on('blur', function () { element.next().removeClass('has-focus'); element.next().addClass('has-visited'); }); } } })
Все мои элементы управления вводом содержат элемент span в качестве следующего элемента, в котором отображается мое сообщение проверки, и поэтому директива в качестве атрибута добавляется к каждому элементу управления вводом.
У меня также есть (необязательно) класс css .has-focus и has-visit в моем файле css, на который вы видите ссылку в директиве.
ПРИМЕЧАНИЕ: не забудьте добавить 'on-blur-val' именно таким образом в ваш элемент управления вводом без апострофов.
источник
Используя ng-focus, вы можете достичь своей цели. вам нужно указать ng-focus в поле ввода. И при написании производных ng-show вы также должны написать логику не равную. Как приведенный ниже код:
<input type="text" class="form-control" name="inputPhone" ng-model="demo.phoneNumber" required ng-focus> <div ng-show="demoForm.inputPhone.$dirty && demoForm.inputPhone.$invalid && !demoForm.inputPhone.$focused"></div>
источник
Мы можем использовать функции onfocus и onblur. Было бы просто и лучше.
<body ng-app="formExample"> <div ng-controller="ExampleController"> <form novalidate class="css-form"> Name: <input type="text" ng-model="user.name" ng-focus="onFocusName='focusOn'" ng-blur="onFocusName=''" ng-class="onFocusName" required /><br /> E-mail: <input type="email" ng-model="user.email" ng-focus="onFocusEmail='focusOn'" ng-blur="onFocusEmail=''" ng-class="onFocusEmail" required /><br /> </form> </div> <style type="text/css"> .css-form input.ng-invalid.ng-touched { border: 1px solid #FF0000; background:#FF0000; } .css-form input.focusOn.ng-invalid { border: 1px solid #000000; background:#FFFFFF; } </style>
Попробуйте здесь:
http://plnkr.co/edit/NKCmyru3knQiShFZ96tp?p=preview
источник