In what sequence does AngularJS directives execute? - angularjs

If I use AngularJS custom directive, which executes a function, and then use a regular directive like ng-repeat, then which one gets executed first?
for example - in a Select element, if I have use custom multi-select directive and in the same I use an ng-repeat, then which directive gets executed first. Is it in the sequence it is defined?
<select multi-select ng-repeat="x in Xes" multiple></select>

The priority is property that defines which directive will be compiled or linked first.
To avoid the duplication of explanations, read this post here.
I think that's what you want to know.

Related

How do I know if directive is enclosed in a container with ng-if = false?

I am developing a custom directive and now I need to handle ng-if. This is easy enough when ng-if is on the directive it self. However when ng-if is on an enclosing container element my compile function fails with run time errors.
Question is: what is the best and most efficient way to know, inside the compile function of a directive, that the directive is enclosed within a container with ng-if is false OR an expression that evaluates to false.
For example:
<div ng-if="false">
<my-directive></my-directive>
</div>
And another example:
<div ng-if="somescopeValue > 300">
<my-directive></my-directive>
</div>
Maybe the answer is using jquery to traverse the dom and find a parent with
an ng-if attribute but I was wondering if there is another more "angular" way of doing this.
Your directive shouldn't rely on knowing whether it is encapsulated in a ng-if expression. That breaks the principle of 'Separation of Concerns' and deteriorates code re-use. Consider redesigning your custom directive in such a way that it needs not be aware of its host elements, in the same fashion that all components (should) work.
If you are using same scope as parent controller or directive then you are able to access same variable in your directive(here my-directive) also. If this is not a case then you need to write code to access parent element in link function of my-directive. You will get directive element in link function as a parameter.
I'm not sure how the error happens, because when your directive is inside ng-if="false", your directive won't get called at all - all compile, link and controller function in the directive will only run as soon as your directive gets added in DOM.
Perhaps your error can be solved by initializing something in case your directive is not added.

How can I implement an Angular directive similar to ngAttr?

How can I implement an Angular directive similar to ngAttr? This means a directive to match all the elements that start with a prefix.
Example: directive myDirective will match the attributes data-my-directive-first, my-directive-second and so on.
ngAttr* is handled in angular in a special way. There is hard wired logic only meant for directives with ng-attr prefix. So, it is not possible what you want to achieve. You can see the logic in collectDirectives function which is used by angular to collect directives from HTML nodes. Here:
https://github.com/angular/angular.js/blob/92374f9633d6121b115d77c10248e40e1f4f2aa1/src/ng/compile.js#L1759
My suggestion would be, have aliases' array and loop through to create directives with same function provided.

Few questions regarding Angular directives

I have few questions regarding angular directives
I'm basing my questions based on the following block of codes
<ul class='parent'>
<li class='child1'></li>
<li class='child2 active'></li>
<li class='child3'></li>
</ul>
So based on the above
How can i create a directive based on the above (assuming this comes from an Angular plugin, and there is no angular directive attribute defined within the tag)?
Assuming the above is from an Angular plugin, and i don't intend to edit the plugin, how can i use the directive to see which list is currently active?
How can i do operations through the code above using Angular? With Jquery, i can easily do it as
For checking the child length
$('.parent').children().length
For iterating through the child elements
$.each($('.parent').children(), function(){ console.log(this); });
But when i tried to do it with Angular way
angular.element(document.querySelectorAll('.parents')).children().length
Somehow this part always returned me the wrong value. I guess my Jquery mindset is the reason why i couldn't get the value but still, i read somewhere that angular.element object is the equivalent of the jquery $() object, thus both should be able to use the same functions.
If i want to do event binding on the code above i should do it inside the link function correct? If i want to watch and apply changes for the code above, then i should use the directive's scope and do it inside the link function too right?
Is there easy-to-chew guide on how Angular's directives? Somehow most of those that i read are pretty much as confusing as the directive guide in Angularjs documentation itself.

How do I include other directives in the template of my customer directive in Angular?

I wrote a simple custom directive. The template in this directive includes other directives (e.g. ui-sortable). Because it doesn't always use ui-sortable, I add it in the link phase. Yet it doesn't seem to apply:
link: function ($scope,$element,attrs) {
attrs.$observe('admin', function(value) {
if ($scope.admin) {
$element.find("span").html("true");
$element.find("ul").attr("ui:sortable","sortableOptions");
}
});
}
Full fiddle example is here: http://jsfiddle.net/VjfEf/4/
There are two lists. The first uses ui-sortable directly and drag/drop/sort works, the second uses my custom members directive. The directive does work, it renders, but the addition of ui-sortable in the exact same way as the first has no impact and drag/drop/sort does not.
I am assuming I am not understanding something about the processing phases of custom directives, and either need to add something to my custom directive?
You need to compile the newly added HTML.
$compile($element.contents())($scope);
Fiddle

Directive ng-show alternatives

I have a control that should display breadcrumb navigation. It needs data (route & title) to display the navigation correctly. Data is taken from scope and used inside a directive.
What causes my problems is that I use a localization directive in the control that should translate the title. And this localization directive is called even when expression in ng-show is evaluated to false. Then the translation in localization directive ends with exception because it tries to translate incorrect string (see 'localize' directive in http://jsfiddle.net/F97wn/7/).
That seems quite weird. I would expect that if something sets whether the inner content should be visible or hidden, then it is evaluated first and then the inner content..
Ok, then I found that ng-show only sets some css attribute, so it's quite useless for me.
The question is: How should I solve the problem - what to use instead of the ng-show?
An example is at http://jsfiddle.net/F97wn/7/
You could use ngSwitch instead with the on part set to "toshow()" and the inner ng-switch-when="true" part to have your custom directive inside that area. This will then not execute the custom directive if the value of toshow is not true.
If the directive is throwing an exception, more information should probably be passed to the directive, in one of the following ways, so that the directive can decide if it has the required information to do what it needs to do:
attribute data -- e.g., localize="..." show-me="..."
something defined on the scope associated with ctrl -- e.g., $scope.showMe. The directive scope will have access to this property as scope.showMe, based on the way you currently have the directive defined.
or inject a service (that has the data) into the directive -- e.g., directive('localize', function(myShowMeService) { ... }
You might also want to look into <ng-if>. The ngIf directive removes and recreates a portion of the DOM tree (HTML) conditionally based on "falsy" and "truthy" values evaluated within an expression. It might be more intuitive than <ng-show> for your needs.
However, it is currently only available in the unstable version of AngularJS. If you can use that version of AngularJS you can find more information about it here.

Resources