I know that a $scope
from a controller
can be shared to a link function in directives
.
For example, in this code I can call a function from declared controller to print 'Hello World' on browser console:
.directive('myDirective', [function () {
return {
restrict : 'E',
replace : true,
controller: 'MyController',
templateUrl : 'directives/myDirective.tpl.html',
link : function (scope, elem, attrs, controller) {
scope.message = 'Hello World!';
}
};
}])
.controller('MyController', [function ($scope, $element, $attrs, $log, $timeout) {
// $timeout to wait the link function to be ready.
$timeout(function () {
// This prints Hello World as expected.
$log.debug($scope.message);
});
});
}])
Ok, this works fine.
My questions are:
DOM
elements in controller
, only in link function
.controller
? Even if the $scope
, $elem
, etc are the same?These are questions that I didn't find on Angular Directive documentation.
Here's a plunker with the sample code.
AngularJS ng-controller Directive The ng-controller directive adds a controller to your application. In the controller you can write code, and make functions and variables, which will be parts of an object, available inside the current HTML element. In AngularJS this object is called a scope.
You just create a myVar variable in your controller and pass it to the directive using my-var attribute. Since you are using two way binding, any changes made to myVar by the directive are available in your controller.
A controller is usually used to contain and maintain the logic for your view, which gets bound to your view via $scope. A directive is something that you might use repeatedly and is called in your view directly through the directive name which you can pass in as an attribute.
Answer:The link option is just a shortcut to setting up a post-link function. controller: The directive controller can be passed to another directive linking/compiling phase. It can be injected into other directices as a mean to use in inter-directive communication.
In this approach, it is the SAME scope that will shared between the controller and the directive?
Yes, it is.
What is the consequences to use this approach? Let us assume that I will not manipulate DOM elements in controller, only in link function.
The controller is what provides the directive's behavior, just like with a regular Angular application. That said, you should manipulate the scope inside the controller function only. If you need to change the scope from the link function, call a method of it. Besides, since the controller is executed before the link function, you should initialized the scope in the former so the latter can get a valid model to work on.
I really need to avoid manipulate DOM elements in this controller? Even if the $scope, $elem, etc are the same?
By definition, the link function is the place to perform DOM manipulation. I can't find a technical reason that would prevent you from manipulating the DOM inside the directive's controller except that you shouldn't. In fact, in order to check that I've just changed one directive I've written and moved all the code from the link function to the controller function and everything's kept working. But if you mix both scope logic and DOM manipulation together I think it'll be hard to track down what's going on.
Finally, you may find this article useful: Understanding Directives.
1) Yes they both share the same scope, because you are using the controller of the directive to log the scope, which means you can put the 'MyController' inside of the directive like so
return {
replace: true,
controller: function($scope,...){ // equals MyController
}
}
If the controller is a wrapper of the directive instead of inside it and the directive scope is set to true or an object hash, then they wont share the same scope.
2) No consequences, just DO NOT manipulate DOM in the controller, one of uses of the controller is to connect the directives together to get or set data from perhaps a service or by a simple augmentation of the scope (ie: scope.message = "Hello World") either way they need to be minimal. The way you have it setup is ideal if you want to share data amongst other directives you can simply require this directive's controller.
3) Yes avoid DOM manipulation in the controller, its not meant for presentation logic or what the user sees, that is the role of the directives, remember SOC(separation of concerns) each part of the MVC/MV* pattern has its own roll to play.
Think of it in a simple way like this user sees button on presentation layer, user clicks button a function for the click of the button occurs on the business layer (controller) that takes the results and stores in the data/model layer.
Caveat if the button does anything other than process a command (calculations,evaluations,etc) between user and data layer, such as adding classes (DOM manipulation) that function belongs inside a directive.
A great read and more in depth here
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