2017-01-23 3 views
1

Я пытаюсь сделать это https://angular.io/docs/ts/latest/cookbook/component-communication.html#!#bidirectional-serviceкомпонент взаимодействия через сервис Угловое 2

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> 

И объявить "providers: [InteractionService]" в app.module.ts.

Но в sidebar.component.ts У меня есть ошибка «Не удается прочитать свойство„режим“неопределенной».

Что делать неправильно? Как я могу это разрешить?

ответ

1

Нельзя предположить, что значение будет доступно при вызове ngOnInit().

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 { 
        //... 
       } 
      }); 
    } 
} 

Это только с уверенностью предположить, что значение доступно, когда обратного вызова передается subscribe(...) называется. Если вы получите значение из запроса на сервер, это может быть довольно долго после того, как был вызван и завершен конструктор или ngOnInit (или любой другой обратный вызов жизненного цикла).

+0

Что бы вы мне предложили? Сделайте тот же второй ajax-запрос в sidebar.component.ts, что и в app.component.ts? Я просто хочу уменьшить количество аякс-запросов в моем приложении. –

+0

Что-то вроде http://stackoverflow.com/questions/36271899/what-is-the-correct-way-to-share-the-result-of-an-angular-2-http-network-call-in/36291681 # 36291681 –

0

Есть несколько вещей, которые вы можете попробовать сделать:
interaction.service.ts:

  • попробовать использовать BehaviorSubject как private optionsSource = new BehaviorSubject<Options>(null);.

Надеемся, что над одной строкой приложение будет работать без каких-либо изменений. Но мы можем сделать лучше.

app.component.ts:

  • попробуйте переместить подписку на interaction.service.ts «s конструктора.

Затем, вы не будете иметь никакого взаимодействия с interaction.service.ts в app.component, который не то, что вы делаете - общение через сервис. Не волнуйся.

sidebar.component.ц

  • пытаются переместить подписку от constructor к ngOnInit.

Вот plnk с вышеуказанными изменениями для вашей справки.

Смежные вопросы