I have been watching the videos by John Linquist and in one video he gives this as an example:
var app = angular.module('twitterApp', [])
app.controller("AppCtrl", function ($scope) {
$scope.loadMoreTweets = function () {
alert("Loading tweets!");
}
}
app.directive("enter", function() {
return function (scope, element, attrs) {
element.bind("mouseenter", function () {
scope.LoadMoreTweets();
})
}
}
One thing I am wondering about is should the directive in this example talk back to the controller or would it be a better programming practice to create a service and then have the directive talk to a service? I guess I am still not sure if it is common practices for directives to talk to controllers in this way.
U tube video
How I would have done it
<span enter="loadMoreTweets()">Something</span>
JS
app.controller('AppController', function ($scope) {
$scope.loadMoreTweets = function () {
console.log("Loading tweets!");
}
})
app.directive("enter", function() {
return {
link: function (scope, element, attrs) {
element.bind("mouseenter", function () {
scope.$apply(attrs.enter)
})
}
}
});
Demo: Plunker
Another way to achieve the same
app.directive("enter", function() {
return {
scope: {
callback: '&enter'
},
link: function (scope, element, attrs) {
element.bind("mouseenter", function () {
scope.$apply('callback()')
})
}
}
});
Demo: Plunker
Is it common practice?
Yes that is common practice, directives frequently need to access the $scope for variables, and to call methods (like LoadMoreTweets
).
Even in the official docs they have examples like..
scope.$watch(...)
...fom inside a directive (where the controller might be making changes to the watched variable).
It is entirely appropriate for a directive to communicate with a controller in this way.
You can even inject a controller itself (not just the scope) into the link
method of a directive. Looks at the "Linking function" section of http://docs.angularjs.org/guide/directive.
"The controller is shared among all the directives, which allows the directives to use the controllers as a communication channel."
But could I use a service?
Sure you could. The question is why? If you are working with a single page (that displays tweets for example) and the controller already has a $scope.tweets
variable and $scope.loadMoreTweets
method, you are overcomplicating things if you try to stick a service in there where it's not needed.
On the other hand services are perfect for application wide data, like user profile. If your directive needed to access the currently logged in user, then it makes a lot of sense to do that via service.
From the docs:
Angular services are singletons that carry out specific tasks common to web apps, such as the $http service that provides low level access to the browser's XMLHttpRequest object.
If you have a application-wide task that is best suited for a singleton, by all means use a service. If you just need to access/modify the $scope from a directive, just talk directly to the controller, or trigger an event that the controller can respond to.
Calling outer scope functions like that is risky, because it makes assumptions about the surrounding scope. What would happen if the directive were used in a different context?
There are better[1] strategies that a reusable directive may employ to communicate with the outside world:
&attr
property which is bound to an expression from an outer scope. The directive can call that expression as a method of its private scope.As an example of this second strategy, I've modified your example. See it in action here http://plnkr.co/5uOBNu
var app = angular.module('twitterApp', []);
app.controller("AppCtrl", function ($scope) {
$scope.loadMoreTweets = function() {
alert("Loading tweets!");
};
});
app.directive("specialEnter", function() {
return {
scope: {
onEnter: '&'
},
link: function(scope, element, attrs) {
element.bind("mouseenter", function() {
scope.onEnter();
});
}
};
});
<div ng-controller="AppCtrl">
<div special-enter on-enter="loadMoreTweets()">Hover here!</div>
</div>
[1] "Better" in a sense of avoiding hard-wired dependencies.
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