preventing angular to run in non displayed DOM elements - angularjs

lets say I have a HTML structure like this
<myHandler>
<element_1 ng-controller="..." ng-init="">
content
</element_1>
<element_2 ng-controller="..." ng-init="">
content
</element_2>
</myHandler>
So, my css is saying element_2 has display: none;
how to tell angular not to run on these lements, that are hidden?
and run only (once) when they are visible?
to clarify the case more, the myHandler is handling authorization and is displaying element_1/element_2 depending on the permissions.
so I don't want to initialized element_2 if it has no permissions

Instead of keeping display none ,just keep an attribute ng-if with a flag variable
because if we use ng-if then no element is added into the dom or if no element added then no controller will get instantiated.
<myHandler>
<element_1 ng-controller="..." ng-init="">
content
</element_1>
<sample ng-if="isDisplay">
<element_2 ng-controller="..." ng-init="">
content
</element_2>
</sample>
</myHandler>

Related

Angular ui-select2 - hide initial drawing/rendering of component

I'm evaluating using Angular with ui-select2 and wondered whether someone could provide help on hiding the flicker/conversion of the <select> into the select2 component.
It's only very brief, but users can see the component change styles.
Is there a way of hiding it until the select has been modified by select2?
I came across the same problem and I had a look at the source code. The directive is deliberately initialised later by using a timeout. In the code there is a comment saying "Initialize the plugin late so that the injected DOM does not disrupt the template compiler".
My solution (you can see it in this jsplunker: http://plnkr.co/edit/fXjDxs?p=preview ) is to set the visibility of the select tag to "hidden".
<select ui-select2 ng-model="....." style="visibility: hidden; ">......
When the component is loaded that tag is replaced with a div. In ui-select2.js I have added a line (line 208) to set its visibility to "visible".
elm.prev().css({"visibility": "visible"});

Hide Angular brackets until javascript loaded

I have a few bits of HTML like
<p class="noresults">{{numberOfContacts}} Results Are Available</p>
Is it possible for me to hide {{numberOfContacts}} until Angular has loaded? So it would just say Results Are Available
I've seem some solutions such as hiding the entire body until Angular has loaded, but I'd rather not do that if possible.
Yes, use ng-cloak. Simply add class="ng-cloak" or ng-cloak to an element like this
Using directive <div ng-cloak></div>
Using class <div class="ng-cloak"></div>
It's simply a set of CSS rules with display: none !important and as Angular has rendered your DOM it removes the ng-cloak so an element is visible.
use <span ng-bind="numberOfContacts" /> instead of {{numberOfContacts}}
Sometimes, even if I used the ng-cloak, I could still see the braces for a few seconds. Adding the following style resolved my issue:
[ng-cloak]
{
display: none !important;
}
Please see this link link for more explanation.
Hope it helps :D
This is typically only an issue when working with complex content on really slow devices. In those instances, there can be a brief moment when the browser displays the HTML in the document while AngularJS is parsing the HTML, getting ready, and processing the directives. In this interval of time, any inline template expressions you have defined will be visible to the user. Most devices nowadays have pretty good browsers which are quick enough to prevent this from being an issue. There are two ways to solve the problem.
Avoid using inline template expressions and stick with ng-bind directive.
(Best) Use the ng-cloak directive which will hide the content until Angular has finished processing it. Basically, the ng-cloak directive uses CSS to hide the elements and angular removes the CSS class when the content has been processed, ensuring that the user never sees the {{ and }} characters of a template expression.
One strategy to consider is using the ng-cloak directly to the body element, which will ensure that the user will see an empty browser while AngularJS loads. However, you can be more specific by applying it to parts of the document where there are inline expressions.
I have seen issues with ng-cloak not working when added to an element. In the past, I have worked around this issue by simply adding ng-cloak class to element.
You can use ng-bind instead of expression like
<span ng-bind="data"></span>

AngularJS: Updating a view with a template from a controller?

I have been working with routing and I have seen how I can update the ng-view using routing and a view template.. But the problem I have is that I am doing a REST call and depending what I get back from the response I wish to update part of the DOM with a view template but I don't want to involve routing.
Does anyone know how I can do this? Or any examples would be great
Thanks in advance
Another answer. Based on your description in the comment, it sounds like you wish to display part of the DOM conditionally.
When you want to display part of the DOM conditionally, you have the following choices:
Use an ng-show and ng-hide directive.
Based on what returns from the RESTful call, you can set up a model that will identify the DOM that needs to be displayed. An example:
<div ng-show="status">
This text will be shown only when the status is truthy
</div>
<div ng-hide="status">
This text will be shown only when the status is false.
</div>
Inside your controller, you could then set the status to true or false based on your RESTful calls and based on which part of the DOM you wish to display post RESTful call.
You can use ng-switch directive
While the ng-show and ng-hide directives will display the content of your DOM conditionally, that is anybody could simply open the source file and see the contents for both, ng-switch directive will load the contents only based on which case fulfills the swtich. An example:
<div ng-switch on="status">
<div ng-switch-when="true">
This text will be shown only when the status is truthy.
Else this is completely hidden and cannot be seen even
when looking at the source.
</div>
<div ng-switch-when="false">
This text will be shown only when the status is false.
Else this is completely hidden and cannot be seen even
when looking at the source.
</div>
</div>
The first child div is shown when the status is true else it is not shown at all. The advantage over ng-show or ng-hide is that the DOM will not contain the child elements if the case is not fulfilled.
$location.path() can be used here.
So, in your Parent Controller, you can make the REST call. Once you have the data with you, you can then decide which route to take. The route value goes into the path() function.
As an example, let us say that if your REST call returns with cherries, you need to take the /foo path (which, based on your $routeProvider will load the template associated with that route). You can then write the following:
$location.path('/foo');
and it will loads the /foo path - $routeProvider will then take care of loading the template associated with that path.
Reference: $location

Stop AngularJS inserting <span class="ng-scope"></span> using ng-include

I'm using the Foundation layout framework, which automatically floats the last sibling of .column to the right and I really appreciate this is a behaviour. However, AngularJS takes it upon itself to insert span.ng-scope after every div.column, which somehow causes browsers to consider the last span the last sibling of .column (even though it is not).
Specifically the css in Foundation responsible for this is:
[class*="column"] + [class*="column"]:last-child { float: right; }
As I understand it, [attribute*="substring"] should select only siblings that match, so, for the above, only elements whose class attribute contains column (including columns). I would think a span tag whose class attribute that does not contain column should not match (and thus be ignored by :last-child). However, this does not seem to be the case.
Regardless, the span is causing the problem:
Angular buggering it up (jsfiddle)
Works fine without Angular (same jsfiddle, no ng-include)
Is there a way to configure angular to stop inserting those span tags? I would, begrudgingly, modify the css selector to somehow ignore all span tags; however I might eventually need/want to use a span tag.
Since you indicated the div can be moved inside, this works:
<ng-include src="'main.tmpl'"></ng-include>
Then in your template:
<div class="row">
<article id="sidepanels" class="four columns">
...
</div>
I'm not aware of any way to prevent angular from inserting the span tags (I think it keeps track of scopes that way -- for garbage collection).
Also you can try my version of include directive that does not creates a scope: Gist source.
As no scopes are created, AngularJS should not create additional element to mainain scope (it actually use data attributes to store link to scope).

Alternative to ng-show/-hide or how to load only relevant section of DOM

When using ng-show/-hide, the content included in those blocks initially displays on the user screen. Only after few milliseconds (after angular.js has loaded and executed) does the right block show up in ng-show.
Is there a better way than ng-show/-hide to load only the relevant section of data into the DOM?
The problem with ng-view is that I can have only one on the page, so I have to toggle the behavior of many sections of the DOM based on the current state.
To avoid the "flash of uncompiled content", use ng-bind instead of {{}} or use ng-cloak:
<span ng-cloak ng-show="show">Hello, {{name}}!</span>
If you use ng-cloak, and you do not load Angular.js in the head section of your HTML, you will need to add this to your CSS file, and ensure it loads at the top of your page:
[ng\:cloak], [ng-cloak], .ng-cloak { display: none; }
Note that you only need to use these directives on your initial page. Content that is pulled in later (e.g., via ng-include, ng-view, etc.) will be compiled by Angular before the browser renders.
Is there a better way to load data other than ng-show / hide, in which only the relevant section is loaded into the DOM.
Some alternatives to ng-show/ng-hide are ng-include, ng-switch and (since v1.1.5) ng-if:
<div ng-include src="someModelPropertySetToThePartialYouWantToLoadRightNow"></div>
See also https://stackoverflow.com/a/12584774/215945 for an example of ng-switch working together with ng-include.
Note that ng-switch and ng-if add/remove DOM elements, whereas ng-show/hide only alters the CSS (if that matters to you).
I used the ng-cloak trick and it doesn't seem to work that well. Following the Angular documentation I added the following to my CSS and that does work:
[ng\:cloak], [ng-cloak], [data-ng-cloak], [x-ng-cloak], .ng-cloak, .x-ng-cloak {
display: none !important;
}
See: http://docs.angularjs.org/api/ng.directive:ngCloak
Per Mark Rajcok's fine answer, here's a CodePen showing ng-show, ng-switch, and ng-if in action, so you can compare the approaches, and see differences in how the conditional content is actually rendered.
Note that some people feel that ng-show is a little faster than ng-switch and ng-if for file-based templates. But you can use $templateCache to preload your templates at bootstrap time, reducing or eliminating that advantage. Using ng-switch and ng-if, you no longer have to deal with hidden conditional content being in the DOM when it's not needed, and prevent expressions on that content being evaluated by Angular at inopportune times. That saves you processing resources you don't need to waste, and avoids errors that can be thrown when something's evaluated prematurely.

Resources