Angular directive loading order. - javascript

I have a view containing two nested directives. The inner-directive depends upon the outer-directive to be present. When I load the page from scratch the directives are loaded as expected i.e the outer exists before the inner. But when I navigate from the page and then return, the order of directive-loading is reversed i.e the inner-directive is loaded before the outer-directive. Both directives are costume directives. When I change the outer-directive to instead being a ng-controller, the problem is solved. To perform the navigation ui-router is used. Does anybody know how to solve this issue without having to use a ng-controller as the outer-directive? And why ng-controller solves the problem?
<div outer-directive>
<inner-directive></inner-directive>
</div>

Without knowing a ton about your specific directives, you can take a look a this blog post about directive priority.
(Controller gets processed in a different cycle than directives, so it makes sense that putting whatever 'dependent' code inner-directive requires into a controller solves your problem).
Here's the interesting part: Angular will follow, it appears, this "path" for your nested directives:
outer-directive: compile
inner-directive: compile
outer-directive: pre-link
inner-directive: pre-link
inner-directive: post-link
outer-directive: post-link
The linked blog post explains "why," but this processing order explains your discrepancy between initial page load (where compile is run for the directive) and your page-back case (where the directive is already compiled and we just need to link).
Again, without knowing much about your directives, maybe you need to relocate the dependent outer-directive code into pre-link (instead of link) so that it gets processed first?
You do that by breaking up your Link object into:
Link: {
pre: function(){
},
post: function() {
}
}
Still need help, [here's a decent post] (http://www.undefinednull.com/2014/07/07/practical-guide-to-prelink-postlink-and-controller-methods-of-angular-directives/) on the breaking up link into pre/post.

Related

How does document.ready work with angular element directives?

In my current project I'm using angular directives to create custom html elements. See example below.
banner.js
app.directive('banner', function () {
return {
restrict: 'E',
replace: true,
templateUrl: './common/banner/banner.html'
};
});
Banner.html
<div>
<div class="banner-image"></div>
</div>
Issue: There is a javascript file that adds additional properties to elements with the banner-image class after document.ready. This worked perfectly before using angular element directives, but the properties are no longer being added.
Question: Does the document.ready callback occur prior to angular element directives being rendered in the dom? If so, that could explain why my javascript file is no longer making the necessary changes to the html elements.
Thank you
This is less a "directives" question, and more an Angular sequence of events question.
Angular itself (if not manually started with .bootstrap) will defer its loading until .onready.
At that point in time, Angular expects that all JS it needs to run will be there and registered.
Then Angular starts up.
Then after Angular starts up, Angular parses the DOM to find a root element to attach to (the one with the ng-app directive).
Then it recursively goes down the line, injecting controllers and building out directives and interpolating nodes as it goes.
Now we are way past any code that would have fired on DOMReady.

AngularJS: directives vs. controllers - What logic to put where? [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 8 years ago.
Improve this question
I'm quite new to angular and try to really learn how to organize my code, so future coworkers will be able to find their way around it quickly.
One rule I know is "If it manipulates the DOM, put it into a directive", which I abide by.
But still there are times where I am unsure where to put my methods, as I can put them into the main app controller, into a controller supplied as the "controller" option within the directive or even within the function that inits the directive (option "link").
With filters and services it's pretty clear to me, but with controllers and directives the line becomes pretty blurry.
I already realized that even with a little app I spread some of the code here and there and it's already confusing, even to myself. So I'd like to get some Tipps on organizing my code better.
So I guess my main question is:
1) Is there a good rule of thumb to know what code to put where?
Or if this is too abstract here are some examples:
2) I have a directive with a template which I only use within my app. Something should happen, when I click on the element. I already know its preferable to use the ng-click directive over binding a click event within the linked function.
But where should I define the method supplied in ng-click?
A) The main controller of the app.
B) The "link" function of the directive.
C) Add a controller to the directive (using the "controller" option) and define it there.
3) Would the answer to 2) be different if I plan to reuse the directive elsewhere?
4) Different Scenario:
I have a Button and when clicked and dragged it should move a completely unrelated Element.
Should I...
A) Create one directive and influence template & behavior based on a passed attribute?
B) Create two directives (one for the handle, one for the target Element)
If so, it again poses the question of where to put the methods to handle the dragging?
Notes:
I am aware the answers might be a little dependent on personal opinion, but I kinda hope there are some "rules" or "right ways to do it" to which I can abide by for future development.
I didn't include any code for conciseness reasons.
Should it be needed for an answer I'd be happy to provide it.
thank you for your time.
First of all, great question. I think every new-with-angular developer struggles with the differences with all the given components (controller, directive, service, filter etc.).
Let's start with the basic formal definition:
Directives are markers on a DOM element that tell AngularJS's HTML compiler to attach a specified behavior to that DOM element.
And on the other hand
Controller is a JavaScript constructor function that is used to augment the Angular Scope
The defined behavior does guide us through some rule-of-thumbs.
So for your questions above:
In simple words, we user controllers to manage an area (scope) in
The HTML template with all the great abilities a controller brings
(two-way-binding, scoped behavior, services injections etc.) And we
Use directives when we wish to manipulate an existing HTML element or
Custom out own, in most scenarios - when we think about reusing
This elements.
That depends on the context of what ng-click should do. Lets say you have your customized directive for a numeric input that has a customized designed and behavior as you defined in your directive configuration. And you use it in a form that ng-click suppose to pop a modal with optional values and use it in a different place in the application and ng-click will do something else. In this case the function need to be a scope.fucntion. but let's say both location and every other will do exactly the same, this take the function to the directive scope.
Answered above :)
Each of your options will do, this where "opinion" takes in and less rule-of-thumbs exists. why? because both ways will work when each has it pros and cons. The rule of thumb I can find in the scenario is that if both elements are part of the directive template, I would expect the 'behavious' (the dragging function) to be part of the directive scope.
Good luck
1) Is there a good rule of thumb to know what code to put where?
Lots of things at play here; and I'm not sure that there is a 'directives vs controllers' battle going on. They seem different enough to me. Directives can have their own controllers, if you didn't know.
I view directives as a single, specific, set of encapsulated code including the HTML (View) and JavaScript code (Controller). I use directives when I want to reuse something as an 'encapsulated' component.
If I just have a bit of JavaScript code that I want to reuse; I'll put in an AngularJS service which I see as just a collection of JavaScript code without any HTML.
I have a directive with a template which I only use within my app.
Something should happen, when I click on the element. I already know
its preferable to use the ng-click directive over binding a click
event within the linked function. But where should I define the method
supplied in ng-click?
I would define the handler as part of the directive's isolated scope; something like this:
scope:
{
onButtonClick: '&onButtonClick'
}
Define default behavior as part of the Directive's link or controller.
link: function ( $scope, element, attrs ) {
$scope.myDefaultButtonClick = function(){
// do stuff
}
this.onInit = function(){
if(!$scope.onButtonClick){
$scope.onButtonClick = $scope.myDefaultButtonClick;
}
}
this.onInit();
}
In your JavaScript; you can call the function that is passed in as an argument:
$scope.onButtonClick();
And you can do the same in your HTML template.
<img src="button.png" ng-click="onButtonClick()">
3) Would the answer to 2) be different if I plan to reuse the
directive elsewhere?
If I do not plan for reuse; I would probably not use a directive.
I have a Button and when clicked and dragged it should move a completely unrelated Element.
Should I...
A) Create one directive and influence template & behavior based on a passed attribute?
B) Create two directives (one for the handle, one for the target Element)
If so, it again poses the question of where to put the methods to handle the dragging?
I would chose item A probably; passing in the element that needs to be manipulated as an argument to the directive. However, it depends how much I care about re usability of this piece of functionality.
Everything I say should be considered subjective.

angularjs directive with ng-if in the template

I'm building a directive that utilizes an ng-if inside of it's template. What's strange is that the element provided to the link function does not have the ng-if code expanded, it is only a comment line for the ng-if. Playing around, I found that by wrapping my link code in a $timeout seems to get it to work, but I am wondering if that is not the correct way of going about it....and more so, why is this happening.
I've added a plunk to demonstrate: http://plnkr.co/edit/Gl7v8yJLevi664nUKcFY?p=preview
Most directives actually do most of their logic in a $watch(). For example ng-if will setup a watch on it's attribute, and then render/remove the dom when that changes. Watches execute during a digest cycle, so even though directives have been compiled and linked, the watch hasn't run yet to determine whether it should show the if or not.
EDIT:
You should probably think about what you are actually doing to make sure if it's what you want. Keep in mind that the ng-if is dynamic. And so at any time it might get removed or added based on whether the items array is empty or not.
This means that even if you manage to defer your dom manipulation until after the if is rendered, you run the risk of the if going away and coming back (at which point your css code will not be run again).
A much better way to do this would be to setup a watch and add your css in a watch, or better still, use ng-class and add the css in your template.
The angular framework needs to have $scope.$apply() called in order to update the bindings and expand the template. $timeout() is an async wrapper which assumes that changes were made outside angular world and it calls $scope.$apply() as a final step. in your case, using $scope.$apply(); directly, immediately before your element call achieves the desired effect.

How to decide when to use ngView or ngInclude?

Just trying to understand the exact difference in approaches of using ngView and ngInclude in AngularJS. When would is it correct to use one over the other? Thanks.
ngView works together with routing, and is mostly essential to an angular SPA. It's normally used to include the main content of your site, the bit in between the header and footer that changes every time a user clicks a link. Its integration with routing means changing the ngView content changes the controller too (depending on your configuration).
ngInclude is a general purpose include, you may not even need it. You'd sometimes use it inside a view to avoid repeating yourself, in the cases where several views need the same code included.

Difference between the directives and static DOM elements in AngularJS

I have already read the
Compilation process, and directive matching
on AngularJS Doc.
but I really didn't understand the directives.
Example:
I have static html:
<div class="test test2" cid="549" sid="a5e3c4f8a9">text-text-text</div>
when I do it manually, I know it will only created and called one time at browser's parse time.
but what happens when I create a directive with the same dom element ?
<x my-directive>text-text-text</x>
is this the same effect?
I am asking such a newbie question, because I am using over 200 elements on my html page.
If I change them to single directive: for sure it will be much more easier to manage them.
and its no problem if its only slow at browser's compile time but what happend in run time?
and I am sorry, if the qustion is not pro enought. I am just new to Stackoverflow.
Thank You
Daniel
If I understand you correctly, you want to know how AngularJS creates a directive and how many times your directive methods are called.
When you create a directive (with module.directive('myDirective', ...)), you are really just creating a definition. Every time you use that directive (like <div my-directive>), AngularJS will run through the process described in the guide: that is, it will compile and link each use. It has to be this way because the directive doesn't exist in isolation; it exists not only in the $scope in which it was called, but also it can make use of element attributes and transcluded contents. The definition occurs once, but each instance is compiled and linked.
Once the directive is created, it's technically done; if you don't set up any $watch or $observe or event bindings, your "directive" is now just whatever's in the DOM at the end of your link function - there's no more computation. In other words, what happens after compilation and linking is entirely up to you.
So back to your example: if you use 200 of the same directive on the page, the directive will be defined once, but all 200 will be compiled and linked separately. But I'm not really sure what you're implying by asking. What's the question behind your question?

Categories

Resources