Angularjs $compile之后的ng类奇怪行为
我已作出以下指示:Angularjs $compile之后的ng类奇怪行为,angularjs,angularjs-directive,ng-class,Angularjs,Angularjs Directive,Ng Class,我已作出以下指示: (function () { 'use strict'; angular .module('app.widgets') .directive('zzForminput', formInput); function formInput($compile) { // Usage: // <div zz-forminput></div> fu
(function () {
'use strict';
angular
.module('app.widgets')
.directive('zzForminput', formInput);
function formInput($compile) {
// Usage:
// <div zz-forminput></div>
function setupDom(element) {
var input = element.querySelector("input, textarea, select");
var type = input.getAttribute("type");
var name = input.getAttribute("name");
if (type !== "checkbox" && type !== "radio") {
input.classList.add("form-control");
}
var label = element.querySelector("label");
label.classList.add("control-label");
element.classList.add("form-group");
return name;
}
function addNgClass(form, element, name, $compile, scope) {
var isExistingNgClass = element[0].attributes["data-ng-class"] || element[0].attributes["ng-class"];
if (!isExistingNgClass) {
var ngClass = "{'has-error':" + form.$name + "." + name + ".$invalid && " +
"(" + form.$name + "." + name + ".$dirty || vm.submit), " +
"'has-success':" + form.$name + "." + name + ".$valid && " +
form.$name + "." + name + ".$dirty}";
element.attr("data-ng-class", ngClass);
$compile(element)(scope);
}
}
function link($compile) {
return function (scope, element, attrs, form) {
var name = setupDom(element[0]);
addNgClass(form, element, name, $compile, scope);
}
}
return {
restrict: 'A',
require: '^form',
link: link($compile)
}
}
}());
(函数(){
"严格使用",;
有棱角的
.module('app.widgets')
.指令(“zzForminput”,formInput);
函数formInput($compile){
//用法:
//
函数setupDom(元素){
var input=element.querySelector(“input,textarea,select”);
var type=input.getAttribute(“type”);
var name=input.getAttribute(“name”);
如果(键入!=“复选框”&&type!=“无线电”){
input.classList.add(“表单控件”);
}
var label=element.querySelector(“label”);
label.classList.add(“控制标签”);
元素.classList.add(“表单组”);
返回名称;
}
函数addNgClass(表单、元素、名称、$compile、范围){
var isExistingNgClass=元素[0]。属性[“数据ng类”]| |元素[0]。属性[“ng类”];
如果(!IsExistingClass){
var ngClass=“{'has-error':“+form.$name+”+name+“$invalid&&”+
“(“+form.$name+”+name+“$dirty | | vm.submit),”+
“'has-success':“+form.$name+”+name+“$valid&&”+
表格.$name+“+name+”$dirty}”;
元素属性(“数据ng类”,ngClass);
$compile(元素)(范围);
}
}
函数链接($compile){
返回函数(范围、元素、属性、形式){
var name=setupDom(元素[0]);
addNgClass(表单、元素、名称、$compile、范围);
}
}
返回{
限制:“A”,
要求:“^form”,
链接:链接($compile)
}
}
}());
我将该指令用作:
<div zz-forminput>
<label for="firstName" class="col-md-4">First Name*</label>
<div class="col-md-8">
<input type="text" name="firstName" id="firstName" data-ng-model="vm.userDetails.firstName" required data-ng-maxlength="100">
</div>
</div>
名字*
Angular成功编译标记。当我在输入字段中输入任何文本时,has success不会添加到div。但是当我清除文本框时,has success类将应用到div。现在,当我在输入字段中输入一些文本时,has success将应用到div
请为我提供此问题的解决方案您之所以看到这种奇怪的行为,是因为您如何处理承载指令的元素的内容 发生的情况是,内容(包括输入上的
ng model
指令)被编译两次:一次是在Angular经过DOM时(在编译阶段),一次是在手动调用$compile
服务时(在指令的链接阶段)。这会导致ng model
指令以相同的名称向父窗体控制器注册两次,长话短说会导致一些奇怪的情况
处理内容的正确方法是使用指令的link
功能提供的transclude
功能
transclude: true,
link: function(scope, element, attrs, ctrls, transclude){
transclude(scope, function(clone){
element.append(clone); // clone is the clone of the contents, prebound to scope
}
}
或者,简单地说,通过模板使用
,因为您不需要在那里做任何特殊的事情
transclude: true,
template: '<div ng-transclude></div>`
而且不需要$compile
或transclude
link: function(scope, element, attrs, formCtrl){
var inputName = setupDom(element[0]);
scope.$watch(function(){
return formCtrl[inputName].$valid && formCtrl[inputName].$dirty;
}, function(v){
if (v) element.addClass("has-success");
else element.removeClass("has-success");
});
scope.$watch(function(){
return formCtrl[inputName].$invalid &&
(formCtrl[inputName].$dirty || formCtrl.$submitted);
}, function(v){
if (v) element.addClass("has-error");
else element.removeClass("has-error");
})
}