I have a parent component and a child component. The parent component could look something like this:
<button (click)="popupState = true>Click this to get a popup</button>
<popup-component [popupState]="popupState"></popup-component>
With the ts
file containing:
import { Component, OnInit} from '@angular/core';
@Component({
selector: 'parent-component',
templateUrl: './parent.component.html',
styleUrls: ['./parent.component.scss']
})
export class ParentComponent implements OnInit {
popupState: Boolean;
constructor() { }
ngOnInit() {
}
}
The child component, i.e. the popup, looks something like this:
<div [ngClass]="popupState? 'is-active' : ''">
<p>Hello world</p>
<button (click)="popupState= false">Cancel</button>
</div>
With the ts
file containing:
import { Component, OnInit, Input } from '@angular/core';
@Component({
selector: 'child-component',
templateUrl: './child.component.html',
styleUrls: ['./child.component.scss']
})
export class ChildComponent implements OnInit {
@Input() popupState: Boolean = false;
constructor() { }
ngOnInit() {
}
}
If I run this and click the button on the parent component the state is sent to the child component, and the child component popup-wrapper
gets the is-active
class added which makes it appear. When I click the cancel button in the child component the is-active
class is removed in the child component. However, the parent component still has the popupState
set to true
, hence when I try to click on the button again nothing happens.
So how to I make sure that the parent and child components have the same state at all times ?
CodePudding user response:
There are many ways to handle this type of situation.
First: Why don't you use ngIf in your parent component?
<popup-component *ngIf="popupState" (close)="popusState = false"></popup-component>
And child component:
- html file
<div [ngClass]="'is-active'">
<p>Hello world</p>
<button (click)="closePopup()">Cancel</button>
</div>
- ts file
export class ChildComponent implements OnInit {
@Input() popupState: Boolean = false;
@Output() close: EventEmitter<void> = new EventEmitter<void>();
public closePopup(): void {
this.closeEvent.emit()
}
}
Second(good solution): Use an external service
@Injectable({
providedIn: 'root',
})
export class PopupService {
private popupState: BehaviorSubject<boolean>(false);
public getPopupState: Observable<boolean> = this.popupState.asObservable();
public updatePopupState(value: boolean): void {
this.popupState.next(value);
}
}
You have to subscribe to getPopupState in both your components(child/parent), in this way, they both have the same state. And if you want to update the state, you can use updatePopupState method in both components.
Third(the best one): Use a state management library like NgRx (the boilerplate is quite big - https://ngrx.io/guide/store-devtools/install). So create a reducer with pop-up state and subscribe to that inside your components. You can run an action to update the state inside the reducer, and it will automatically update your components.
CodePudding user response:
when you made boolean false on the child. Its only for that child component but is being runned at parent. Creating a service would be the best thing if you want your property to be same on all child and parent.