我正在创建一个smart input
指令,它将包装一个文本输入元素,并且需要访问input元素上的模型才能操作指令上的某些类。
因为输入元素可以是多种类型之一(文本,电子邮件,密码),我需要转换该指令并能够为每个类型添加不同类型的验证。
我遇到的问题(与互联网上的许多其他人一样)是范围继承。
以下是我目前的代码
的 HTML
<smart-input ng-model="username">
<span ng-show="isTyping">{{ placeholder }}</span>
<input type="text" name="username" ng-model="username" ng-minlength="4" ng-maxlength="20" required />
</smart-input>
JS
angular.module('myApp').directive('smartInput', function ($compile) {
return {
restrict: 'E',
transclude: true,
replace: true,
scope: {
model: '=ngModel'
},
template: '<div class="text-input" ng-class="{typing: isTyping}" ng-transclude>' +
'</div>',
link: function(scope, element, attrs) {
scope.isTyping = false;
scope.$watch('model', function(value) {
console.log(value);
scope.isTyping = value.length > 0;
});
}
};
});
基本上,$ watch函数中的value
是未定义的,所以很明显我没有这样做。
那么,如何将模型绑定到输入字段,同时让指令引用同一个对象并且能够watch
它的值?
答案 0 :(得分:0)
当您使用隔离范围进行转换时,您的范围没有父/子关系。它看起来像这样:
<controllerScope>
<smartInputScope>
<transcludedContentScope>
这就是为了访问smartInputScope的model
属性,我们必须访问$$prevSibling.model
在您的第一个示例中ng-model="username"
有效,因为此范围继承自controllerScope,它正在访问父级的范围属性。
使用自定义转换检查我的解决方案:http://plnkr.co/edit/cV9urKJdcn4mKlpqPJTr?p=preview
app.directive('smartInput', function($compile) {
return {
restrict: 'E',
transclude: true,
replace: true,
scope: {
model: '=ngModel'
},
template: '<div class="text-input" ng-class="{typing: isTyping}">' +
'</div>',
compile: function(element, attr, linker) {
return {
pre: function(scope, element, attr) {
linker(scope, function(clone) { //bind the scope your self
element.append(clone); // add to DOM
});
},
post: function postLink(scope, iElement, iAttrs) {
scope.isTyping = false;
scope.$watch('model', function(value) {
console.log(value);
scope.isTyping = value.length > 0;
});
}
};
}
};
});
在html中,我不再需要$$prevSibling
:
<input type="text" name="username" ng-model="model" ng-minlength="4" ng-maxlength="20" required />