If I have an AngularJS directive without a template and I want it to set a property on the current scope, what is the best way to do it?
For example, a directive that counts button clicks:
<button twoway="counter">Click Me</button>
<p>Click Count: {{ counter }}</p>
With a directive that assigns the click count to the expression in the two way attribute:
.directive('twoway', [
'$parse',
function($parse) {
return {
scope: false,
link: function(scope, elem, attrs) {
elem.on('click', function() {
var current = scope.$eval(attrs.twoway) || 0;
$parse(attrs.twoway).assign(scope, ++current);
scope.$apply();
});
}
};
}
])
Is there a better way to do this? From what I've read, an isolated scope would be overkill, but do I need a child scope? And is there a cleaner way to write back to a scope variable defined in the directive attribute other than using $parse
. I just feel like I'm making this too difficult.
Full Plunker here.
Why is an isolate scope overkill? its pretty useful for exactly this kind of thing:
scope: {
"twoway": "=" // two way binding
},
This is a pretty idiomatic angular solution to this problem, so this is what I'd stick with.
I'm surprised no one has mentioned ng-model
, the default directive for doing two-data binding. Maybe it's not so well known, but the linking function has a fourth parameter:
angular.module('directive-binding', [])
.directive('twoway',
function() {
return {
require: '?ngModel',
link: function(scope, elem, attrs, ngModel) {
elem.on('click', function() {
var counter = ngModel.$viewValue ? ngModel.$viewValue : 0
ngModel.$setViewValue(++counter);
scope.$apply();
});
}
};
}
);
On your view
<button twoway ng-model="counter">Click Me</button>
<p>Click Count: {{ counter }}</p>
The fourth parameter is an API for the ngModelController, which has many uses for handling (parsing and formatting, for instance) and sharing data between a directive and a scope.
Here's the updated Plunker.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With