I decided to write a custom directive to help me validate my input boxes. The idea is that I add my new fancy nx-validate
directive to a bootstrap div.form-group
and it'll check whether my <input/>
is $dirty
or $invalid
and apply the .has-success
or .has-error
class as required.
我决定编写一个自定义指令来帮助我验证输入框。我的想法是将新的nx-validate指令添加到bootstrap div.form-group中,它将检查我的是$dirty还是$invalid,并根据需要应用.has-success或.has-error类。
For some odd reason, my directive works perfectly under normal circumstances, but the added ng-class
is completely ignored inside a ui-bootstrap modal.
由于某些奇怪的原因,我的指令在正常情况下可以完美地工作,但是在ui-bootstrap模式中,添加的ng类完全被忽略。
Identical code in both the modal and the form
模态代码和形式代码相同
<form name="mainForm">
<div class="row">
<div nx-validate class="form-group has-feedback col-lg-6 col-md-6 col-xs-12">
<label class="control-label">Green if long enough, red if not</label>
<input type="text" id="name" class="form-control" ng-model="property.name" required="required" ng-minlength="5"/>
(once touched I do change colour - happy face)
</div>
</div>
And my lovely directive
和我可爱的指令
nitro.directive("nxValidate", function($compile) {
return {
restrict: 'A',
priority: 2000,
compile: function(element) {
var node = element;
while (node && node[0].tagName != 'FORM') {
console.log (node[0].tagName)
node = node.parent();
}
if (!node) console.error("No form node as parent");
var formName = node.attr("name");
if (!formName) console.error("Form needs a name attribute");
var label = element.find("label");
var input = element.find("input");
var inputId = input.attr("id")
if (!label.attr("for")) {
label.attr("for", inputId);
}
if (!input.attr("name")) {
input.attr("name", inputId);
}
if (!input.attr("placeholder")) {
input.attr("placeholder", label.html());
}
element.attr("ng-class", "{'has-error' : " + formName + "." + inputId + ".$invalid && " + formName + "." + inputId + ".$touched, 'has-success' : " + formName + "." + inputId + ".$valid && " + formName + "." + inputId + ".$touched}");
element.removeAttr("nx-validate");
var fn = $compile(element);
return function($scope) {
fn($scope);
}
}
}
});
Check it out on plunker: http://plnkr.co/edit/AjvNi5e6hmXcTgpXgTlH?
在plunker: http://plnkr.co/edit/ajvni5e6hmxctxgtlh?
1 个解决方案
#1
3
The simplest way I'd suggest you is you can put those classes by using watch on those fields, this watcher
will lie inside the postlink
function after compiling a DOM
我建议您的最简单的方法是,您可以通过在这些字段上使用watch来放置这些类,在编译DOM之后,这个监视程序将位于postlink函数中
return function($scope, element) {
fn($scope);
$scope.$watch(function(){
return $scope.modalForm.name.$invalid && $scope.modalForm.name.$touched;
}, function(newVal){
if(newVal)
element.addClass('has-error');
else
element.removeClass('has-error');
})
$scope.$watch(function(){
return $scope.modalForm.name.$valid && $scope.modalForm.name.$touched;
}, function(newVal){
if(newVal)
element.addClass('has-success');
else
element.removeClass('has-success');
})
}
演示
Update
更新
The actual better way of doing this would be instead of compiling element from compile, we need $compile
the element from the link
function itself. The reason behind the compiling DOM in link fn using $compile
is that our ng-class
attribute does contain the scope variable which is like myForm.name.$invalid
,so when we $compile
the DOM of compile function then they are not evaluating value of myForm.name.$invalid
variable because compile don't have access to scope & the would be always undefined
or blank
. So while compile DOM inside the link
would have all the scope values are available that does contain myForm.name.$invalid
so after compiling it with directive scope you will get your ng-class
directive binding will work.
这样做的更好方法是不从编译中编译元素,而是需要从link函数本身编译元素。编译DOM的原因使用美元编译链接fn ng-class属性包含范围变量,就像myForm.name。美元是无效的,所以当我们编译编译函数的DOM美元然后他们不是myForm.name评价值。$无效变量因为编译没有访问范围&就总是定义或空白。因此,虽然在链接内编译DOM时,所有包含myForm.name的作用域值都是可用的,$invalid所以在使用指令作用域编译它之后,您将得到您的ng类指令绑定。
Code
代码
compile: function(element) {
//..other code will be as is..
element.removeAttr("nx-validate");
//var fn = $compile(element); //remove this line from compile fn
return function($scope, element) {
//fn($scope);
$compile(element)($scope); //added in postLink to compile dom to get binding working
}
}
更新Plunkr
#1
3
The simplest way I'd suggest you is you can put those classes by using watch on those fields, this watcher
will lie inside the postlink
function after compiling a DOM
我建议您的最简单的方法是,您可以通过在这些字段上使用watch来放置这些类,在编译DOM之后,这个监视程序将位于postlink函数中
return function($scope, element) {
fn($scope);
$scope.$watch(function(){
return $scope.modalForm.name.$invalid && $scope.modalForm.name.$touched;
}, function(newVal){
if(newVal)
element.addClass('has-error');
else
element.removeClass('has-error');
})
$scope.$watch(function(){
return $scope.modalForm.name.$valid && $scope.modalForm.name.$touched;
}, function(newVal){
if(newVal)
element.addClass('has-success');
else
element.removeClass('has-success');
})
}
演示
Update
更新
The actual better way of doing this would be instead of compiling element from compile, we need $compile
the element from the link
function itself. The reason behind the compiling DOM in link fn using $compile
is that our ng-class
attribute does contain the scope variable which is like myForm.name.$invalid
,so when we $compile
the DOM of compile function then they are not evaluating value of myForm.name.$invalid
variable because compile don't have access to scope & the would be always undefined
or blank
. So while compile DOM inside the link
would have all the scope values are available that does contain myForm.name.$invalid
so after compiling it with directive scope you will get your ng-class
directive binding will work.
这样做的更好方法是不从编译中编译元素,而是需要从link函数本身编译元素。编译DOM的原因使用美元编译链接fn ng-class属性包含范围变量,就像myForm.name。美元是无效的,所以当我们编译编译函数的DOM美元然后他们不是myForm.name评价值。$无效变量因为编译没有访问范围&就总是定义或空白。因此,虽然在链接内编译DOM时,所有包含myForm.name的作用域值都是可用的,$invalid所以在使用指令作用域编译它之后,您将得到您的ng类指令绑定。
Code
代码
compile: function(element) {
//..other code will be as is..
element.removeAttr("nx-validate");
//var fn = $compile(element); //remove this line from compile fn
return function($scope, element) {
//fn($scope);
$compile(element)($scope); //added in postLink to compile dom to get binding working
}
}
更新Plunkr