In AngularJS, I've noticed that a controller is injected with $element
, which is a JQuery/JQLite wrapper of the element the controller is controlling. For example:
<body ng-controller="MainCtrl">
Then you can have access to the body element in the controller by injecting $element
app.controller('MainCtrl', function($scope, $element) { ...
This can be seen working at this Plunkr.
And seems to be confirmed as a deliberate feature in the docs for $compile
My questions are:
In the light of the various guides and tutorials that suggest you shouldn't access the DOM in a controller, why is this even possible?
Is there any non-hacky use case for this?
Are there any examples of this being used in available code somewhere?
Thanks.
Injecting a value into an AngularJS controller function is done simply by adding a parameter with the same name as the value (the first parameter passed to the value() function when the value is defined).
26) Which of the following components can be injected as a dependency in AngularJS? Answer: D is the correct answer. The "Application Module" can be injected as a dependency in AngularJS.
Dependency Injection is pervasive throughout AngularJS. You can use it when defining components or when providing run and config blocks for a module.
element() Function in AngularJS is used to initialize DOM element or HTML string as an jQuery element. If jQuery is available angular. element can be either used as an alias for the jQuery function or it can be used as a function to wrap the element or string in Angular's jqlite. Syntax: angular.element(element)
A well written directive that is extendable and/or interacts with other directives will have a controller. That controller needs to access the DOM because it is where that directive's functionality is defined. Directives are effectively a different way to bind a controller/scope to an element on the page; the preferred way to add functionality to the DOM. From what I understand, the best practice is: don't use both a controller and a link function. So directive controllers need an $element
.
In the light of the various guides and tutorials that suggest you shouldn't access the DOM in a controller, why is this even possible?
The guides are a little misleading once you dig into how it all works.
Controllers handle defining functions and assign variables to be used by the view. And the right way to bind those functions and variables to the view is with a directive. That is my understanding of best practices, having worked with large and growing angular applications for the past year.
The tricky thing is that the directive basically binds a controller to the DOM. ng-model
is a directive and has a controller that can be accessed from other directives. You will want to take advantage of this if you do things like add custom validation fanciness. This controller of the directive is supposed to manipulate the DOM. So a generic controller is actually is a super set of view controllers; a detail that the tutorials usually glaze over.
Is there any non-hacky use case for this?
$element
:Using it in a directive's controller for example.
Are there any examples of this being used in available code somewhere?
Angular source code, though perhaps a little dense of a read, is good code and well commented. It may take a little bit to see what's going on, but usually quite informative.
NgModelController (complex example) https://github.com/angular/angular.js/blob/master/src/ng/directive/input.js https://github.com/angular/angular.js/blob/master/src/ng/directive/input.js#L1660
What could be a simple example, but uses a compile function instead, the eventDirectives (ng-click
for example), https://github.com/angular/angular.js/blob/master/src/ng/directive/ngEventDirs.js#L3
Whether you inject $element or not, the controller's scope is bound on that element.
angular.element('#element-with-controller').scope();
Angular revolves around directives. It's what glues things together in the MVC. And if you think about it, ng-controller, is a directive itself.
I guess this can come in handy when you're using a single controller for multiple directives.
.controller('MyController', function($scope, $element){ $scope.doSomething = function(){ // do something with $element... } }) .directive('myDirective1', function(){ return { controller: 'MyController' } }) .directive('myDirective2', function(){ return { controller: 'MyController' } })
Each directive will have a new instance of the assigned controller, but basically share it's properties, dependencies.
I wrote a form handler controller once, for registration/login/contactus, etc.
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