When to favor ng-if vs. ng-show/ng-hide?
Asked Answered
S

7

537

I understand that ng-show and ng-hide affect the class set on an element and that ng-if controls whether an element is rendered as part of the DOM.

Are there guidelines on choosing ng-if over ng-show/ng-hide or vice-versa?

Salinas answered 19/2, 2014 at 1:42 Comment(2)
possible duplicate of what is the difference between ng-if and ng-show/ng-hideAbigail
Not related to dart language.Modestia
A
725

Depends on your use case but to summarise the difference:

  1. ng-if will remove elements from DOM. This means that all your handlers or anything else attached to those elements will be lost. For example, if you bound a click handler to one of child elements, when ng-if evaluates to false, that element will be removed from DOM and your click handler will not work any more, even after ng-if later evaluates to true and displays the element. You will need to reattach the handler.
  2. ng-show/ng-hide does not remove the elements from DOM. It uses CSS styles to hide/show elements (note: you might need to add your own classes). This way your handlers that were attached to children will not be lost.
  3. ng-if creates a child scope while ng-show/ng-hide does not

Elements that are not in the DOM have less performance impact and your web app might appear to be faster when using ng-if compared to ng-show/ng-hide. In my experience, the difference is negligible. Animations are possible when using both ng-show/ng-hide and ng-if, with examples for both in the Angular documentation.

Ultimately, the question you need to answer is whether you can remove element from DOM or not?

Apian answered 19/2, 2014 at 2:58 Comment(16)
You can use CSS3 animations with ng-if. Check the Animations paragraph and the example in the docs. Also with ng-hide/ng-show the css selectors like :first-child or :nth-child won't work properly since the hidden elements will be also counted.Fredric
Animation service in angular.dart is relatively new. At the time of writing this it wasn't available.Apian
You first point is a non-issue if you're using directives (like ng-click) to bind handlers , as you should be.Bakerman
To summarize: always use ng-if unless there is a reason not to.Frontlet
How do screen readers and other assistive technologies interpret DOM elements hidden with CSS? If the reason for hiding elements is more than just for visual effect, I would think ng-if is the appropriate choice. Also, having just run into this, scope issues associated with ng-if may require a little more work.Distort
Also, ng-if creates a new scope while ng-show doesn't.Pickmeup
It should also be mentioned that adding and removing elements from the DOM can incur a high performance cost if done frequently.Bakerman
@KevinC. Agreed, but there does seem to be a trade-off to some degree. What if there's a significant number of expressions (i.e. watchers) within the ng-hidden DOM element? Your digest cycles with elongate the more watchers you have, which affects overall performance. Would you agree with that trade-off?Olshausen
@Olshausen yup, that is correct. You need to take all of these factors into consideration when optimizing your app.Bakerman
plnkr.co/edit/gyYbFdZqOMcipizqX0XE?p=preview ng-if will attach handlers auto.Rode
What is the impact of having a new scope with ng-if? Does it change anything, really?Mutiny
It should be noted that ng-if is executed at a higher priority than ng-show/ng-hide. So if you're having problems with something not showing up / being hidden fast enough, give ng-if a try.Long
Also, with ng-show if a child element is required="true", it will be required even though it is not visible.Aye
Suppose I have a LOT of bindings inside a div, and those bindings only make sense when the div is visible.. then ng-if should have better performance..right?Haply
@Mutiny - having a new scope can lead to a world of pain if you are caught unawares :) It breaks two-way binding!Formyl
I would say it also depends on how frequently the element gets togglet. If it toggles rarely i would prefere ng-if, because handlers do not need to watch for events anymore. BUT (and i think thats the more important fact): If it toggles often, i would prefere ng-show, it's much cheaper to hide an element via CSS as to remove and append it from the DOM, especially the dedicated handlers.Rossiter
C
130

See here for a CodePen that demonstrates the difference in how ng-if/ng-show work, DOM-wise.

@markovuksanovic has answered the question well. But I'd come at it from another perspective: I'd always use ng-if and get those elements out of DOM, unless:

  1. you for some reason need the data-bindings and $watch-es on your elements to remain active while they're invisible. Forms might be a good case for this, if you want to be able to check validity on inputs that aren't currently visible, in order to determine whether the whole form is valid.
  2. You're using some really elaborate stateful logic with conditional event handlers, as mentioned above. That said, if you find yourself manually attaching and detaching handlers, such that you're losing important state when you use ng-if, ask yourself whether that state would be better represented in a data model, and the handlers applied conditionally by directives whenever the element is rendered. Put another way, the presence/absence of handlers is a form of state data. Get that data out of the DOM, and into a model. The presence/absence of the handlers should be determined by the data, and thus easy to recreate.

Angular is written really well. It's fast, considering what it does. But what it does is a whole bunch of magic that makes hard things (like 2-way data-binding) look trivially easy. Making all those things look easy entails some performance overhead. You might be shocked to realize how many hundreds or thousands of times a setter function gets evaluated during the $digest cycle on a hunk of DOM that nobody's even looking at. And then you realize you've got dozens or hundreds of invisible elements all doing the same thing...

Desktops may indeed be powerful enough to render most JS execution-speed issues moot. But if you're developing for mobile, using ng-if whenever humanly possible should be a no-brainer. JS speed still matters on mobile processors. Using ng-if is a very easy way to get potentially-significant optimization at very, very low cost.

Cochin answered 6/5, 2014 at 21:43 Comment(2)
Very nice addition to the above answer. Given with some good context, which also helps the decision making. Thanks.Phototonus
ng-show can be useful when you have, say tabs each with a lot of content that takes time to render. After the first rendering, moving between tabs will be instant, whereas ng-if would require re-rendering, binding events etc. The downside as you say, is that creates watches executing in the background. Angular desperately needs ng-ifshowwatchGloboid
P
53

From my experience:

1) If your page has a toggle that uses ng-if/ng-show to show/hide something, ng-if causes more of a browser delay (slower). For example: if you have a button used to toggle between two views, ng-show seems to be faster.

2) ng-if will create/destroy scope when it evaluates to true/false. If you have a controller attached to the ng-if, that controller code will get executed every time the ng-if evaluates to true. If you are using ng-show, the controller code only gets executed once. So if you have a button that toggles between multiple views, using ng-if and ng-show would make a huge difference in how you write your controller code.

Palette answered 7/10, 2014 at 23:8 Comment(4)
That's a huge true! ng-if does not necessarily make your frontend faster. It depends on your needs. Actually it could make the other way around if you are using in the wrong situation.Celinecelinka
But according to me as ng-if does't render onto DOM so it is fast as compared to ng-show/hide. am i wrong pls let me correct at that point.Manny
ng-if would be faster if it evaluates to false, since, as you say, nothing needs to be inserted into the DOM. But, if it is true then you have an overhead of inserting the - possibly quite complicated - element into the DOM.Jodoin
"2) ng-if will create/destroy scope when it evaluates to true/false. If you have a controller attached to the ng-if, that controller code will get executed every time the "Decaffeinate
T
39

The answer is not simple:

It depends on the target machines (mobile vs desktop), it depends on the nature of your data, the browser, the OS, the hardware it runs on... you will need to benchmark if you really want to know.

It is mostly a memory vs computation problem ... as with most performance issues the difference can become significant with repeated elements (n) like lists, especially when nested (n x n, or worse) and also what kind of computations you run inside these elements:

  • ng-show: If those optional elements are often present (dense), like say 90% of the time, it may be faster to have them ready and only show/hide them, especially if their content is cheap (just plain text, nothing to compute or load). This consumes memory as it fills the DOM with hidden elements, but just show/hide something which already exists is likely to be a cheap operation for the browser.

  • ng-if: If on the contrary elements are likely not to be shown (sparse) just build them and destroy them in real time, especially if their content is expensive to get (computations/sorted/filtered, images, generated images). This is ideal for rare or 'on-demand' elements, it saves memory in terms of not filling the DOM but can cost a lot of computation (creating/destroying elements) and bandwidth (getting remote content). It also depends on how much you compute in the view (filtering/sorting) vs what you already have in the model (pre-sorted/pre-filtered data).

Tengdin answered 20/10, 2015 at 8:21 Comment(2)
Other answers for technical facts. This one for wisdom. You have clearly built non-trivial Angular apps sir! +1Globoid
This problem goes beyond angular, it is a fundamental problem in computer science, there is a point from which on one method is more efficient than the other. Usually this can be found through some benchmarking. So you could even switch between one method and the other depending on the item count ... Similar topic: math.stackexchange.com/questions/1632739/…Tengdin
B
13

One important note:

ngIf (unlike ngShow) usually creates child scopes that may produce unexpected results.

I had an issue related to this and I've spent MUCH time to figure out what was going on.

(My directive was writing its model values to the wrong scope.)

So, to save your hair just use ngShow unless you run too slow.

The performance difference is barely noticable anyway and I am not sure yet on who's favour is it without a test...

Boesch answered 10/9, 2014 at 11:43 Comment(4)
Using $parent.scopevar in data bindings within an ngIf will rectify things like child scopes issues when using ngIfVisionary
This is not entirely true (the original @user2173353's comment, that is). If you stick to good practices, you won't get into trouble. That's a pretty basic rule: "if there's no dot, you're doing it wrong". See here for a demo of how it works: bit.ly/1SPv4wL. Another great reference (see mistake #2): bit.ly/1QfFeWd > (My directive was writing its model values to the wrong scope.) This is the result of not sticking to the above practice.Haddix
@Haddix You are right, but that is not something a beginner may need to focus on and there is another best practice that says that it is better to leave performance improvements for the end (especially performance improvements that may not be improvements in reality). I have seen people putting ngIf everywhere believing that this will improve performance. This is simply not true and one can't say which is best, ngIf or ngShow, without a test or a deep analysis in the particular case. So, I still recommend forgetting about ngIf, until one sees bad performance or knows what he is doingBoesch
Good point. But using controllerAs makes this a non-issue. See, for instance, John Papa's take on controllerAs and vm.Giralda
W
5

If you use ng-show or ng-hide the content (eg. thumbnails from server) will be loaded irrespective of the value of expression but will be displayed based on the value of the expression.

If you use ng-if the content will be loaded only if the expression of the ng-if evaluates to truthy.

Using ng-if is a good idea in a situation where you are going to load data or images from the server and show those only depending on users interaction. This way your page load will not be blocked by unnecessary nw intensive tasks.

Wilk answered 20/9, 2015 at 17:36 Comment(1)
This is especially useful as most browsers will load images even if the CSS hides their DOM containers. They usually just look for the src attribute of the img tag, when present it gets loaded !Tengdin
S
4

ng-if on ng-include and on ng-controller will have a big impact matter on ng-include it will not load the required partial and does not process unless flag is true on ng-controller it will not load the controller unless flag is true but the problem is when a flag gets false in ng-if it will remove from DOM when flag gets true back it will reload the DOM in this case ng-show is better, for one time show ng-if is better

Sullins answered 4/7, 2014 at 3:49 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.