Проверять поля после того, как пользователь покинул поле
С помощью AngularJS я могу использовать ng-pristine
или ng-dirty
, чтобы определить, введен ли пользователь в поле. Тем не менее, я хочу сделать проверку на стороне клиента только после того, как пользователь покинул поле. Это связано с тем, что, когда пользователь входит в поле, такое как электронная почта или телефон, они всегда будут получать ошибки, пока они не завершат заполнение полного сообщения электронной почты, и это не оптимальный пользовательский интерфейс.
Пример
UPDATE:
Angular теперь поставляется с настраиваемым событием размытия:
https://docs.angularjs.org/api/ng/directive/ngBlur
Ответы
Ответ 1
Angular 1.3 теперь имеет параметры ng-model, и вы можете, например, установить параметр { 'updateOn': 'blur'}
, и вы даже можете отбросить, когда использование будет слишком набирать слишком быстро, или вы хотите сохранить несколько дорогостоящие операции DOM (например, запись модели в несколько мест DOM, и вы не хотите, чтобы на каждом нажатии клавиши выполнялся цикл $digest)
https://docs.angularjs.org/guide/forms#custom-triggers и https://docs.angularjs.org/guide/forms#non-immediate-debounced-model-updates
По умолчанию любое изменение содержимого приведет к обновлению модели и проверка формы. Вы можете переопределить это поведение, используя Директива ngModelOptions связывается только с указанным списком событий. То есть ng-model-options = "{updateOn: 'blur'}" будет обновлять и проверять только после того, как управление теряет фокус. Вы можете установить несколько событий, используя Список разделенных пробелами. То есть ng-model-options = "{updateOn: 'mousedown blur '}"
И debounce
Вы можете задержать обновление/проверку модели с помощью ключа debounce с директивой ngModelOptions. Эта задержка будет также применяться к парсеров, валидаторов и флагов модели, таких как $грязный или $чистый.
т.е. ng-model-options = "{debounce: 500}" будет ждать полсекунды поскольку последнее изменение содержимого перед запуском обновления модели и проверка формы.
Ответ 2
Из версии 1.3.0 это можно легко сделать с помощью $touched
, который является истинным после того, как пользователь покинул поле.
<p ng-show="form.field.$touched && form.field.$invalid">Error</p>
https://docs.angularjs.org/api/ng/type/ngModel.NgModelController
Ответ 3
Я решил это, расширив то, что предложил @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 можно использовать, чтобы дать пользователю лучший опыт.
Ответ 4
Мне удалось сделать это с помощью довольно простого фрагмента CSS. Это требует, чтобы сообщения об ошибках были братьями и сестрами ввода, к которому они относятся, и что у них есть класс error
.
:focus ~ .error {
display:none;
}
После выполнения этих двух требований это скроет любое сообщение об ошибке, связанное с целенаправленным полем ввода, что, по-моему, должно быть в любом случае. Похоже на надзор.
Ответ 5
Что касается решения @lambinator... Я получил следующую ошибку в angular.js 1.2.4:
Ошибка: [$ rootScope: inprog] $digest уже выполняется
Я не уверен, что я сделал что-то неправильно или это изменение в 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);
Ответ 6
Это, по-видимому, реализовано как стандарт в новых версиях angular.
Классы ng-нетронутые и ng-touched установлены соответственно до и после того, как пользователь сосредоточился на проверенном элементе.
CSS
input.ng-touched.ng-invalid {
border-color: red;
}
Ответ 7
Может возникнуть необходимость написать специальную директиву, которая обертывает метод javascript blur() (и запускает функцию проверки при срабатывании); существует проблема Angular, которая имеет образец один (а также общую директиву, которая может связываться с другими событиями, не поддерживаемыми изначально Angular):
https://github.com/angular/angular.js/issues/1277
Если вы не хотите идти по этому маршруту, другим вариантом будет установка $watch в поле, снова запускающее проверку, когда поле будет заполнено.
Ответ 8
Чтобы получить дополнительные ответы на эти ответы, вы можете упростить ввод тегов с помощью псевдоклассов 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>
Ответ 9
на основе @nicolas answer.. Чистый 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;
}
Ответ 10
Вот пример использования ng-сообщений (доступно в 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']);
Ответ 11
ng-model-options в 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>
Ответ 12
Вы можете динамически установить класс css has-error (при условии, что вы используете загрузку), используя ng-класс и свойство в области действия связанного контроллера:
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;
};
Ответ 13
Если вы используете bootstrap 3 и lesscss, вы можете включить проверку blur с помощью следующего менее фрагмента:
:focus ~ .form-control-feedback.glyphicon-ok {
display:none;
}
:focus ~ .form-control-feedback.glyphicon-remove {
display:none;
}
.has-feedback > :focus {
& {
.form-control-focus();
}
}
Ответ 14
outI использовал директиву. Вот код:
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 в качестве следующего элемента, в котором отображается мое сообщение проверки, и поэтому директива как атрибут добавляется к каждому элементу управления вводом.
У меня также есть (необязательный).has-focus и has-visited css-класс в моем файле css, который вы видите ссылкой в директиве.
ПРИМЕЧАНИЕ: не забудьте добавить "on-blur-val" именно таким образом к вашему вводу без апострофов
Ответ 15
Используя 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>
Ответ 16
Мы можем использовать функции 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
Ответ 17
Использовать полевое состояние $коснулось. Поле коснулось для этого, как показано ниже.
<div ng-show="formName.firstName.$touched && formName.firstName.$error.required">
You must enter a value
</div>