通过AngularJS,我可以使用ng-pristine
或ng-dirty
检测用户是否输入了该字段。但是,我只想在用户离开字段区域之后进行客户端验证。这是因为,当用户输入电子邮件或电话之类的字段时,他们总是会抛出错误,直到他们完成完整的电子邮件键入为止,这不是最佳的用户体验。
更新:
Angular现在附带了一个自定义模糊事件:https : //docs.angularjs.org/api/ng/directive/ngBlur
通过AngularJS,我可以使用ng-pristine
或ng-dirty
检测用户是否输入了该字段。但是,我只想在用户离开字段区域之后进行客户端验证。这是因为,当用户输入电子邮件或电话之类的字段时,他们总是会抛出错误,直到他们完成完整的电子邮件键入为止,这不是最佳的用户体验。
更新:
Angular现在附带了一个自定义模糊事件:https : //docs.angularjs.org/api/ng/directive/ngBlur
Answers:
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
默认情况下,对内容的任何更改都会触发模型更新和表单验证。您可以使用ngModelOptions指令覆盖此行为,使其仅绑定到指定的事件列表。即ng-model-options =“ {updateOn:'blur'}”仅在控件失去焦点后才会更新和验证。您可以使用空格分隔的列表设置多个事件。即ng-model-options =“ {updateOn:'mousedown blur'}”
并反跳
您可以通过将去抖动键与ngModelOptions指令一起使用来延迟模型的更新/验证。此延迟还将适用于解析器,验证器和模型标志,例如$ dirty或$ pristine。
即ng-model-options =“ {debounce:500}”自上次内容更改以来将等待半秒钟,然后触发模型更新和表单验证。
ng-change
在用户离开该字段之前接收事件。例如,在我的情况下,只要输入字段有效,我就立即从API请求新数据,但我不想在无效时立即显示错误消息-我只想在输入错误时执行此操作无效,并且发生了模糊事件。
从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;
}
在元素仍然获得$ invalid属性等的情况下,此方法效果很好,但是CSS可用于为用户提供更好的体验。
formName.inputName.$dirty
。我建议编辑指令以编写类似的布尔值like formName.inputName.$focused
,而不是使用类名进行模糊处理,并使用布尔值进行验证。
关于@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);
您可能需要编写一个包含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']);
AngularJS 1.3(撰写本文时为beta版)中的ng-model-options被记录为支持{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>
您可以使用ng-class和关联控制器范围内的属性来动态设置has-error css类(假设您正在使用引导程序):
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;
};
我使用了指令。这是代码:
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和已访问过的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>
试试这里: