3

I am trying to have a service pass, from a parent component, an object to a child component via a <router-outlet></router-outlet>. I used the docs to guide me https://angular.io/docs/ts/latest/cookbook/component-communication.html#!#bidirectional-service, however when I try to run the app, I receive no error or output.

the service's code:

import {Injectable} from '@angular/core';
import {Subject} from 'rxjs';
import {MyObject} from '../models/my-object.model';

@Injectable()
export class ObjectTransferService {
    private myObjectSource = new Subject<MyObject>();
    objectSource$ = this.myObjectSource.asObservable();

    sendMyObject(myObject: MyObject) {
        this.myObjectSource.next(myObject);
    }
 }

The parent component:

import {Component} from '@angular/component';
import {MyObject} from '../models/my-object.model';
import {ObjectTransferService} from '../service/object-transfer.service';

@Component({
    template: `
    <router-outlet></router-outlet>
    `,
    providers: [ObjectTransferService]
})
export class ParentComponent implements OnInit {
    public myObject: MyObject = <MyObject>{ foo: 'bar' };
    constructor(private objectTransferService: ObjectTransferService){}

    public ngOnInit(): void {
        this.objectTransferService.sendMyObject(myObject);
    }
}

the child Component that comes through the <router-outlet></router-outlet>:

import {Component} from '@angular/component';
import {MyObject} from '../models/my-object.model';
import {ObjectTransferService} from '../service/object-transfer.service';

@Component({
  ...
})
export class ChildComponent {

    constructor(private objectTransferService: ObjectTransferService){
         objectTransferService.objectSource$.subscribe(
         res => console.log('details', res),
         err => console.log('err' ,err));.
    }
}

Update (Answered)

Changed new Subject<MyObject>() to new BehaviorSubject<MyObject>(<MyObject>{})

I believe that the reason this was not receiving a response was that the Subject was not being updated with a new value after I had subscribed to it. Using BehaviorSubject allows the observer to be updated with the most recent value, as explained here, Angular 2 - Behavior Subject vs Observable?.

Community
  • 1
  • 1
Rex
  • 376
  • 2
  • 11

1 Answers1

3

There is a timing problem. The event in ngOnInit() of ParentComponent is emitted before the constructor of ChildComponent is executed, therefore the subscription happens too late.

BehaviorSubject remembers the last event and and passes it to new subscribers, therefore ChildComponent receives an event as soon as the subscription is set up. Alternatively ReplaySubject can be used. ReplaySubject doesn't require an initial value.

Günter Zöchbauer
  • 623,577
  • 216
  • 2,003
  • 1,567