parliament parliament - 2 months ago 38
AngularJS Question

Angular ng-if and ng-show combination

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.


+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>


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.