Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Update parent component property from child component in Angular 2

I'm using @input to receive a property from parent component in order to activate a CSS class in one of child component's element.

I'm able to receive the property from parent and also activate the class. But this works only once. The property i'm receiving from parent is a boolean data typed and when I set the status of it to false from child component, it does not change in parent.

Plunkr: https://plnkr.co/edit/58xuZ1uzvToPhPtOING2?p=preview

app.ts

import {Component, NgModule} from '@angular/core' import {BrowserModule} from '@angular/platform-browser' import { HeaderComponent } from './header'; import { SearchComponent } from './header/search';  @Component({   selector: 'my-app',   template: `     <app-header></app-header>   `, }) export class App {   name:string;   constructor() {   } }  @NgModule({   imports: [ BrowserModule ],   declarations: [ App, HeaderComponent, SearchComponent ],   bootstrap: [ App ] }) export class AppModule {} 

header.ts

import { Component, OnInit } from '@angular/core';  @Component({   selector: 'app-header',   template: `<header>               <app-search [getSearchStatus]="isSearchActive"></app-search>               <button (click)="handleSearch()">Open Search</button>             </header>` }) export class HeaderComponent implements OnInit {   isSearchActive = false;    handleSearch() {     this.isSearchActive = true     console.log(this.isSearchActive)   }    constructor() { }   ngOnInit() { } } 

header/search.ts

import { Component, OnInit, Input } from '@angular/core';  @Component({   selector: 'app-search',   template: `<div id="search" [class.toggled]="getSearchStatus">               search                <button  (click)="getSearchStatus = false" class="close">Close Search</button>             </div>` }) export class SearchComponent implements OnInit {   @Input() getSearchStatus: boolean;    constructor() { }    ngOnInit() {    } } 

Please check the above given plunker. The open search function works only once. After closing the search, it does not trigger again.

Is @input is the proper use case for this scenario? Please help me fix this. (Please update the plunker).

like image 501
Body Avatar asked Jan 04 '17 13:01

Body


People also ask

How will you send data from a child component to the parent component?

To pass data from child to parent component in React:Pass a function as a prop to the Child component. Call the function in the Child component and pass the data as arguments. Access the data in the function in the Parent .

How do you pass data from child component to parent component in Angular?

The @Output() decorator in a child component or directive lets data flow from the child to the parent. @Output() marks a property in a child component as a doorway through which data can travel from the child to the parent.

How do you call parent components from a child?

To call a parent's function from a child component, pass the function reference to the child component as a prop. Then you can call that parent's function from the child component like props. parentMethodName().


2 Answers

You need to use 2 way data-binding.

@Input() is one way data-binding. to enable 2 way data-binding you need to add an @Output() corresponding to the property, with a "Change" suffix

@Input() getSearchStatus: boolean; @Output() getSearchStatusChange = new EventEmitter<boolean>(); 

when you want to publish the change made to your property to the parent, you need to notify the parent with:

this.getSearchStatusChange.emit(newValue) 

and in the parent you need to use the banana-in-a-box notation for that property:

[(getSearchStatus)]="myBoundProperty" 

you can also bind to the property and trigger a callback when it changes in child:

[getSearchStatus]="myBoundProperty" (getSearchStatusChange)="myCrazyCallback($event)" 

see the plnkr

like image 80
n00dl3 Avatar answered Oct 20 '22 12:10

n00dl3


Another approach: use rxjs/BehaviorSubject to pass status between different components.
Here's the plunkr.
I name subject with a suffix 'Rxx', so the BehaviorSubject for searchStatus will be searchStatusRxx.

  1. initialize it in parent component like searchStatusRxx = new BehaviorSubject(false);,
  2. pass it to child component using @Input
  3. in child template, you do async pipe.
  4. in both parent and child, you do searchStatusRxx.next(value) to change the latest value.
like image 33
Timathon Avatar answered Oct 20 '22 11:10

Timathon