我有一个AngularJS指令,我正在尝试使用延迟表单字段验证,无论是模糊还是空闲(一段时间没有输入)。我有两种接线方式;一种是在实际输入字段上添加一个类,另一种是在范围上设置状态变量。设置类可以用于样式化字段,但是我更关心样式化(ng-显示)帮助消息,这是在一个不相关的元素上。加上类可以添加ng-class,所以我想要的方法似乎应该是状态变量属性检查。
我的问题:
<form name="f">
<div class="form-group" ng-class="{'has-error': f.e.$invalid}">
<label>Enter Email Address</label>
<input type="email" class="form-control" name="e" ng-model="user.email" required autofocus active="1500" is-active="state.active"/>
<p class="help-block" ng-show="!state.active && f.e.$error.required">email is required</p>
<p class="help-block" ng-show="!state.active && f.e.$error.email">enter a valid email address</p>
<p class="help-block" ng-show="state.active">typing...</p>
<p class="help-block" ng-show="!state.active && f.$valid">ok!</p>
</div>
</form>
相关指令......
app.directive('active', ['$parse', function ($parse) {
var tid;
return {
restrict: 'A',
require: '?ngModel',
scope:
{
isActive: "=",
ngModel: "="
},
link: function (scope, elem, attrs, ctrl) {
elem.bind('blur', function()
{
scope.isActive = false;
elem.removeClass("ng-active");
});
var timeout = attrs.active || 2000;
ctrl.$parsers.unshift(function(value)
{
scope.isActive = true;
console.log("adding class");
elem.addClass("ng-active");
if (tid) clearTimeout(tid);
tid = setTimeout(function()
{
console.log("timeout elapsed, removing class");
scope.$apply(function(){
scope.isActive = false;
});
elem.removeClass("ng-active")
}, timeout);
return value;
})
}
};
}]);
//myApp.directive('myDirective', function() {});
//myApp.factory('myService', function() {});
function TestCtrl($scope)
{
$scope.testName = "Validation Test";
$scope.user = {
email: 'test@foo.com'
};
$scope.state = {
active: false
};
}
这是a fiddle of this code running
基本上,它可以工作,但我不喜欢我必须为每个输入字段传入一个外部属性,我不喜欢验证检查的不对称性。有没有更好的方法呢?
答案 0 :(得分:1)
您可以尝试:ngModelController.$setValidity
app.directive('active', ['$parse', function ($parse) {
var tid;
return {
restrict: 'A',
require: '?ngModel',
scope:
{
ngModel: "="
},
link: function (scope, elem, attrs, ctrl) {
elem.bind('blur', function()
{
scope.$apply(function(){
ctrl.$setValidity("active",true);
});
});
var timeout = attrs.active || 2000;
ctrl.$parsers.unshift(function(value)
{
ctrl.$setValidity("active",false);
console.log("adding class");
if (tid) clearTimeout(tid);
tid = setTimeout(function()
{
ctrl.$setValidity("active",false);
}, timeout);
return value;
})
}
};
}]);
1)像这样设置活动:ctrl.$setValidity("active",true);
。
2)从html访问:f.e.$error.active
。
3)请注意,当我们使用此功能时:ctrl.$setValidity("active",true);
表示active
=&gt;没有错误f.e.$error.active == true
(有点颠倒你当前的逻辑)
另一个解决方案是直接将属性添加到你的ngModelController:ctrl.active = false;
并在html中访问它,如:f.e.active
。但是这个解决方案不是很好的IMO,因为当角度决定创建一个具有相同名称的新属性时,它可能会与角度的未来版本发生碰撞。
答案 1 :(得分:1)
在@Khanh TO(第二)回答的基础上,我已经更新了小提琴,以便更接近我的原创并删除一些拼写错误。然后,我使用公开状态根据需要使用ng-class设置帮助文本和输入字段的样式。
对于后代,HTML的相关部分:
<form name="f">
<div class="form-group" ng-class="{'has-error': !f.e.active && f.e.$invalid}">
<label>Enter Email Address</label>
<input type="email" ng-class="{'active' : f.e.active}" class="form-control" name="e" ng-model="user.email" required autofocus active="1500" />
<p class="help-block" ng-show="!f.e.active && f.e.$error.required">email is required</p>
<p class="help-block" ng-show="!f.e.active && f.e.$error.email">enter a valid email address</p>
<p class="help-block" ng-show="f.e.active">typing...</p>
<p class="help-block" ng-show="!f.e.active && f.$valid">ok!</p>
</div>
</form>
和JS:
app.directive('active', ['$parse', function ($parse) {
var tid;
return {
restrict: 'A',
require: '?ngModel',
// warning - this adds an "active" property to ctrl; consider prefixing to avoid future collisions
link: function (scope, elem, attrs, ctrl) {
elem.bind('blur', function()
{
ctrl.active = false;
});
var timeout = attrs.active || 2000;
ctrl.$parsers.unshift(function(value)
{
ctrl.active = true;
if (tid) clearTimeout(tid);
tid = setTimeout(function()
{
scope.$apply(function(){
ctrl.active = false;
});
}, timeout);
return value;
})
}
};
}]);