Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular 2 ngModel in child component updates parent component property

I made a simple UI which consist two components (parent and child).

What the UI does is that when I type some stuff in the input box of the Child component. The value will change using ngModel.

The child component works fine that way.

// Child Component @Component({     selector: 'child',     template: `         <p>{{sharedVar}}</p>         <input [(ngModel)]="sharedVar">     ` }) export class ChildComponent {     sharedVar: string; } 

Now I have a parent component which I intend to use the same value as Child Component.

I added the Child Component into the Parent template, and use dependency injection to call Child Component's sharedVar.

// Parent Component @Component({     selector: 'parent',     template: `         <h1>{{sharedVar}}</h1>         <child></child>     `,     directives: [ChildComponent],     providers: [ChildCompnent] }) export class ParentComponent {     sharedVar: string;     constructor(child: ChildComponent) {         this.sharedVar = child.sharedVar;     } } 

The problem is as I'm typing in the input box, the value in <p> changes automatically while the value in parent component's <h1> do not change.

like image 561
movila Avatar asked Feb 10 '16 23:02

movila


2 Answers

We can use the [(x)] syntax in the parent template to achieve two-way databinding with the child. If we create an Output property with the name xChange, Angular will automatically update the parent property. We do need to emit() an event whenever the child changes the value however:

import {Component, EventEmitter, Input, Output} from 'angular2/core'  @Component({     selector: 'child',     template: `         <p>Child sharedVar: {{sharedVar}}</p>         <input [ngModel]="sharedVar" (ngModelChange)="change($event)">     ` }) export class ChildComponent {     @Input() sharedVar: string;     @Output() sharedVarChange = new EventEmitter();     change(newValue) {       console.log('newvalue', newValue)       this.sharedVar = newValue;       this.sharedVarChange.emit(newValue);     } }  @Component({     selector: 'parent',     template: `         <div>Parent sharedVarParent: {{sharedVarParent}}</div>         <child [(sharedVar)]="sharedVarParent"></child>     `,     directives: [ChildComponent] }) export class ParentComponent {     sharedVarParent ='hello';     constructor() { console.clear(); } } 

Plunker

I used sharedVarParent in the ParentComponent just to demonstrate that the names don't have to be the same in the parent and child.

like image 198
Mark Rajcok Avatar answered Sep 30 '22 21:09

Mark Rajcok


You could set up event emitter communication (outputs) from child to parent. For example like this:

@Component({     selector: 'child',     template: `         <p>Child: {{sharedVar}}</p>         <input [(ngModel)]="sharedVar" (ngModelChange)="change()">     ` }) export class ChildComponent {     @Output() onChange = new EventEmitter();     sharedVar: string;     change() {         this.onChange.emit({value: this.sharedVar});     } } 

and the in parent component:

@Component({     selector: 'parent',     template: `         <h1>{{sharedVar}}</h1>         <child (onChange)="sharedVar = $event.value"></child>     `,     directives: [ChildComponent] }) export class ParentComponent {     sharedVar: string;     constructor() {      } } 

Demo: http://plnkr.co/edit/T2KH4nGKPSy6GEvbF1Nb?p=info

like image 33
dfsq Avatar answered Sep 30 '22 21:09

dfsq