Reputation: 6742
I have an angular app, where I have a popup component. I can control the popups visibility through it's parent and also from itself.
app.component.ts
import { Component } from '@angular/core';
@Component({
selector: 'my-app',
template: `
<popup [visible]="visible"></popup>
<button (click)="onShow()">Show</button>
<button (click)="onHide()">Hide</button>
`,
styleUrls: [ './app.component.css' ]
})
export class AppComponent {
public visible: boolean = false;
public onShow(): void {
this.visible = true;
}
public onHide(): void {
this.visible = false;
}
}
popup.component.ts
import { Component, Input } from '@angular/core';
@Component({
selector: 'popup',
template: `<div *ngIf="visible">My fancy popup <button (click)="onClick()">Click to close</button></div>`,
})
export class PopupComponent {
@Input()
public visible: boolean;
public onClick(): void {
this.visible = false;
}
}
Working stackblitz.
Use case:
The problem:
As far as I know, its because the visible
member inside app.component.ts
doesn't changes, so the PopupComponent
's @Input()
value doesn't changes either. Any idea how to fix this?
Upvotes: 2
Views: 5285
Reputation: 1986
popup.component.ts
import { Component, Input, OnInit, Output, EventEmitter } from '@angular/core';
@Component({
selector: 'popup',
template: `<div *ngIf="visible">My fancy popup <button (click)="onClick()">Click to close</button></div>`,
})
export class PopupComponent implements OnInit {
@Input() visible;
@Output() visibleUpdate = new EventEmitter();
// public visible: boolean;
ngOnInit() {
console.log('ngOnInit', this.visible);
}
public onClick(): void {
this.visible= false;
this.visibleUpdate.emit(this.visible);
console.log('onClick', this.visible);
}
}
app.component.ts
import { Component, Input} from '@angular/core';
@Component({
selector: 'my-app',
template: `<popup [visible]="visible" (visibleUpdate)="visibleUpdated($event)"></popup>
<button (click)="onShow()">Show</button>
<button (click)="onHide()">Hide</button>`,
styleUrls: [ './app.component.css' ]
})
export class AppComponent {
public visible: boolean = false;
public onShow(): void {
this.visible = true;
console.log('onShow', this.visible);
}
public onHide(): void {
this.visible = false;
console.log('onHide', this.visible);
}
public visibleUpdated($event): void {
this.visible = $event;
console.log('visibleUpdate', $event)
}
}
Let me know if you have any doubt.
Upvotes: 1
Reputation: 3386
You can use Event Emitter to pass value from child to parent
APP component
import { Component, Input, Output, EventEmitter } from '@angular/core';
@Component({
selector: 'popup',
template: `<div *ngIf="visible">My fancy popup <button (click)="onClick()">Click to close</button></div>`,
})
export class PopupComponent {
@Input()
public visible: boolean;
@Output() close: EventEmitter<any> = new EventEmitter();
public onClick(): void {
this.visible = false;
this.toggle();
}
toggle() {
this.close.emit(false);
}
}
App Component
import { Component } from '@angular/core';
@Component({
selector: 'my-app',
template: `
<popup [visible]="visible" (close)="onHide($event)"></popup>
<button (click)="onShow()">Show</button>
<button (click)="onHide()">Hide</button>
`,
styleUrls: [ './app.component.css' ]
})
export class AppComponent {
public visible: boolean = false;
public onShow(): void {
this.visible = true;
}
public onHide(value: boolean): void {
console.log(value)
if(value) {
this.visible = value;
} else {
this.visible = false;
}
}
}
Upvotes: 1
Reputation: 11982
You Should emit changes from child to parent:
export class PopupComponent {
@Input()
public visible: boolean;
@Output() visibleChange: EventEmitter<boolean> = new EventEmitter<boolean>();
public onClick(): void {
this.visible = false;
this.visibleChange.emit(this.visible);
}
}
parent:
@Component({
selector: 'my-app',
template: `
<popup [(visible)]="visible"></popup>
<button (click)="onShow()">Show</button>
<button (click)="onHide()">Hide</button>
`,
styleUrls: [ './app.component.css' ]
})
export class AppComponent {
public visible: boolean = false;
public onShow(): void {
this.visible = true;
}
public onHide(): void {
this.visible = false;
}
}
Upvotes: 5