I'm currently adding the ng-model-options
directive to a number of my input boxes to debounce. My elements look like this:
<input type="text" ng-model="search" ng-model-options="{ debounce: { 'default': 200 } }" />
I would like to put this in a directive so:
I ultimately want the markup to look like this where it uses a debounce
directive:
<input type="text" ng-model="search" debounce />
I've attempted to implement this directive like so:
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);
}
}
}]);
It appears to result in the correct HTML, but the debounce is not doing anything. What is wrong with my directive?
Actually you dont need to even access the element. you can set the options in the ngModel controller's $options
property and set the necessary values like this:
ctrl.$options = {debounce:{default:300}, updateOnDefault: true};
Code:
.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);
}
});
<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>
If you want to make it more configurable by accepting a debounce value as attribute then:
.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
}
});
}
}
}
])