Reputation: 29149
When binding a callback function to a directive it is important for me to execute this function with the right context. Now, as long as the directive has an isolated scope it is not a problem
<bar-foo callback="mycontroller.callback()"></bar-foo>
and the directive:
...
scope:{
callback: '&'
},
...
Without an isolated scope I extract the callback from the $attrs attrubute
$scope.callback = $parse($attrs.callback)($scope);
But, now I cannot do
<bar-foo callback="mycontroller.callback()"></bar-foo>
Because it will execute the callback directly. What would be the preferred way to solve this ?
Upvotes: 2
Views: 868
Reputation: 48968
In your directive without a scope, just access mycontroller.callback()
in the directive template.
.directive('helloWorld', function () {
return {
restrict: 'E',
scope: false,
//Use THIS
template: '<button ng-click="mycontroller.callback()">Not isolated</button>',
//NOT this
//template: '<button ng-click="callback()">Not isolated</button>',
controller: function ($attrs, $scope, $parse) {
//$scope.callback = $parse($attrs.callback)($scope);
}
}
});
Since the directice has no scope of its own, the template has direct access to the controller which was instantiated with ng-controller="MyCtrl as mycontroller"
.
what if you want to reuse the directive?
In that case, bind a click handler to the element.
.directive('helloWorld', function () {
return {
restrict: 'E',
scope: false,
template: '<button>Not isolated</button>',
link: function (scope, elem, attrs) {
elem.on("click", function(e) {
scope.$eval(attrs.callback, {$event: e});
});
}
}
});
When the directive's element is clicked the Angular expression defined by the callback
attribute will be evaluated with the event object exposed as $event
.
For more information on $event
, see AngularJS Developer Guide -- $event.
Upvotes: 0
Reputation: 2954
As this scope isn't isolated isn't just a case of calling what you want?
.directive('helloWorld', function () {
return {
restrict: 'E',
template: '<button ng-click="mycontroller.callback()">Not isolated</button>',
}
});
and then just calling your directive?
<hello-world></hello-world>
Or am I missing something here?? Specifying the controller with the require attribute is also desirable.
Upvotes: 0
Reputation: 24551
First create a function in your controller which explicitly sets the value of this
inside of this function:
this.exportableCallback = this.callback.bind(this);
where this.callback
is the one you use for the isolated scope.
Second step is setting it as an attribute
<hello-world callback="mycontroller.exportableCallback"></hello-world>
where you do not call the function like you did with isolated scope.
See fiddle.
Another option (if you remove this.callback
from your controller) is
this.exportableCallback = function() {
console.log(this.test);
}.bind(this);
If you want to pass arguments to this function:
this.exportableCallback = function() {
console.log(arguments);
}.bind(this);
Upvotes: 2