1

I'm trying to do this https://angular.io/docs/ts/latest/cookbook/component-communication.html#!#bidirectional-service

interaction.service.ts:

import { Injectable } from '@angular/core';
import { Subject } from 'rxjs/Subject';    
import { Options } from './options';

@Injectable()
export class InteractionService {
    private optionsSource = new Subject<Options>();

    options$ = this.optionsSource.asObservable();

    setOptions(options: Options) {
        this.optionsSource.next(options);
    }
}

app.component.ts:

import { Component, OnInit } from '@angular/core';
import { CoreService } from './core/core.service';
import { InteractionService } from './providers/interaction.service';
import { Options } from './options';

@Component({
    selector: 'app',
    templateUrl: './app/app.component.html'
})
export class AppComponent implements OnInit {
    constructor(private coreService: CoreService,
        private interactionService: InteractionService) { }

    ngOnInit() {
          this.coreService.getOptions().subscribe((options: Options) => { 
              this.interactionService.setOptions(options);
            });
        }
    }

sidebar.component.ts:

import { Component, OnInit} from '@angular/core';
import { InteractionService } from './../../providers/interaction.service';
import { Options } from './options';

@Component({
    selector: 'app-sidebar',
    templateUrl: './app/core/sidebar/sidebar.component.html'
})
export class SidebarComponent implements OnInit {
    options: Options;

    constructor(private interactionService: InteractionService) {
        this.interactionService.options$.subscribe(
            (options: options) => {
                this.options = options;
            });
    }

    ngOnInit() {
        if (this.options.mode === "test") {
            //...
        } else {
            //...
        }
    }
}

app.component.html:

<app-sidebar></app-sidebar>
<router-outlet></router-outlet>

And declare "providers: [InteractionService]" in app.module.ts.

But in sidebar.component.ts I have error "Cannot read property 'mode' of undefined".

What do I do wrong? How can I resolve that?

A. Gladkiy
  • 3,134
  • 5
  • 38
  • 82

2 Answers2

1

It's not safe to assume that the value will be available when ngOnInit() is called.

export class SidebarComponent implements OnInit {
    options: Options;

    constructor(private interactionService: InteractionService) {
        this.interactionService.options$.subscribe(
            (options: options) => {
                this.options = options;
                if (this.options.mode === "test") {
                  //...
                } else {
                  //...
                }
            });
    }
}

It's only safe to assume that the value is available when the callback passed to subscribe(...) is called. If you get the value from a request to the server this can be quite long after the constructor or ngOnInit (or any other lifecycle callback) was called and completed.

Günter Zöchbauer
  • 623,577
  • 216
  • 2,003
  • 1,567
  • What would you suggest me? Do the same second ajax-request in sidebar.component.ts as in app.component.ts? I just want to reduce count of ajax-requests in my app. – A. Gladkiy Jan 23 '17 at 08:04
  • Something like http://stackoverflow.com/questions/36271899/what-is-the-correct-way-to-share-the-result-of-an-angular-2-http-network-call-in/36291681#36291681 – Günter Zöchbauer Jan 23 '17 at 08:09
0

There are several things you may try to do:
interaction.service.ts:

  • try use BehaviorSubject like private optionsSource = new BehaviorSubject<Options>(null);.

Hopefully, above one line will make your app running without other changes. But we can do better.

app.component.ts:

  • try move the subscription to interaction.service.ts's constructor.

Then, you will have no interaction with interaction.service.ts in app.component, which is not what you are doing -- communication via service. Don't worry.

sidebar.component.ts

  • try move the subscription from constructor to ngOnInit.

Here is a plnk with above modifications for your reference.

Timathon
  • 1,049
  • 9
  • 11