Angular2: how to chain ngModel with two-way bound variable of other component?

Issue

I have a main-component which passes a variable to another component sub-component via custom two-way binding. The passed variable is used for an input tag via ngModel.

These two variables are currently not in sync. How can I chain those two variables?

main.component.ts

import { Component, OnInit } from '@angular/core';

@Component({
  selector: 'app-main-component',
  templateUrl: './main-component.component.html',
  styleUrls: ['./main-component.component.css']
})
export class MainComponentComponent implements OnInit {

  private you: any = {};

  constructor() { }

  ngOnInit() {
    this.you.name = "Name";
  }
}

main.component.html

<div>
  This is the main component.
  you.name = {{you.name}}
  <br>
  <app-sub-component [(variable)]="you.name"></app-sub-component>
</div>

sub.component.ts

import { Component, OnInit, OnChanges, Input, Output, EventEmitter, SimpleChanges } from '@angular/core';

@Component({
  selector: 'app-sub-component',
  templateUrl: './sub-component.component.html',
  styleUrls: ['./sub-component.component.css']
})
export class SubComponentComponent implements OnInit, OnChanges {

  constructor() { }

  @Input() variable: any;

  @Output() variableChange: EventEmitter<any> = new EventEmitter<any>();

  ngOnInit() {
  }

  ngOnChanges(changes: SimpleChanges) {
    console.log(changes);
  }
}

sub.component.html

<input type="text" [(ngModel)]="variable">

Variable = {{variable}}

Given above configuration,
I want the variable you.name in the main component and the variable variable in the sub-component to be in sync.

How can this be achieved?

Solution

You should use onModelChange() on the child. Here is an example:

DEMO

child:

  @Input() name;
  @Input() surname;
  @Input() age;

  @Output() nameChange = new EventEmitter();
  @Output() surnameChange = new EventEmitter();
  @Output() ageChange = new EventEmitter();


  onModelChange(event, type) { 
    this[`${type}Change`].emit(event); //this line was optimised by yurzui
  }

parent:

@Component({
  selector: 'my-app',
  template: `
      <child [(name)]="name" [(surname)]="surname" [(age)]="age"></child>
      <br><br>
      Name :{{name}} 
      <br>
      Surname: {{surname}} 
      <br>
      Age: {{age}} 
      <br>
      <button (click)="reset()">Reset</button>
  `,
})
export class AppComponent implements OnInit{
  name:string;
  surname:string;
  age:number;


  reset(){
    this.name = "";
    this.surname = "";
    this.age = 18;
  } 

  ngOnInit(){
    this.reset();
  }

}

Answered By – Vega

Answer Checked By – Clifford M. (AngularFixing Volunteer)

Leave a Reply

Your email address will not be published.