Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular 2 @Input: Is it possible to pass data from a component to another child route component?

Based on the docs of Angular 2 you can pass data from a component to another quite easily with the @Input.

So for example I can set the parent like this:

import { Component } from '@angular/core';
import { HEROES } from './hero';
@Component({
  selector: 'hero-parent',
  template: `
    <h2>{{master}} controls {{heroes.length}} heroes</h2>
    <hero-child *ngFor="let hero of heroes"
      [hero]="hero"
      [master]="master">
    </hero-child>
  `
})
export class HeroParentComponent {
  heroes = HEROES;
  master: string = 'Master';
}

And the get the data in the child component like this:

import { Component, Input } from '@angular/core';
import { Hero } from './hero';
@Component({
  selector: 'hero-child',
  template: `
    <h3>{{hero.name}} says:</h3>
    <p>I, {{hero.name}}, am at your service, {{masterName}}.</p>
  `
})
export class HeroChildComponent {
  @Input() hero: Hero;
  @Input('master') masterName: string;
}

So it's quite obvious, pass the [hero]="data" to the template of the parent component (of course in the child selector) and handle them into the child component.

But here's the issue.

My child component DOM element (in this case <hero-child>) is not available in the parent's template but instead it is loaded there in a <router-outlet> element.

How can I pass data then to a child route component then? Isn't the input the correct way? I want to avoid double,treble etc calls to get the same data that already have in my parent route/component.

like image 390
Vassilis Pits Avatar asked Aug 31 '16 14:08

Vassilis Pits


People also ask

How to pass data from parent component to child component in angular?

By using this decorator, we can pass data from the Parent component to the Child component. Angular provides the Decorator, @Output (). By using this decorator, we can pass data from the child component to the parent component.

How to pass data in angular route component?

How to pass data in angular route component 1 Navigation within the application. ... 2 Using a state object of navigate () the method of Angular router object to pass data between components: Angular allows different ways of passing data between components. ... 3 Reading state object data in navigate () method. ... 4 Using Route params. ...

How to pass data from the parent component to the child component?

When we want to pass the data from the parent component to the child component, we use input binding with @Input decorations. Let's consider an example where PersonChildComponent has two input properties with @Input decorations.

How to share data between two components in angular?

In angular, we are able to pass different ways to share data between the components. Small components are always good to manage code in Angular. We have to define the relationship between the components. Please follow the below steps. When you define @Input () in the child component it will receive value from the parent component.


1 Answers

I don't believe there is any way to pass objects as an input to a component that is routed to. I've accomplished this by using a service with an observable to share the data between a parent and one or many child components.

Basically the parent component calls the service and pushes whatever data it needs to it. In my case it is just an ID, but it could be anything. The Service then can do something with that data (or not). In my example I'm making a call to the server to get a company based on the ID but if you already have the object you need this isn't needed. Then it pushes an object into an Observable stream which is subscribed to in the child component.

Parent Component:

import { Component, OnInit, OnDestroy } from '@angular/core';
import { ActivatedRoute, Params } from '@angular/router';
import { SalesProcessService } from './salesProcess.service';
import { Subscription } from 'rxjs/Rx';

@Component({
    selector: 'ex-sales-process',
    template: `
        <router-outlet></router-outlet>
    `
})
export class SalesProcessComponent implements OnInit, OnDestroy {
    private companyRowId: string;
    private paramsSubscription: Subscription;
    constructor(
        private salesProcessService: SalesProcessService,
        private route: ActivatedRoute
    ) {}
    ngOnInit() {
        this.paramsSubscription = this.route.params.subscribe((params: Params) => {
            if (this.companyRowId !== params['companyId']) {
                this.companyRowId = params['companyId'];
                this.salesProcessService.getCompany(this.companyRowId);
            }
        });
    }
    ngOnDestroy() {
        this.paramsSubscription.unsubscribe();
    }

}

Service:

import { Injectable } from '@angular/core';
import { CompanyDataService } from '../common/services/data';
import { ReplaySubject } from 'rxjs';
import { Observable, Subject, Subscription } from 'rxjs/Rx';

@Injectable()
export class SalesProcessService {
    private companyLoadedSource = new ReplaySubject<any>(1);
    /* tslint:disable:member-ordering */
    companyLoaded$ = this.companyLoadedSource.asObservable();
    /* tslint:enable:member-ordering */

    constructor (
        private companyDataService: CompanyDataService) { }
    getCompany(companyRowId: string) {
      // Data service that makes http call and returns Observable
        this.companyDataService.getCompany(companyRowId).subscribe(company => this.companyLoadedSource.next(company));
    }

}

Child Component

import { Component, OnInit, OnDestroy } from '@angular/core';
import { SalesProcessService } from '../salesProcess.service';
import { Subscription } from 'rxjs/Rx';

@Component({
    selector: 'ex-company',
    template: require('./company.component.html'),
    styles: [require('./company.component.css')]
})
export class CompanyComponent implements OnInit, OnDestroy {
    company: any;
    private companySub: Subscription;
    constructor(
        private salesProcessService: SalesProcessService
        ) { }
    ngOnInit() {
        this.companySub = this.salesProcessService.companyLoaded$.subscribe(company => {
            this.company = company;
        });
    }
    ngOnDestroy() {
        this.companySub.unsubscribe();
    }
}
like image 110
dmungin Avatar answered Oct 26 '22 03:10

dmungin