我正在尝试创建一个将使用ng-pattern属性替换自身的指令。该属性应用于输入元素,但此后元素基本上变得不可用。我无法再在文本框中输入字符。
这是plunkr http://plnkr.co/edit/F6ZQYzxd8Y04Kz8xQmnZ?p=preview
我想我必须在添加属性后错误地编译元素。
app.directive('passwordPattern', ['$compile', function($compile){
return{
compile: function (element, attr){
element.removeAttr('password-pattern');
element.attr('ng-pattern', '/^[\\w\\S]{6,12}$/');
return {
pre: function preLink(scope, iElement, iAttrs, controller) { },
post: function postLink(scope, iElement, iAttrs, controller) {
$compile(iElement)(scope);
}
};
}
};
}]);
对解决方案的任何想法或文本框变得无法使用的原因都将非常值得赞赏。感谢。
答案 0 :(得分:10)
除了priority: 1000
之外,您还需要添加terminal: true
。
问题是没有 terminal: true
,input
指令被编译两次,并且添加了2组更改侦听器,这会引发ngModel
有点指示逻辑。
第一次编译Angular执行时看不到ng-pattern
,因此输入指令不会将validateRegex
解析器添加到其解析器列表中。但是,第二次编译(通过您的$compile(iElement, scope)
)会看到ng-pattern
和做 add validateRegex
解析器。
当您在输入框中输入3
时,请输入first change listener is called并查看号码3
。由于未应用ng-pattern
(这会添加validateRegex $parser
),因此不存在$parsers
,模型会立即更新为3
。
但是,当第二个更改侦听器被调用时,它会看到ng-pattern
并调用validateRegex
,calls ngModel.$setValidity('pattern', false)
和returns {{1} (因为模型永远不应该设置为无效值)。以下是undefined
指令内的踢球者,因为ngModel
的{{1}}以及$viewValue
的新3
为out of sync ,Angular调用输入指令的value
函数,updates the input为空。因此,当您在输入框中输入undefined
(或任何内容)时,它会立即删除,并且似乎已被破坏。
高$render
(如3
)和priority
会阻止输入指令(除非你有一个1000
,否则很可能是其他指令从第一次编译。这很好,因为你想要输入指令来考虑ng-pattern - 而不是没有它。您不希望将多组更改侦听器添加到同一元素中,或者它可能(并且会)导致奇怪的副作用。
答案 1 :(得分:0)
另一种解决方案是覆盖pattern
控制器中$validators
对象的ngModel
属性。
以下是指令中的示例:
angular.module('mymodule')
.directive('mydirective', MyDirective);
function MyDirective() {
return {
restrict: 'A',
require: 'ngModel',
scope: {},
link: function(scope, element, attrs, ngModelController) {
ngModelController.$validators["pattern"] = validatePattern;
function validatePattern(modelValue, viewValue) {
var value = modelValue || viewValue;
return /[0-9]+/.test(value);
}
}
}
}
您可以修改上面的示例以从外部范围接收模式,并使用模式上的scope.$watch
更改验证功能。