Angular 4: Pass data parent to child component (part 1 of 2)

The full code for part 1 & 2 here and demo on gh-pages here.

This post explains how to pass data from a parent component directly into a child component without iteration using ngFor as we did in the other post on this same issue here.

With angular-cli previously installed, create a new project,

$ ng new angulardataparenttochild

Then change directory into that newly created directory,

$ cd angulardataparenttochild

Next create a child component,

$ ng g c child

In your editor place a tag <app-child$gt;$lt;app-child/$gt; in app.component.html to put the child component inside the parent component. Also add some bootstrap to make it nice! app.component.html should look like this,

<div class="container" style="border: 3px solid #515B89; background-color: #79809E; border-radius: 15px;">
  <div class="row">
    <div class="col-xs-12">
      <h1>
        {{title}}
      </h1>
    </div>
  </div>
  <div class="row">
    <div class="col--xs-12">
      <app-child></app-child>
    </div>
  </div>
</div>

Likewise the child.component.html file is

<div class="container" style="border: 3px solid #458075; background-color: #6D948C; border-radius: 15px;">
  <div class="row">
    <div class="col-xs-12">
      <p>
        child works!
      </p>
    </div>
  </div>
</div>

Let’s check this works with

$ ng serve

Navigate in your browser to localhost:4200

First be sure to import ‘Input’ into the top of the child component’s ts file child.component.ts,

import { Component, ElementRef, NgZone, OnDestroy, OnInit, Input } from '@angular/core';

Then just inside the child component’s class, in child.component.ts, use the input decorator to setup the data structure of the data being input to this child component,

@Input() quantity: number = null;

Add an input form to the root app, app.component.html

<input type="number" class="form-control" [(ngModel)]="value" (ngModelChange)="fun()"/>

Here we are using [(ngModel)] and setting any input to “value”. (ngModelChange)=”fun()” will call a function fun() whenever there is a change in the input form.

The full app.component.html file should look like this,

<div class="container" style="border: 3px solid #515B89; background-color: #79809E; border-radius: 15px;">
  <div class="row">
    <div class="col-xs-12">
      <h1>
        {{title}}
      </h1>
      <label for="box">Value:</label>
      <input type="number" class="form-control" [(ngModel)]="value" (ngModelChange)="fun()" />
      <p>value = {{ value }}</p>
      <p>newvalue = value + 2 = {{ newvalue }}</p>
    </div>
  </div>
  <div class="row">
    <div class="col--xs-12">
      <app-child [quantity]="newvalue"></app-child>
    </div>
  </div>
</div>

In app.component.ts just inside the “export class AppComponent(” we will define value and also in this class we will create the fun() function which increase “value” by 2, just to do something with it! We also set this then equal to “newvalue” and define that as we did with “value”.

So app.component.ts should look like this,

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

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  title = 'root app';
  value: number = null;
  newvalue: number = null;

  constructor(){
  }

  ngOnInit(){
  }

  fun(){
    this.newvalue = this.value + 2;
  }
}

We will display the values “value” and “newvalue” in app.component.html using interpolation which is just a fancy word for the double curly brackets {{ newvalue }},

<p>value = {{ value }}</p>
<p>newvalue = value + 2 = {{ newvalue }}</p>

Also in the file we will include child component using it’s selector which is app-child, like this,

<app-child></app-child>

But this where we pass the parent component value “newvalue” to the child value “quantity”.

<app-child [quantity]="newvalue"></app-child>

But we don’t want to pass it to the child.component.html just yet. We will like to get it into the child.componet.ts file first and do soemthing with it. We will again just increase it’s value by 2. This is done using the ngOnChanges() function.

But do use this you must import ‘OnChanges’ at the tope of child.component.ts,

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

Also you need to implement it with the class like this,

export class ChildComponent implements OnInit, OnChanges {...

Increasing the this.quantity value by 2 in ngOnChanges() is done like this,

  ngOnChanges(){
      this.quantity = this.quantity + 2;
  }

The function ngOnChanges() runs anytime the quantity value changes. In other words when there is an change to “newvalue” in the parent component. This is very useful!

Next we display that value in child.component.html using the {{quantity}}.

The child.component.html file,

<div class="container" style="border: 3px solid #458075; background-color: #6D948C; border-radius: 15px;">
  <div class="row">
    <div class="col-xs-12">
      <h3>child app</h3>
      <p>
        value + 4 = newvalue + 2 = quantity = <span *ngIf="quantity">{{quantity}}</span>
      </p>
    </div>
  </div>
</div>

However I found this always displayed the ‘quantity’ value as 2, even before anything was input.

As a result I put an if(quantity){…} around this line. So child.component.ts looks like this,

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

@Component({
  selector: 'app-child',
  templateUrl: './child.component.html',
  styleUrls: ['./child.component.css']
})
export class ChildComponent implements OnInit, OnChanges {
@Input() quantity: number = null;

  constructor() {
  }

  ngOnInit() {
  }

  ngOnChanges(){
    if(this.quantity){
      this.quantity = this.quantity + 2;
    }
  }
}

The full code for part 1 & 2 here and demo on gh-pages here.