Home > Software design >  Showing and Hiding a child component from parent for specific seconds
Showing and Hiding a child component from parent for specific seconds

Time:04-27

I have notification component, which is a child component and being shown in parent component after a button click. After a custom seconds of time it will be hidden. So far I have come up with this code (Stackblits).

MyCode

Parent component:

<button (click)="handleClick()">Initiate Message</button>

<app-notification [message]="message" [duration]="3000" [show]="show"></app-notification>

<app-notification [message]="message" [duration]="6000" [show]="show"></app-notification>
export class AppComponent  {
   message:string;
   show:boolean;


  handleClick(){
    this.message = 'Good Morning';
    this.show=true;
  }
}

Child comp:

<div  *ngIf="show">
  {{ message }}
</div>
 @Input() message: string;
  @Input() duration: number;
  @Input() show = false;

  constructor() {}

  ngOnChanges(changes: SimpleChanges) {
    console.log(this.show)
    setTimeout(()=>{
      this.show = false;
      console.log(3)
    }, this.duration)
  }

This works perfectly, but after 3 seconds as it is in the example, If I click the button, the child component is not being showed. What am I doing wrong. I am new to Angular, please help me.

Also I want to handle the same for both instances of the child.

CodePudding user response:

You have to move the code for the timeout out of ngOnChanges. In your component setup a setter would do the trick.

@Component({
  selector: 'app-notification',
  templateUrl: './notification.component.html',
  styleUrls: ['./notification.component.css'],
})
export class NotificationComponent {
  @Input() message: string;
  @Input() duration: number;
  @Input() set show(value: boolean) {
    this._show = value;
    // Or find another failsafe if the values are not set as expected
    if (value && this.duration) {
      this._show = true;
      setTimeout(() => {
        this._show = false;
      }, this.duration);
    }
  }
  get show(): boolean {
    return this._show;
  }

  private _show = false;
}

As well as an ugly hack to avoid Angular not realizing that this value needs to be reset:

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css'],
})
export class AppComponent {
  message: string;
  show: boolean;
  duration: number;

  handleClick() {
    this.message = 'Good Morning';
    this.show = true;
    setTimeout(() => (this.show = false), 1);
  }
}

Using RxJS Observables would solve this problem in a nice way, but it would also be more complicated if you are new to Angular.

CodePudding user response:

You can do like this: app.component.ts

import { Component } from '@angular/core';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: [ './app.component.css' ]
})
export class AppComponent  {
   message:string;
   show:boolean;
   duration:number;


  handleClick(){
    this.message = 'Good Morning';
    this.duration = 3000;
    this.show = true;
  }

  hideShow(event) {
    this.show = event;
  }
}

And app.component.html:

<button (click)="handleClick()">Initiate Message</button>

<app-notification [message]="message" [duration]="duration" [show]="show" (hideShow)="hideShow($event)"></app-notification>

And notification.component.ts:

import { Component, Input, OnChanges, OnInit, Output, SimpleChanges, EventEmitter } from '@angular/core';

@Component({
  selector: 'app-notification',
  templateUrl: './notification.component.html',
  styleUrls: ['./notification.component.css'],
})
export class NotificationComponent implements OnInit, OnChanges {
  @Input() message: string;
  @Input() duration: number;
  @Input() show: boolean;
  @Output() hideShow = new EventEmitter<boolean>();

  constructor() {}

  ngOnChanges(changes: SimpleChanges) {
    if(this.duration) {
      setTimeout(()=> {
        this.show = false;
        this.hideShow.emit(false);
      }, this.duration);
    }
  }
  
  ngOnInit() {
  }
}
  • Related