Angular Components: Pass by Reference or Pass by Value?

Dhananjay Kumar / Tuesday, August 14, 2018

In Angular, you can pass data from parent component to child component using @Input() decorator, and a child component can emit an event to a parent comment using @Output() decorator.

You can learn more about @Input() decorator here and about @Output decorator here.

The purpose of this blog post is to explain you whether it is pass by reference or pass by value in context of @Input() and @Output decorator.

To start with, let us assume that we have two components, as listed below:

import { Component, Input } from '@angular/core';
@Component({
    selector: 'app-video',
    template: `
        {{data.counter}} {{count}}
     `
})
export class VideoComponent {
 
    @Input() data: any;
    @Input() count: number;
 
}

As you see, we have two input properties.

  1. In data property, we will pass an object.
  2. In count property, we will pass a number.

 

 From the AppComponent, we are passing value for both properties, as shown below:

import { Component, OnInit } from '@angular/core';
 
@Component({
    selector: 'app-root',
    template: `
  <app-video [data]='data' [count]='count' ></app-video>
  `
})
export class AppComponent implements OnInit {
    data: any = {};
    count: number;
    constructor() {
    }
 
    ngOnInit() {
        this.data.counter = 1;
        this.count = 1;
    }
}

As you see,  we are passing data (object) and count( number) to the child component. Since data is being passed as object,  it will be “Pass by Reference” and, since count is passed as number,  it will be “Pass by Value”.

Therefore, if passing an object, array, or the like,  then it is Pass by Reference, and for primitive types like number, it is Pass by Value. 

To better understand it, let us raise two events on the child component, as shown in the listing below:

import { Component, Input, EventEmitter, Output } from '@angular/core';
@Component({
    selector: 'app-video',
    template: `
        {{data.counter}} {{count}}
        <button (click)='senddata()'>send data</button>
        <button (click)='sendcount()'>send count</button>
     `
})
export class VideoComponent {
 
    @Input() data: any;
    @Input() count: number;
 
    @Output() dataEvent = new EventEmitter();
    @Output() countEvent = new EventEmitter();
 
    senddata() {
        this.dataEvent.emit(this.data);
 
    }
    sendcount() {
        this.countEvent.emit(this.count);
    }
 
}

In both events, we are passing back same @Input() decorated properties to the parent component.  In dataEvent, data is passed back and, in countEvent, count is passed back to the parent component.  

In the parent component, we are capturing event as below:

import { Component, OnInit } from '@angular/core';
 
@Component({
    selector: 'app-root',
    template: `
  <app-video [data]='data' [count]='count' (dataEvent)='updateData($event)' (countEvent)='updateCount($event)' ></app-video>
  `
})
export class AppComponent implements OnInit {
    data: any = {};
    count: number;
    constructor() {
    }
 
    ngOnInit() {
        this.data.counter = 1;
        this.count = 1;
    }
 
    updateData(d) {
        d.counter = d.counter + 1;
        console.log(this.data.counter);
    }
 
    updateCount(c) {
        c = c + 1;
        console.log(this.count);
    }
}

Let us talk through updateData and updateCount function. These functions are capturing events raised on the child component.

In the updateData function, we are incrementing value of passed parameter, however, since it is an object, it will update value of this.data and in the child component, the updated value will be rendered.

In the updateCount function, we are incrementing value of passed parameter, however, since it is primitive type it will not update this.count and in the child component, no impact will happen.

As output on clicking of button, you will find value of data is incrementing but value of count is not incrementing.

We can summarize that if we pass objects in @Input() decorator then it would be passed as reference, and if we pass primitive types, then it would be passed as value. I hope you find this article useful. Thanks for reading.

 If you like this post, please share it. Also, if you have not checked out Infragistics Ignite UI for Angular Components, be sure to do so! They have 30+ material based Angular components to help you code web apps faster.