Imagine some heavy content that might be rendered on a web page, such as a chart. Angular gives 2 options to toggle the visibility of said content.
ng-show will render the content regardless of the expression and simple "hide" it after the fact. This is not ideal since the user may never "open" the content during their session, so it was a waste to render it.
ng-if is better in this regard. Using it in place of ng-show will prevent the heavy content from being rendered in the first place if the expression is false. However, its strength is also its weakness, because if the user hides the chart and then shows it again, the content is rendered from scratch each time.
How can I make a directive that takes the best of both worlds? Meaning it works like ng-if until the content is rendered the first time, then switches to work like ng-show to prevent re-rendering it each time.
ng-if is better in this regard. Using it in place of ng-show will prevent the heavy content from being rendered in the first place if the expression is false. However, its strength is also its weakness, because if the user hides the chart and then shows it again, the content is rendered from scratch each time.
ng-if can only render data whenever the condition is true. It doesn't have any rendered data until the condition is true. ng-show can show and hide the rendered data, that is, it always kept the rendered data and show or hide on the basis of that directives.
Both are actually one and the same. Both are directives to specify Conditions. You can use ng-if or prefixing ng-if with data- or x- like data-ng-if or x-ng-if. Angular allows prefixing to its directives with data- or x- just for Validation due to "HTML5 validator".
we cannot use two structural directives on same element. Structural directives like ngfor can do complex things with the host element and its childrens. When two directives placed on same element we cannot decide which one takes precedence i.e., which should execute first *ngIf or *ngFor?
+1 on Denis's answer, but just for completeness-sake, it can even be simplified further by keeping the logic in the View without "polluting" the controller:
<button ng-click="show = !show">toggle</button>
<div ng-if="once = once || show" ng-show="show">Heavy content</div>
plunker
EDIT: the version above could be further improved (and simplified) with one-time binding to reduce an unnecessary $watch on once
- this will only work in Angular 1.3+:
<div ng-if="::show || undefined" ng-show="show">Heavy content</div>
The undefined
is needed to ensure that the watched value does not "stabilize" before it becomes true
. Once it stabilizes, it also loses the $watch, so it would not be impacted by any further change to show
.
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