AngularJS 自定义表单验证指令在我的模态中不起作用 [英] AngularJS custom form validation directive doesn't work in my modal
问题描述
我决定编写一个自定义指令来帮助我验证我的输入框.这个想法是我将新的 nx-validate
指令添加到引导程序 div.form-group
中,它会检查我的 <input/>
是 $dirty
或 $invalid
并应用 .has-success
或 .has-error
> 按要求上课.
出于某种奇怪的原因,我的指令在正常情况下运行良好,但是在 ui-bootstrap 模式中完全忽略了添加的 ng-class
.
模态和表单中的代码相同
还有我可爱的指令
nitro.directive("nxValidate", function($compile) {返回 {限制:'A',优先级:2000,编译:函数(元素){var 节点 = 元素;while (node && node[0].tagName != 'FORM') {console.log (node[0].tagName)节点 = node.parent();}if (!node) console.error("没有表单节点作为父节点");var formName = node.attr("name");if (!formName) console.error("Form 需要一个 name 属性");var label = element.find("label");var input = element.find("输入");var inputId = input.attr("id")if (!label.attr("for")) {label.attr("for", inputId);}if (!input.attr("name")) {input.attr("name", inputId);}如果(!input.attr(占位符")){input.attr("占位符", 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);返回函数($scope){fn($scope);}}}});
在 plunker 上查看:http://plnkr.co/edit/AjvNi5e6hmXcTgpXgTlH?>
我建议你最简单的方法是你可以通过在这些字段上使用 watch 来放置这些类,这个 watcher
会在里面编译DOM后的postlink
函数
返回函数($scope, element) {fn($scope);$scope.$watch(function(){返回 $scope.modalForm.name.$invalid &&$scope.modalForm.name.$touched;},函数(新值){如果(新值)element.addClass('有错误');别的element.removeClass('有错误');})$scope.$watch(function(){返回 $scope.modalForm.name.$valid &&$scope.modalForm.name.$touched;},函数(新值){如果(新值)element.addClass('已成功');别的element.removeClass('已成功');})}
更新
实际上更好的方法是不是从 compile 编译元素,我们需要 $compile
来自 link
函数本身的元素.使用 $compile
在链接 fn 中编译 DOM 背后的原因是我们的 ng-class
属性确实包含范围变量,类似于 myForm.name.$invalid
,所以当我们 $compile
compile 函数的 DOM 时,它们不会评估 myForm.name.$invalid
变量的值,因为 compile 没有访问权限范围&总是 undefined
或 blank
.因此,虽然在 link
中编译 DOM 将拥有包含 myForm.name.$invalid
的所有范围值,因此在使用指令范围编译后,您将获得 ng-class
指令绑定将起作用.
代码
编译:函数(元素){//..其他代码将保持原样..element.removeAttr("nx-validate");//var fn = $compile(element);//从编译fn中删除这一行返回函数($scope,元素){//fn($scope);$compile(element)($scope);//在postLink中添加以编译dom以获得绑定工作}}
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.
For some odd reason, my directive works perfectly under normal circumstances, but the added ng-class
is completely ignored inside a ui-bootstrap modal.
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?
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
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.
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
}
}
这篇关于AngularJS 自定义表单验证指令在我的模态中不起作用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!