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).
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() {
}
}