使用AngularJS,我可以使用ng-pristine
或ng-dirty
来检测用户是否已输入该字段。但是,我想在用户离开字段区域后才进行客户端验证。这是因为当用户输入电子邮件或电话等字段时,他们总是会在完成输入完整的电子邮件之前收到错误,这不是最佳的用户体验。
更新
Angular现在附带自定义模糊事件: https://docs.angularjs.org/api/ng/directive/ngBlur
答案 0 :(得分:92)
从版本1.3.0开始,可以使用$touched
轻松完成,在用户离开该字段后这是真的。
<p ng-show="form.field.$touched && form.field.$invalid">Error</p>
https://docs.angularjs.org/api/ng/type/ngModel.NgModelController
答案 1 :(得分:75)
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'}”将更新并验证 只有在控制失去焦点之后。您可以使用a设置多个事件 空格分隔列表。即ng-model-options =“{updateOn:'mousedown 模糊'}“
去抖动
您可以使用去抖键延迟模型更新/验证 使用ngModelOptions指令。这种延迟也适用于 解析器,验证器和模型标志,如$ dirty或$ pristine。
即。 ng-model-options =“{debounce:500}”将等待半秒钟 自触发模型更新之前的最后一次内容更改 表格验证。
答案 2 :(得分:32)
我通过扩展@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可用于为用户提供更好的体验。
答案 3 :(得分:16)
我设法用一个非常简单的CSS来做到这一点。这确实要求错误消息是它们所涉及的输入的兄弟,并且它们具有error
类。
:focus ~ .error {
display:none;
}
在满足这两个要求之后,这将隐藏与聚焦输入字段相关的任何错误消息,我认为angularjs应该做的事情。似乎是疏忽。
答案 4 :(得分:4)
关于@lambinator's解决方案......我在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);
答案 5 :(得分:4)
这似乎是在较新版本的角度中作为标准实现的。
在用户专注于经过验证的元素之前和之后,分别设置 ng-untouched 和 ng-touching 类。
<强> CSS 强>
input.ng-touched.ng-invalid {
border-color: red;
}
答案 6 :(得分:2)
为了进一步了解给定答案,您可以使用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>
答案 7 :(得分:2)
基于@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;
}
答案 8 :(得分:2)
你可能会编写一个包装javascript blur()方法的自定义指令(并在触发时运行验证函数);有一个Angular问题有一个样本(以及一个可以绑定到Angular本身不支持的其他事件的泛型指令):
https://github.com/angular/angular.js/issues/1277
如果你不想走那条路,你的另一个选择是在场上设置$ watch,再次填写字段时触发验证。
答案 9 :(得分:2)
以下是使用ng-messages(角度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']);
答案 10 :(得分:1)
使用字段状态 $ touch 已触摸该字段,如下例所示。
<div ng-show="formName.firstName.$touched && formName.firstName.$error.required">
You must enter a value
</div>
答案 11 :(得分:1)
ngularJS 1.3中的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>
答案 12 :(得分:0)
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元素作为下一个元素,这是我的验证消息的显示位置,因此作为属性的指令被添加到每个输入控件。
我在css文件中也有(可选).has-focus和has-visited css类,你看到它在指令中被引用。
注意:请记住以这种方式将'on-blur-val'添加到没有撇号的输入控件
答案 13 :(得分:0)
通过使用 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>
答案 14 :(得分:0)
如果您使用bootstrap 3和lesscss,则可以使用以下较少的代码段启用模糊验证:
:focus ~ .form-control-feedback.glyphicon-ok {
display:none;
}
:focus ~ .form-control-feedback.glyphicon-remove {
display:none;
}
.has-feedback > :focus {
& {
.form-control-focus();
}
}
答案 15 :(得分:0)
我们可以使用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>
试试这里:
答案 16 :(得分:0)
您可以使用ng-class和相关控制器范围的属性动态设置has-error css类(假设您正在使用bootstrap):
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;
};