Should the directive talk to the controller in Angular JS?

I watched a video from John Linkwist 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'm curious about is whether the directive in this example should go back to the controller, or would it be best programming practice to create a service, and then have a conversation with the service? I’m probably still not sure if these are common practices for directives to talk to controllers in this way.

U-video

+7
source share
3 answers

How would i do that

 <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

+6
source

Is this a common practice?

Yes, this is common practice, directives often need access to the $ scope variable for variables and calls (e.g. LoadMoreTweets ).

Even in official documents , they have examples like ..

 scope.$watch(...) 

... fom inside the directive (where the controller can make changes to the observed variable).

This is quite appropriate for the directive to communicate with the controller in this way.

You can even enter the controller itself (and not just the area) into the link method of the directive. Take a look at the “Function Binding” section of http://docs.angularjs.org/guide/directive .

"The controller is common to all directives, which allows directives to use controllers as a communication channel."

But is it possible to use the service?

Of course. The question is why? If you work with a single page (for example, displays tweets), and the controller already has the variable $scope.tweets and $scope.loadMoreTweets , you over-click on things if you try to use the service where it is not needed.

Services, on the other hand, are ideal for widespread data such as user profiles. If your directive needs to access the current user, then it makes sense to do this through the service.

From the docs:

Services

Angular are singletones that perform specific tasks common to web applications, such as the $ http service, which provides low-level access to the browser XMLHttpRequest object.

If you have a task for the whole application that is best suited for a single, be sure to use the service. If you just need to access the $ scope variable from a directive, just talk directly to the controller or raise an event that the controller can respond to.

+4
source

Calling the outer functions of a scope like this is risky because it makes assumptions about the surrounding area. What happens if the directive is used in a different context?

There are more effective strategies [1] that can be used for use with the outside world in a reusable directive:

  • Delaying service dependencies. This is more suitable for system functions. I think this does not apply to your example.
  • Defining a selection region containing some &attr property that is associated with an expression from the outer region. A directive can invoke this expression as a method of its private domain.

As an example of this second strategy, I modified your example. See here in action 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 the sense of avoiding hard dependencies.

+2
source

All Articles