217

I'm having a problem hiding and showing an element depending of a boolean variable in Angular 2.

this is the code for the div to show and hide:

<div *ngIf="edited==true" class="alert alert-success alert-dismissible fade in" role="alert">
        <strong>List Saved!</strong> Your changes has been saved.
</div>

the variable is "edited" and it's stored in my component:

export class AppComponent implements OnInit{

  (...)
  public edited = false;
  (...)
  saveTodos(): void {
   //show box msg
   this.edited = true;
   //wait 3 Seconds and hide
   setTimeout(function() {
       this.edited = false;
       console.log(this.edited);
   }, 3000);
  }
}

The element is hidden, when saveTodos function starts, the element is shown, but after 3 seconds, even if the variable come back to be false, the element does not hide. Why?

11 Answers11

231

There are two options depending what you want to achieve :

  1. You can use the hidden directive to show or hide an element

    <div [hidden]="!edited" class="alert alert-success box-msg" role="alert">
      <strong>List Saved!</strong> Your changes has been saved.
    </div>
    
  2. You can use the ngIf control directive to add or remove the element. This is different of the hidden directive because it does not show / hide the element, but it add / remove from the DOM. You can loose unsaved data of the element. It can be the better choice for an edit component that is cancelled.

    <div *ngIf="edited" class="alert alert-success box-msg" role="alert"> 
      <strong>List Saved!</strong> Your changes has been saved.
    </div>
    

For you problem of change after 3 seconds, it can be due to incompatibility with setTimeout. Did you include angular2-polyfills.js library in your page ?

jonrsharpe
  • 115,751
  • 26
  • 228
  • 437
gentiane
  • 6,715
  • 3
  • 23
  • 34
  • 8
    `[hidden]="edited"` doesnt seem to have any effects...? – phil294 Jan 30 '17 at 14:31
  • 8
    In case you have issues with hidden, please follow the answer of http://stackoverflow.com/a/35578093/873282: `[hidden] { display: none !important;}` in your global css. – koppor Apr 02 '17 at 16:33
189

You should use the *ngIf Directive

<div *ngIf="edited" class="alert alert-success box-msg" role="alert">
        <strong>List Saved!</strong> Your changes has been saved.
</div>


export class AppComponent implements OnInit{

  (...)
  public edited = false;
  (...)
  saveTodos(): void {
   //show box msg
   this.edited = true;
   //wait 3 Seconds and hide
   setTimeout(function() {
       this.edited = false;
       console.log(this.edited);
   }.bind(this), 3000);
  }
}

Update: you are missing the reference to the outer scope when you are inside the Timeout callback.

so add the .bind(this) like I added Above

Q : edited is a global variable. What would be your approach within a *ngFor-loop? – Blauhirn

A : I would add edit as a property to the object I am iterating over.

<div *ngFor="let obj of listOfObjects" *ngIf="obj.edited" class="alert alert-success box-msg" role="alert">
        <strong>List Saved!</strong> Your changes has been saved.
</div>


export class AppComponent implements OnInit{
   
  public listOfObjects = [
    {
       name : 'obj - 1',
       edit : false
    },
    {
       name : 'obj - 2',
       edit : false
    },
    {
       name : 'obj - 2',
       edit : false
    } 
  ];
  saveTodos(): void {
   //show box msg
   this.edited = true;
   //wait 3 Seconds and hide
   setTimeout(function() {
       this.edited = false;
       console.log(this.edited);
   }.bind(this), 3000);
  }
}
Community
  • 1
  • 1
inoabrian
  • 3,762
  • 1
  • 19
  • 27
42

When you don't care about removing the Html Dom-Element, use *ngIf.

Otherwise, use this:

<div [style.visibility]="(numberOfUnreadAlerts == 0) ? 'hidden' : 'visible' ">
   COUNTER: {{numberOfUnreadAlerts}} 
</div>
Dudi
  • 3,069
  • 1
  • 27
  • 23
16

For child component to show I was using *ngif="selectedState == 1"

Instead of that I used [hidden]="selectedState!=1"

It worked for me.. loading the child component properly and after hide and un-hide child component was not undefined after using this.

Swapnil Kale
  • 2,620
  • 2
  • 23
  • 21
10

This is a good use case for an Angular Directive. Something like this is surprisingly useful.

@Directive({
  selector: '[removeAfter]'
})
export class RemoveAfter {
  constructor(readonly element: ElementRef<HTMLElement>) { }
 
  /**
   * Removes the attributed element after the specified number of milliseconds.
   */
  @Input() removeAfter: number;

  ngOnInit() {
    setTimeout(() => {
      this.element.nativeElement.remove();
    }, this.removeAfter);
  }
}

Usage:

<div [removeAfter]="3000">Removed after 3 seconds</div>
Aluan Haddad
  • 29,886
  • 8
  • 72
  • 84
  • I like the idea, but this will remove the element completely. I changed it to hide, so you could reuse it but that doesn't hide the element presumably due to the `ngIf` is `true`. Is there a way to set the parent's variable that controls this to `false`? – occasl Mar 21 '17 at 20:13
  • Can't you just add a hidden class or something instead of calling remove? This technique is pretty generic. – Aluan Haddad Mar 21 '17 at 20:31
  • I think the problem is `ngIf` is more for whether the element is in the DOM or not. What I want is this: `
    ...` where I show/hide messages if there are any and then remove messages after 3 seconds so user doesn't have to close box. I added your directive above and switched it to do a `hide()` but it doesn't get called when the messages are shown. How do I get it to be invoked on the event? `@Output()` and `EventEmitter`?
    – occasl Mar 21 '17 at 22:02
8

In TS file

showMyContainer: boolean = false;

In HTML

<button (click)="showMyContainer=!showMyContainer">Show/Hide</button>

<div *ngIf="showMyContainer">
     your code
</div>

See my stackblitz

Happy to hear if someone got helped.

Pullat Junaid
  • 3,224
  • 3
  • 25
  • 25
6

We can do it by using the below code snippet..

Angular Code:

 export class AppComponent {  
    toggleShowHide: string = "visible";  
 }

HTML Template:

  Enter text to hide or show item in bellow: 
  <input type="text" [(ngModel)]="toggleShowHide">
  <br>
  Toggle Show/hide:
  <div [style.visibility]="toggleShowHide">   
     Final Release Angular 2!
  </div>
j3ff
  • 5,719
  • 8
  • 38
  • 51
Rejwanul Reja
  • 1,339
  • 1
  • 17
  • 19
4

Depending on your needs, *ngIf or [ngClass]="{hide_element: item.hidden}" where CSS class hide_element is { display: none; }

*ngIf can cause issues if you're changing state variables *ngIf is removing, in those cases using CSS display: none; is required.

Günter Zöchbauer
  • 623,577
  • 216
  • 2,003
  • 1,567
Luke Dupin
  • 2,275
  • 23
  • 30
0

@inoabrian solution above worked for me. I ran into a situation where I would refresh my page and my hidden element would reappear on my page. Here's what I did to resolve it.

export class FooterComponent implements OnInit {
public showJoinTodayBtn: boolean = null;

ngOnInit() {
      if (condition is true) {
        this.showJoinTodayBtn = true;
      } else {
        this.showJoinTodayBtn = false;
      }
}
Jason Spence
  • 472
  • 5
  • 16
0

Just add bind(this) in your setTimeout function it will start working

setTimeout(function() {
       this.edited = false;
       console.log(this.edited);
   }.bind(this), 3000);

and in HTML change

<div *ngIf="edited==true" class="alert alert-success alert-dismissible fade in" role="alert">
        <strong>List Saved!</strong> Your changes has been saved.
</div>

To

<div *ngIf="edited" class="alert alert-success alert-dismissible fade in" role="alert">
        <strong>List Saved!</strong> Your changes has been saved.
</div>
Mukesh Rawat
  • 894
  • 2
  • 8
  • 27
0

You can use the built-in HTML attribute that can be used to conditionally hide or show an element which is [hidden].

NOTE: This will work on div if you try on any other element tag like this will not work.

HTML

<div [hidden]="edited" class="alert alert-success alert-dismissible fade in" role="alert">
        <strong>List Saved!</strong> Your changes has been saved.
</div>

TS file

export class AppComponent implements OnInit{
  edited: boolean;
  constructor(){}

  // function that does something then updates the edited condition
  func(){

   .....
    this.edited = true;
  }

....
 
}
Philip Mutua
  • 6,016
  • 12
  • 41
  • 84