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.

Angular4: Pass data from parent to child component (part 5)

Set  up an ng project,

$ ng new angularcomponentpassing

Create a new component,

$ ng g c cockpit

File: cockpit.component.ts

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

@Component({
selector: 'app-cockpit',
templateUrl: './cockpit.component.html',
styleUrls: ['./cockpit.component.css']
})
export class CockpitComponent implements OnInit {
@Input('srvElement') element: {name: string, id: number;}
constructor() { }

ngOnInit() {
}
}

Note: ‘srvElement’ is an alias for ‘element’ and can be left out above like this,

@Input() element: {name: string, id: number;}
constructor() { }

File: cockpit.component.html

<hr>
<p>
cockpit works!
</p>
<p><strong>Name:</strong> {{ element.name }}, <strong>id:</strong> {{ element.id }}</p>

File: app.component.ts

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

@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})

export class AppComponent {
title = 'app works!';
serverElements = [{name: 'John', id: 8}, {name: 'Matt', id: 10}];
}

File: app.component.html

<h1>
{{title}}
</h1>
<app-cockpit *ngFor="let serverElement of serverElements" [srvElement]="serverElement">hello</app-cockpit>

If the alias for ‘element’, which is ‘srvElement’ is not used then the above line should be,

<app-cockpit *ngFor="let serverElement of serverElements" [element]="serverElement">hello</app-cockpit>

Angular 4: Data Binding Two-Way-Binding

Initially the button is disabled until a username is input, after which time it is possible to reset the username by clicking the button.


In app.component.ts he simply declare two variables and set ‘username’ to an empty string. The function clears the string and resets the username.

export class AppComponent {
username: string = '';
allowButton: boolean = false;
onUsernameReset(){
this.username = '';
}
}

In app.component.html we use [(ngModel)] for two-way-databinding. This uses both square and round brackets. The input is set to ‘username’ and because of the two-way-binding this is available everywhere, e.g. for string interploation on the next line using {{ username }} and for property binding [disabled]=”!username”

<div class="container">
  <div class="row">
    <div class="col-md-4">
     <label for="box">Username:</label>
     <input name="box" type="text" class="form-control" [(ngModel)]="username"/>
     <p> {{ username }} </p>
     <button class="btn btn-primary" [disabled]="!username" (click)="onUsernameReset()">Reset username</button>
    </div>
  </div>
</div>

The ‘click’ event is put in round brackets and it calls the function onUsernameReset() which can be found in app.component.ts

Angular 4: Data Binding Event Binding

When an event occurs i.e. clicking a button we want a function onButton() to be called.

In app.component.ts we have the function onButton() which simply logs a few words to the console,

export class AppComponent {
onButton(){
   console.log("You pressed it, well done!")
   }
}

In app.component.html the event, in this case ‘click’, is in round brackets,

<button class="btn btn-primary" (click)="onButton()">Button</button>