737

I have a number of elements that I want to be visible under certain conditions.

In AngularJS I would write

<div ng-show="myVar">stuff</div>

How can I do this in Angular 2+?

pjpscriv
  • 866
  • 11
  • 20
Mihai Răducanu
  • 12,225
  • 4
  • 22
  • 31

23 Answers23

1200

The hidden property can be used for that

[hidden]="!myVar"

See also

issues

hidden has some issues though because it can conflict with CSS for the display property.

See how some in Plunker example doesn't get hidden because it has a style

:host {display: block;}

set. (This might behave differently in other browsers - I tested with Chrome 50)

workaround

You can fix it by adding

[hidden] { display: none !important;}

To a global style in index.html.

another pitfall

hidden="false"
hidden="{{false}}"
hidden="{{isHidden}}" // isHidden = false;

are the same as

hidden="true"

and will not show the element.

hidden="false" will assign the string "false" which is considered truthy.
Only the value false or removing the attribute will actually make the element visible.

Using {{}} also converts the expression to a string and won't work as expected.

Only binding with [] will work as expected because this false is assigned as false instead of "false".

*ngIf vs [hidden]

*ngIf effectively removes its content from the DOM while [hidden] modifies the display property and only instructs the browser to not show the content but the DOM still contains it.

Günter Zöchbauer
  • 623,577
  • 216
  • 2,003
  • 1,567
  • 17
    `*ngIf` may be the correct way in most cases, but sometimes you actually want an element to be there, visually hidden. A CSS style with `[hidden]{display:none!important}` helps. That's, for example, how Bootstrap makes sure `[hidden]` elements are actually hidden. [See GitHub](https://github.com/twbs/bootstrap/blob/v4-dev/scss/_reboot.scss) – CunningFatalist Mar 01 '17 at 13:42
  • 1
    You may encounter some issue when you use (myStream | async) pipe inside of *ngIf that also uses (myStream | async) pipe – Pavel Blagodov Sep 26 '17 at 12:03
  • 2
    you are my saviour! using *ngIf will reset the DOM position to the top but [hidden] solved my problem and preserved the position. – Santosh Dec 08 '17 at 15:39
  • @GünterZöchbauer I feel like there used to some thing like *ngShow in the angular.io docs when I started following angular 4. but one thing I can confirm that now there is no such thing, and hidden is the only solution. I went looking for *ngShow myself few months back and found there is no such thing now, either use hidden or create a custom directive if one wants more customized control over this. – Saif Jan 20 '19 at 08:37
  • You might have landed on Angular 1 docs back then when you found it. – Günter Zöchbauer Jan 20 '19 at 09:21
  • 1
    One case where one might want to use [hidden] over *ngIf is when you are using HostListener (and want to differentiate document clicks vs event.target), when trying to show and hide elements (like with custom drop downs) – akhouri Aug 28 '19 at 02:30
  • 2
    @Sam, your comment is misleading. Yes, there are peculiarities about the `hidden`. But according to the linked article it is wrong to say `Using hidden is actually not recommended.`. – Sasuke Uchiha Sep 30 '20 at 17:10
192

Use the [hidden] attribute:

[hidden]="!myVar"

Or you can use *ngIf

*ngIf="myVar"

These are two ways to show/hide an element. The only difference is: *ngIf removes the element from DOM while [hidden] tells the browser to show/hide an element using CSS display property by keeping the element in DOM.

Ali Shahzad
  • 5,163
  • 7
  • 36
  • 64
  • 4
    [hidden] is adding conditionnaly an attribute "hidden" to the element. It also could be [whatever] or [ali]. The important thing here is to load a CSS rule who mention "hidden" attributes has to be display:none – Gabriel Aug 05 '16 at 07:14
  • 7
    Bear in mind: *ngIf and [hidden] are fundamentalyl different. ngIf will not evaluate the content inside the *ngIf block until the condition is true. This is especially important if you use the `async` pipe, as the subscription to the observable will only be added after the condition becomes true! – Dynalon Sep 09 '16 at 07:59
  • 4
    One more thing to take into consideration is that *ngIf destroys the component and it has to be re-created, while [hidden] keeps it alive and in memory. If you have a resource-intense component it may be preferable to hide it instead of destroy it – Michael Kork. Nov 16 '17 at 15:33
  • 1
    they are not same thing. – Kamuran Sönecek Aug 18 '18 at 10:37
  • As stated, not the same at all. If a component is using `ngIf` and the result is false it will not be rendered at all, so any code inside the component will not run until the `ngIf` condition is met. – Daniel Dewhurst Jan 08 '21 at 14:21
55

I find myself in the same situation with the difference than in my case the element was a flex container.If is not your case an easy work around could be

[style.display]="!isLoading ? 'block' : 'none'"

in my case due to the fact that a lot of browsers that we support still need the vendor prefix to avoid problems i went for another easy solution

[class.is-loading]="isLoading"

where then the CSS is simple as

&.is-loading { display: none } 

to leave then the displayed state handled by the default class.

Valex
  • 1,149
  • 1
  • 8
  • 14
33

Sorry, I have to disagree with binding to hidden which is considered to be unsafe when using Angular 2. This is because the hidden style could be overwritten easily for example using

display: flex;

The recommended approach is to use *ngIf which is safer. For more details, please refer to the official Angular blog. 5 Rookie Mistakes to Avoid with Angular 2

<div *ngIf="showGreeting">
   Hello, there!
</div>
Tim Hong
  • 2,734
  • 20
  • 23
  • 14
    I think it's a rookie mistake to say something is bad before knowing the exact requirements. If one doesn't want an element to be removed and destroyed and added and recreated, `*ngIf` is a poor choice. But you are right that consequences need to be considered and pointing out pitfalls is always a good idea. – Günter Zöchbauer Nov 25 '16 at 05:43
  • 2
    I know what you mean. It is not my word about it is a novice mistake, it is taken from Angular 2 official blog. I don't mean to offend anyone. Thanks for pointing out, though. – Tim Hong Nov 25 '16 at 21:22
  • 11
    Yeah, I don't think `ngIf` exactly answers what this question is asking. I want to hide some content on a page that includes a ``. If I use `ngIf`, I get an error that it can't find the outlet. I need the outlet to be _hidden_ until my data loads, not _absent_ until my data loads. – Jason Swett Nov 27 '16 at 23:56
  • I agree with you, but the problem that I have is I want to show a form and put values in it if I use the *ngIf I will have the error that it is not defined and with the hidden property it is working well – Hazem HASAN Mar 05 '19 at 08:49
  • @HazemHASAN, sure. I understand. The solution is always conditional. In your case, not sure if it is possible to just check if the form is there before you run any other code against it. It is all about the trade-off. Do you want a safer way to hide the form which will not be offset by another styling in future accidentally? Or do you prefer to have the convenience not to check if the form exists? – Tim Hong Mar 05 '19 at 21:08
17

this is what worked for me:

<div [style.visibility]="showThis ? 'visible' : 'hidden'">blah</div>
Alex
  • 836
  • 9
  • 19
14
<div [hidden]="myExpression">

myExpression may be set to true or false

masterxilo
  • 2,503
  • 1
  • 30
  • 35
Niyaz
  • 2,677
  • 3
  • 21
  • 40
  • 2
    ` – Viprus Sep 06 '17 at 13:21
  • 1
    @Viprus Not picking on you, but I've seen this misuse of the word "truthy" here before. If the CSS selector is `[hidden]`, and the attribute is present in HTML and has a value, the rule will be applied. Truthiness doesn't matter in this case as it's not JS. – Ryan Haney Aug 23 '21 at 21:04
10

According to Angular 1 documentation of ngShow and ngHide, both of these directive adds the css style display: none !important;, to the element according to the condition of that directive (for ngShow adds the css on false value, and for ngHide adds the css for true value).

We can achieve this behavior using Angular 2 directive ngClass:

/* style.css */
.hide 
{
    display: none !important;
}

<!-- old angular1 ngShow -->
<div ng-show="ngShowVal"> I'm Angular1 ngShow... </div>

<!-- become new angular2 ngClass -->
<div [ngClass]="{ 'hide': !ngShowVal }"> I'm Angular2 ngShow... </div>

<!-- old angular1 ngHide -->
<div ng-hide="ngHideVal"> I'm Angular1 ngHide... </div>

<!-- become new angular2 ngClass -->
<div [ngClass]="{ 'hide': ngHideVal }"> I'm Angular2 ngHide... </div>

Notice that for show behavior in Angular2 we need to add ! (not) before the ngShowVal, and for hide behavior in Angular2 we don't need to add ! (not) before the ngHideVal.

Gil Epshtain
  • 8,670
  • 7
  • 63
  • 89
9

For anybody else stumbling across this issue, this is how I accomplished it.

import {Directive, ElementRef, Input, OnChanges, Renderer2} from "@angular/core";

@Directive({
  selector: '[hide]'
})
export class HideDirective implements OnChanges {
  @Input() hide: boolean;

  constructor(private renderer: Renderer2, private elRef: ElementRef) {}

  ngOnChanges() {
    if (this.hide) {
      this.renderer.setStyle(this.elRef.nativeElement, 'visibility', 'hidden');
    } else {
      this.renderer.setStyle(this.elRef.nativeElement, 'visibility', 'visible');
    }
  }
}

I used 'visibility' because I wanted to preserve the space occupied by the element. If you did not wish to do so, you could just use 'display' and set it to 'none';

You can bind it to your html element, dynamically or not.

<span hide="true"></span>

or

<span [hide]="anyBooleanExpression"></span>
Anjil Dhamala
  • 1,544
  • 3
  • 18
  • 37
7

If your case is that the style is display none you can also use the ngStyle directive and modify the display directly, I did that for a bootstrap DropDown the UL on it is set to display none.

So I created a click event for "manually" toggling the UL to display

<div class="dropdown">
    <button class="btn btn-default" (click)="manualtoggle()"  id="dropdownMenu1" >
    Seleccione una Ubicación
    <span class="caret"></span>
    </button>
    <ul class="dropdown-menu" [ngStyle]="{display:displayddl}">
        <li *ngFor="let object of Array" (click)="selectLocation(location)">{{object.Value}}</li>                                
     </ul>
 </div>    

Then on the component I have showDropDown:bool attribute that I toggle every time, and based on int, set the displayDDL for the style as follows

showDropDown:boolean;
displayddl:string;
manualtoggle(){
    this.showDropDown = !this.showDropDown;
    this.displayddl = this.showDropDown ? "inline" : "none";
}
Gary
  • 602
  • 9
  • 7
6

Use hidden like you bind any model with control and specify css for it:

HTML:

<input type="button" class="view form-control" value="View" [hidden]="true" />

CSS:

[hidden] {
   display: none;
}
4

If you are using Bootstrap is as simple as this:

<div [class.hidden]="myBooleanValue"></div>
Gian Marco
  • 22,140
  • 8
  • 55
  • 44
4

in bootstrap 4.0 the class "d-none" = "display: none!important;"

<div [ngClass]="{'d-none': exp}"> </div>
63RMAN
  • 519
  • 4
  • 6
4

for me, [hidden]=!var has never worked.

So, <div *ngIf="expression" style="display:none;">

And, <div *ngIf="expression"> Always give correct results.

Ganesh
  • 5,808
  • 2
  • 21
  • 41
Priyanka Arora
  • 409
  • 4
  • 10
3
<div [hidden]="flagValue">
---content---
</div>
Chirag
  • 413
  • 1
  • 6
  • 16
3

using [ngStyle]

[ngStyle]="{'visibility': my-flag ? 'visible' : 'hidden'}"
mahmoud elgml
  • 161
  • 1
  • 6
2

My issue was displaying/hiding a mat-table on a button click using <ng-container *ngIf="myVar">. The 'loading' of the table was very slow with 300 records at 2-3 seconds.

The data is loaded using a subscribe in ngOnInit(), and is available and ready to be used in the template, however the 'loading' of the table in the template became increasingly slower with the increase in number of rows.

My solution was to replace the *ngIf with:

<div [style.display]="activeSelected ? 'block' : 'none'">

. Now the table loads instantly when the button is clicked.

T. Bulford
  • 387
  • 5
  • 8
2

[hidden]="yourVariable" OR [style.display]="!isShow? 'block' : 'none'"

  • 1
    Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Aug 08 '22 at 13:46
1

Best way to deal with this issue using ngIf Because this will prevent getting that element render in front-end,

If you use [hidden]="true" or style hide [style.display] it will only hide the element in front end and someone can change the value of it and view it easily, In my opinion best way to hide elements is ngIf

<div *ngIf="myVar">stuff</div>

And also If you have multiple elements (need to implement else also) you can Use <ng-template> option

<ng-container *ngIf="myVar; then loadAdmin else loadMenu"></ng-container>
<ng-template #loadMenu>
     <div>loadMenu</div>
</ng-template>

<ng-template #loadAdmin>
     <div>loadAdmin</div>
</ng-template>  

sample ng-template code

DeC
  • 2,226
  • 22
  • 42
  • I agree with you, it's preferred to use *ngIf instead of hidden for some performance reason to DOM optimisation – Rebai Ahmed Jul 13 '21 at 22:20
1

You have two options:

First Option

[style.display]="!isShow ? 'block' : 'none'"

Second Option

myVarible can be boolean

[hidden]="!myVarible"
Naeem Bashir
  • 1,937
  • 20
  • 17
0

To hide and show div on button click in angular 6.

Html Code

<button (click)="toggleElement()">FormatCell</button>
<div class="ruleOptionsPanel" *ngIf="isShow">
   <table>
      <tr>
         <td>Name</td>
         <td>Ram</td>
      </tr>
   </table>
</div>

AppComponent.ts Code

@Component({
   selector: 'app-root',
   templateUrl: './app.component.html',
   styleUrls: ['./app.component.css']
})
export class AppComponent{
   isShow=false;
   toggleElement():void
   {
      this.isShow = !this.isShow
   }
}

this works for me and it is a way to replace ng-hide and ng-show in angular2+

IAfanasov
  • 4,775
  • 3
  • 27
  • 42
Manoj Gupta
  • 456
  • 4
  • 9
  • You are using ngIf - which is different than ngShow. NgIf will remove/add the element form the DOM. This is not the same as ngShow/ngHide which will only add/remove Css styles to the Element. – Gil Epshtain Jan 28 '19 at 17:19
  • The example is too long and too specific. – masterxilo Jun 18 '19 at 11:06
0

There are two examples on Angular documents https://angular.io/guide/structural-directives#why-remove-rather-than-hide

A directive could hide the unwanted paragraph instead by setting its display style to none.

<p [style.display]="'block'">
  Expression sets display to "block".
  This paragraph is visible.
</p>

<p [style.display]="'none'">
  Expression sets display to "none".
  This paragraph is hidden but still in the DOM.
</p>

You can use [style.display]="'block'" to replace ngShow and [style.display]="'none'" to replace ngHide.

koo
  • 171
  • 1
  • 11
0

If you just want to use the symmetrical hidden/shown directives that AngularJS came with, I suggest writing an attribute directive to simplify the templates like so (tested with Angular 7):


import { Directive, Input, HostBinding } from '@angular/core';

@Directive({ selector: '[shown]' })
export class ShownDirective {
  @Input() public shown: boolean;

  @HostBinding('attr.hidden')
  public get attrHidden(): string | null {
    return this.shown ? null : 'hidden';
  }
}

Many of the other solutions are correct. You should use *ngIf where ever possible. Using the hidden attribute can have unexpected styles applied, but unless you are writing components for others, you probably know if it is. So for this shown directive to work, you will also want to make sure that you add:

[hidden]: {
  display: none !important;
}

to your global styles somewhere.

With these you can use the directive like so:

<div [shown]="myVar">stuff</div>

with the symmetrical (and opposite) version like so:

<div [hidden]="myVar">stuff</div>

To add on to the shoulds - yous should also us a prefix like so [acmeShown] vs just [shown].

The main reason I used a shown attribute directive is for converting AngularJS code to Angular -AND- when the content that is being hidden contains container components that cause XHR round trips. The reason I don't just use [hidden]="!myVar" is that often enough it is more complicated like: [hidden]="!(myVar || yourVar) && anotherVar" - yes I can invert that, but it is more error prone.[shown]` is simply easier to think about.

nephiw
  • 1,964
  • 18
  • 38
0

This answer is for those who don't know how make an element hide, visible from .ts file

TS File

export class PostTweetComponent implements OnInit {
isHidden:boolean = false;
  hide(){
    this.isHidden = true;
  }
  unHide(){
    this.isHidden = false;
  }
}

HTML File

<div [hidden]="isHidden">stuff</div>
<button (click)="hide()">Hide</button>
<button (click)="unHide()">UnHide</button>
Raghunath
  • 141
  • 1
  • 5