Home > database >  Send state back to parent component from child
Send state back to parent component from child

Time:05-25

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.

  • Related