cyberbeast
cyberbeast

Reputation: 698

Data communication between parent and grand-child components (separated by a router outlet) in angular2?

[SOLVED] - @günter-zöchbauer

I am new to Angular2 and TypeScript. I am trying to establish communication between a parent and a grand-child node. The hierarchy in my app is as follows

I want to establish communication between child1 and parent. I have created a data service (debug.service.ts) in the following manner:-

import { Injectable } from '@angular/core';
import { Subject } from 'rxjs/Subject';
import { AngularFire, FirebaseListObservable } from 'angularfire2';


@Injectable()
export class DebugService {
    // Observable sources
    private _projectListSource = new Subject<FirebaseListObservable<any[]>>();

    // Observable streams
    projectListRetreived$ = this._projectListSource.asObservable();

    // Service message commands
    announceProjectsList(projects: any) {
        this._projectListSource.next(projects);
        console.log("Received   " + projects);
    }

}

The child component updates data in the following manner:-

import { Component, ... } from '@angular/core';
import { DebugService } from './debug.service';
. . .

@Component({
  selector: 'my-projects',
  templateUrl: 'projects.component.html',
  styleUrls: ['projects.component.css'],
  directives: [
    ProjectDetailComponent,
    . . .
  ],
  providers: [
    DebugService,
    . . .
  ]
})

export class ProjectsComponent implements OnInit {
  projects: Observable<any[]>; 
  . . .

  // constructor
  constructor(
    private router: Router,
    . . .
    private debugService: DebugService) {

  }

  // gotoDashboardView method. CALLED at the click event of the dashboard floating action button on the template.
  gotoDashboardView() {
    this.router.navigate(['']);
  }

  // Supporting method for the ngOnInit() operation. CALLED by ngOnInit.
  getProjects() {
    this.projects = this.projectService.getProjects();
    this.debugService.announceProjectsList(this.projectService.getProjects());

  }

  // ngOnInit() method triggered at the initialization lifecycle hook. PROVIDED by angular2.
  ngOnInit() {
    this.getProjects();
  }

  deleteProject(key: string) {
    this.projectService.deleteProject(key);
  }
}

My parent component which contains the router outlet element in its template is as follows:-

import { Component, ... } from '@angular/core';
.
.
.
import { DebugService } from './debug.service';
import { Observable, Subscription } from 'rxjs';

@Component({
    moduleId: module.id,
    selector: 'app-root',
    templateUrl: 'app.component.html',
    styleUrls: [
        'app.component.css'],
    directives: [
        ProjectsComponent,
        ROUTER_DIRECTIVES,
        . . .
    ],
    providers: [
        DebugService,
        . . .
    ]
})

export class AppComponent implements OnDestroy, OnInit{
    projectObject: Observable<any[]>;
    subscription: Subscription;

    constructor(
        public af: AngularFire,
        private debugService: DebugService){ }

    clicky(){
        console.log(this.projectObject);
    }

    ngOnDestroy() {
        // prevent memory leak when component destroyed
        this.subscription.unsubscribe();
    }

    ngOnInit() {
        this.debugService.projectListRetreived$.subscribe(
            res => {
                this.projectObject = res;
            }
        );        
    }

}

As far as I can observe, the DebugService is receiving data, but for some reason the parent component is not being able to subscribe to it. Any ideas/suggestions as to how I can get router-outlet components to communicate with the parent component?

Upvotes: 3

Views: 566

Answers (1)

G&#252;nter Z&#246;chbauer
G&#252;nter Z&#246;chbauer

Reputation: 658067

Provide DebugService only once at a common parent (can be the ancestor component if the components you want to communicate with are in a ancestor/descendant relationship).

A new instance is created fro each provide. If you provide on every component, every component will get its own service instance. If you provide only once, this component and all descendants will get the same instance.

Upvotes: 4

Related Questions