[angular] How to pass object from one component to another in Angular 2?

I have Angular components and first component uses the second one as a directive. They should share the same model object, which is initialized in the first component. How can I pass that model to the second component?

This question is related to angular angular2-directives

The answer is


Use the output annotation

@Directive({
  selector: 'interval-dir',
})
class IntervalDir {
  @Output() everySecond = new EventEmitter();
  @Output('everyFiveSeconds') five5Secs = new EventEmitter();
  constructor() {
    setInterval(() => this.everySecond.emit("event"), 1000);
    setInterval(() => this.five5Secs.emit("event"), 5000);
  }
}
@Component({
  selector: 'app',
  template: `
    <interval-dir (everySecond)="everySecond()" (everyFiveSeconds)="everyFiveSeconds()">
    </interval-dir>
  `,
  directives: [IntervalDir]
})
class App {
  everySecond() { console.log('second'); }
  everyFiveSeconds() { console.log('five seconds'); }
}
bootstrap(App);

For one-way data binding from parent to child, use the @Input decorator (as recommended by the style guide) to specify an input property on the child component

@Input() model: any;   // instead of any, specify your type

and use template property binding in the parent template

<child [model]="parentModel"></child>

Since you are passing an object (a JavaScript reference type) any changes you make to object properties in the parent or the child component will be reflected in the other component, since both components have a reference to the same object. I show this in the Plunker.

If you reassign the object in the parent component

this.model = someNewModel;

Angular will propagate the new object reference to the child component (automatically, as part of change detection).

The only thing you shouldn't do is reassign the object in the child component. If you do this, the parent will still reference the original object. (If you do need two-way data binding, see https://stackoverflow.com/a/34616530/215945).

@Component({
  selector: 'child',
  template: `<h3>child</h3> 
    <div>{{model.prop1}}</div>
    <button (click)="updateModel()">update model</button>`
})
class Child {
  @Input() model: any;   // instead of any, specify your type
  updateModel() {
    this.model.prop1 += ' child';
  }
}

@Component({
  selector: 'my-app',
  directives: [Child],
  template: `
    <h3>Parent</h3>
    <div>{{parentModel.prop1}}</div>
    <button (click)="updateModel()">update model</button>
    <child [model]="parentModel"></child>`
})
export class AppComponent {
  parentModel = { prop1: '1st prop', prop2: '2nd prop' };
  constructor() {}
  updateModel() { this.parentModel.prop1 += ' parent'; }
}

Plunker - Angular RC.2


you could also store your data in an service with an setter and get it over a getter

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

@Injectable()
export class StorageService {

    public scope: Array<any> | boolean = false;

    constructor() {
    }

    public getScope(): Array<any> | boolean {
        return this.scope;
    }

    public setScope(scope: any): void {
        this.scope = scope;
    }
}

From component

_x000D_
_x000D_
import { Component, OnInit, ViewChild} from '@angular/core';_x000D_
    import { HttpClient } from '@angular/common/http';_x000D_
    import { dataService } from "src/app/service/data.service";_x000D_
    @Component( {_x000D_
        selector: 'app-sideWidget',_x000D_
        templateUrl: './sideWidget.html',_x000D_
        styleUrls: ['./linked-widget.component.css']_x000D_
    } )_x000D_
    export class sideWidget{_x000D_
    TableColumnNames: object[];_x000D_
    SelectedtableName: string = "patient";_x000D_
    constructor( private LWTableColumnNames: dataService ) { _x000D_
       _x000D_
    }_x000D_
    _x000D_
    ngOnInit() {_x000D_
        this.http.post( 'getColumns', this.SelectedtableName )_x000D_
            .subscribe(_x000D_
            ( data: object[] ) => {_x000D_
                this.TableColumnNames = data;_x000D_
     this.LWTableColumnNames.refLWTableColumnNames = this.TableColumnNames; //this line of code will pass the value through data service_x000D_
            } );_x000D_
    _x000D_
    }    _x000D_
    }
_x000D_
_x000D_
_x000D_

DataService

_x000D_
_x000D_
import { Injectable } from '@angular/core';_x000D_
import { BehaviorSubject, Observable } from 'rxjs';_x000D_
_x000D_
@Injectable()_x000D_
export class dataService {_x000D_
    refLWTableColumnNames: object;//creating an object for the data_x000D_
}
_x000D_
_x000D_
_x000D_

To Component

_x000D_
_x000D_
import { Component, OnInit } from '@angular/core';_x000D_
import { dataService } from "src/app/service/data.service";_x000D_
_x000D_
@Component( {_x000D_
    selector: 'app-linked-widget',_x000D_
    templateUrl: './linked-widget.component.html',_x000D_
    styleUrls: ['./linked-widget.component.css']_x000D_
} )_x000D_
export class LinkedWidgetComponent implements OnInit {_x000D_
_x000D_
    constructor(private LWTableColumnNames: dataService) { }_x000D_
_x000D_
    ngOnInit() {_x000D_
    console.log(this.LWTableColumnNames.refLWTableColumnNames);_x000D_
    }_x000D_
    createTable(){_x000D_
        console.log(this.LWTableColumnNames.refLWTableColumnNames);// calling the object from another component_x000D_
    }_x000D_
_x000D_
}
_x000D_
_x000D_
_x000D_