ChatGPT解决这个技术问题 Extra ChatGPT

What is the difference between ng-if and ng-show/ng-hide

I'm trying to understand the difference between ng-if and ng-show/ng-hide, but they look the same to me.

Is there a difference that I should keep in mind choosing to use one or the other?


G
Gajus

ngIf

The ngIf directive removes or recreates a portion of the DOM tree based on an expression. If the expression assigned to ngIf evaluates to a false value then the element is removed from the DOM, otherwise a clone of the element is reinserted into the DOM.

<!-- when $scope.myValue is truthy (element is restored) -->
<div ng-if="1"></div>

<!-- when $scope.myValue is falsy (element is removed) -->
<div ng-if="0"></div>

When an element is removed using ngIf its scope is destroyed and a new scope is created when the element is restored. The scope created within ngIf inherits from its parent scope using prototypal inheritance.

If ngModel is used within ngIf to bind to a JavaScript primitive defined in the parent scope, any modifications made to the variable within the child scope will not affect the value in the parent scope, e.g.

<input type="text" ng-model="data">
<div ng-if="true">
    <input type="text" ng-model="data">
</div>        

To get around this situation and update the model in the parent scope from inside the child scope, use an object:

<input type="text" ng-model="data.input">
<div ng-if="true">
    <input type="text" ng-model="data.input">
</div>

Or, $parent variable to reference the parent scope object:

<input type="text" ng-model="data">
<div ng-if="true">
    <input type="text" ng-model="$parent.data">
</div>

ngShow

The ngShow directive shows or hides the given HTML element based on the expression provided to the ngShow attribute. The element is shown or hidden by removing or adding the ng-hide CSS class onto the element. The .ng-hide CSS class is predefined in AngularJS and sets the display style to none (using an !important flag).

<!-- when $scope.myValue is truthy (element is visible) -->
<div ng-show="1"></div>

<!-- when $scope.myValue is falsy (element is hidden) -->
<div ng-show="0" class="ng-hide"></div>

When the ngShow expression evaluates to false then the ng-hide CSS class is added to the class attribute on the element causing it to become hidden. When true, the ng-hide CSS class is removed from the element causing the element not to appear hidden.


Hint: By removing the HTML element itself with ng-if the model, added by ng-model, doesn't exists anymore.
@CodeHater I've successfully leveraged ng-if over ng-show / ng-hide on a page that would have otherwise had a large dom. It seemed to make the page feel quicker, but is by no means scientific analysis.
The part I'm having trouble with fully understanding is how/why when you have an object in the model data.input it works... but data alone in the model doesn't work. @CodeHater
@mcpDESIGNS ngIf creates a new scope, so looking at the example above the nested ngModel would create a new data model even though a model with same name exists in the parent scope. But when you use a dot notation, you make JS look up the scope's prototype chain. So if it does not find the value in the current scope, it will try to look for it in the parent scope and so on. Few other directives that create a different scope are ngInclude, ngRepeat. Hope its clear now. :)
Which one is better for performance? I think ng-show and ng-hide isn't it?
g
gjoris

Maybe an interesting point to make, is the difference between priorities between both.

As far as I can tell, the ng-if directive has one of the highest (if not the highest) priority of all Angular directives. Which means: it will run FIRST before all other, lower prioritised, directives. The fact that it runs FIRST, means that effectively, the element is removed before any inner directives are processed. Or at least: that's what I make of it.

I observerd and used this in the UI I'm building for my current customer. The entire UI is quite heavily packed, and it had ng-show and ng-hide all over it. Not to go into too much detail, but I built a generic component, which could be managed using JSON config, so I had to do some switching inside the template. There is an ng-repeat present, and inside the ng-repeat, a table is shown, which has a lot of ng-shows, ng-hides and even ng-switches present. They wanted to show at least 50 repeats in the list, which would result in more or less 1500-2000 directives to be resolved. I checked the code, and the Java backend + custom JS on the front would take about 150ms to process the data, and then Angular would chew some 2-3 seconds on it, before displaying. The customer did not complain, but I was appalled :-)

In my search, I stumbled across the ng-if directive. Now, maybe it's best to point out that at the point of conceiving this UI, there was no ng-if available. Because the ng-show and ng-hide had functions in them, which returned booleans, I could easily replace them all with ng-if. By doing so, all inner directives seemed to be no longer evaluated. That meant that I dropped back to about a third of all directives being evaluated, and thus, the UI speeded up to about 500ms - 1 sec loading time. (I have no way to determine exact seconds)

Do note: the fact that the directives are not evaluated, is an educated guess about what is happening underneath.

So, in my opinion: if you need the element to be present on the page (ie: for checking the element, or whatever), but simply be hidden, use ng-show/ng-hide. In all other cases, use ng-if.


Yes, I guess this is the goal of ng-if: to decrease processing time. This directive exists for sure not only due to some CSS pseudoselectors. Good post! +1
A
Andrei

The ng-if directive removes the content from the page and ng-show/ng-hide uses the CSS display property to hide content.

This is useful in case you want to use :first-child and :last-child pseudo selectors to style.


what do you mean by using the :first and :last selector ?
A
AturSams

@EdSpencer is correct. If you have a lot of elements and you use ng-if to only instantiate the relevant ones, you are saving resources. @CodeHater is also somewhat correct, if you are going to remove and show an element very often, hiding it instead of removing it could improve performance.

The main use case I find for ng-if is that it allows me to cleanly validate and eliminte an element if the contents is illegal. For instance I could reference to a null image name variable and that will throw an error but if I ng-if and check if it's null, it's all good. If I did an ng-show, the error would still fire.


s
supersan

One important thing to note about ng-if and ng-show is that when using form controls it is better to use ng-if because it completely removes the element from the dom.

This difference is important because if you create an input field with required="true" and then set ng-show="false" to hide it, Chrome will throw the following error when the user tries to submit the form:

An invalid form control with name='' is not focusable.

The reason being the input field is present and it is required but since it is hidden Chrome cannot focus on it. This can literally break your code as this error halts script execution. So be careful!


This is the real fact, if you are using form controls for validation then you will suffer a lot if you use ng-show/ng-hide . And if you have multiple sections hidden/show based on expression. So if you use ng-show/hide the elements will be still there and validation will fail,in spite of them not being on screen. so ng-if rescue you :)
佚名

@Gajus Kuizinas and @CodeHater are correct. Here i am just giving an example. While we are working with ng-if, if the assigned value is false then the whole html elements will be removed from DOM. and if assigned value is true, then the html elements will be visible on the DOM. And the scope will be different compared to the parent scope. But in case of ng-show, it wil just show and hide the elements based on the assigned value. But it always stays in the DOM. Only the visibility changes as per the assigned value.

http://plnkr.co/edit/3G0V9ivUzzc8kpLb1OQn?p=preview

Hope this example will help you in understanding the scopes. Try giving false values to ng-show and ng-if and check the DOM in console. Try entering the values in the input boxes and observe the difference.

<!DOCTYPE html>

Hello Plunker!

<input type="text" ng-model="data">
<div ng-show="true">
    <br/>ng-show=true :: <br/><input type="text" ng-model="data">
</div>
<div ng-if="true">
    <br/>ng-if=true :: <br/><input type="text" ng-model="data">
</div> 
{{data}}


S
Slava Utesinov

Fact, that ng-if directive, unlike ng-show, creates its own scope, leads to interesting practical difference:

angular.module('app', []).controller('ctrl', function($scope){ $scope.delete = function(array, item){ array.splice(array.indexOf(item), 1); } })

ng-if:

  • {{show}}

ng-show:

  • {{show}}

ng-if with $parent:

  • {{show}}

At first list, on-click event, show variable, from innner/own scope, is changed, but ng-if is watching on another variable from outer scope with same name, so solution not works. At case of ng-show we have the only one show variable, that is why it works. To fix first attempt, we should reference to show from parent/outer scope via $parent.show.


A
Amay Kulkarni

ng-if if false will remove elements from DOM. This means that all your events, directives attached to those elements will be lost. For example, ng-click to one of child elements, when ng-if evaluates to false, that element will be removed from DOM and again when it is true it is recreated. ng-show/ng-hide does not remove the elements from DOM. It uses CSS styles (.ng-hide) to hide/show elements .This way your events, directives that were attached to children will not be lost. ng-if creates a child scope while ng-show/ng-hide does not.


P
Prasad

ng-show and ng-hide work in opposite way. But the difference between ng-hide or ng-show with ng-if is,if we use ng-if then element will created in the dom but with ng-hide/ng-show element will be hidden completely.

ng-show=true/ng-hide=false:
Element will be displayed

ng-show=false/ng-hide=true:
element will be hidden

ng-if =true
element will be created

ng-if= false
element will be created in the dom. 

h
helius

To note, a thing that happened to me now: ng-show does hide the content via css, yes, but it resulted in strange glitches in div's supposed to be buttons.

I had a card with two buttons on the bottom and depending on the actual state one is exchanged with an third, example edit button with new entry. Using ng-show=false to hide the left one(present first in the file) it happened that the following button ended up with the right border outside of the card. ng-if fixes that by not including the code at all. (Just checked here if there are some hidden surprises using ng-if instead of ng-show)


c
curiousBoy

ngIf makes a manipulation on the DOM by removing or recreating the element.

Whereas ngShow applies a css rules to hide/show things.

For most of the cases (not always), I would summarize this as, if you need a one time check to show/hide things, use ng-if, if you need to show/hide things based on the user actions on the screen (like checked a checkbox then show textbox, unchecked then hide textbox etc..), then use ng-show


A
Ashish_B

One interesting difference in ng-if and ng-show is:

SECURITY

DOM elements present in ng-if block will not be rendered in case of its value as false

where as in case of ng-show, the user can open your Inspect Element Window and set its value to TRUE.

And with a whoop, whole contents that was meant to be hidden gets displayed, which is a security breach. :)


This is an extremely weak form of security. If the content is given to the client by the server, then you have to assume the user/attacker can access it, regardless of whether or not it's present in the DOM. All authorization logic must be enforced by the server.
think about html rather than jsp...now if you want to enforce security on html components ..i.e. if you want to hide some components from user...how would you achieve that. And what in case your configuration is divided into server side for backend and client side for front end..