2
votes

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?.

1
Does it work if you use new BehaviorSubject<MyObject>(); instead of new Subject<MyObject>();?Günter Zöchbauer
I assume you don't provide ObjectTransferService in ChildComponent, right?Günter Zöchbauer
@GünterZöchbauer Correct, the child does not provide ObjecTransferService.Rex
@GünterZöchbauer and Yes! It works with new BehaviorSubject<MyObject>(); :) thank you.Rex

1 Answers

3
votes

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.