我目前正在将ng-model-options
指令添加到我的多个输入框中以进行去抖动。我的元素看起来像这样:
<input type="text" ng-model="search" ng-model-options="{ debounce: { 'default': 200 } }" />
我想把它放在一个指令中:
我最终希望标记看起来像这样使用debounce
指令:
<input type="text" ng-model="search" debounce />
我试图像这样实现这个指令:
app.directive('debounce', ['$compile', function ($compile) {
return {
restrict: 'A',
replace: false,
link: function (scope, element, attrs) {
element.attr('ng-model-options', "{ debounce: { 'default': 200 } }");
$compile(element.contents())(scope);
}
}
}]);
它似乎会产生正确的HTML,但是去抖动没有做任何事情。我的指令有什么问题?
答案 0 :(得分:1)
为了做同样的事情,你需要添加更高priority
的指令,以避免编译其他指令&amp;将terminal
选项设置为true。这表明当该指令运行时没有其他指令,然后从该指令运行remove
指令属性&amp;添加ng-model-options
以应用去抖动更改。
删除
debounce
属性是必要的,以避免无限编译
<强>指令强>
app.directive('debounce', ['$compile', function ($compile) {
return {
restrict: 'A',
priority: 1,
terminal: true,
compile: function(element, attrs) {
//compile when scope is not linked to the DOM.
element.attr('ng-model-options', "{ debounce: { 'default': 200 } }");
element.removeAttr('debounce'); //this removal is necessary to avoid infinite compile
var compile = $compile(element);
return function (scope, element, attrs) {
var link = compile(scope);
};
}
}
}]);
答案 1 :(得分:1)
实际上你甚至不需要访问该元素。您可以在ngModel控制器的$options
属性中设置选项,并设置如下所需的值:
ctrl.$options = {debounce:{default:300}, updateOnDefault: true};
代码:
.directive('debounce', ['$timeout',
function($timeout) {
return {
restrict: 'A',
require: 'ngModel',
link: function(scope, element, attrs, ctrl) {
var options = ctrl.$options || {};
ctrl.$options = angular.extend(options, {
debounce: {
default: 300
},
updateOnDefault: true
});
}
}
}
]);
angular.module('app', []).directive('debounce', ['$timeout',
function($timeout) {
return {
restrict: 'A',
require: 'ngModel',
replace: false,
link: function(scope, element, attrs, ctrl) {
var options = ctrl.$options || {};
ctrl.$options = angular.extend(options || {}, {
debounce: {
default: 300
},
updateOnDefault: true
});
}
}
}
]).controller('test', function() {
this.callMe = function() {
console.log(this.search);
}
});
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.0/angular.min.js"></script>
<div ng-app="app" ng-controller="test as vm">
<input type="text" ng-model="vm.search" debounce ng-change="vm.callMe()" />
<input type="text" ng-model="vm.search" ng-change="vm.callMe()" ng-model-options="{ debounce: { 'default': 200 } }" />{{vm.search}}
</div>
&#13;
如果您想通过接受去抖动值作为属性来使其更具可配置性,那么:
.directive('debounce', ['$timeout',
function($timeout) {
return {
restrict: 'A',
require: 'ngModel',
link: function(scope, element, attrs, ctrl) {
var options = ctrl.$options || {updateOnDefault: true};
ctrl.$options = angular.extend(options, {
debounce: {
default: +attrs.debounce || 300
}
});
}
}
}
])
答案 2 :(得分:0)
在Angular中,动态添加指令给自己并不是很好。您通过编译处于正确的轨道上,但是ng-model
指令已经在您执行此操作时进行了编译。
由于ngModel
被记录为以优先级1运行,因此您需要同时为terminal
并以优先级2运行,以便ng-model-options
在适当的时间进行关联。
app.directive('debounce', ['$compile', function ($compile) {
return {
restrict: 'A',
priority: 2,
terminal: true,
compile: function(tElement) {
tElement.attr('ng-model-options', "{ debounce: { 'default': 200 } }");
return function (scope, element, attrs, controllers, transclude) {
$compile(element, null, 2)(scope, {
parentBoundTranscludeFn: transclude
});
};
}
}
}]);