-1

相关问题:

Observable 没有收到 angular2 中的下一个值

angular2中没有服务错误的提供者,为什么我需要将它注入它的父组件?

在 angular2 中使用与其他组件的可观察对话,没有收到即将到来的价值

我有一个具有 setCurrentPlaylists 函数的 PagesService,该函数将从其他组件触发,它将接收 Playlists 类型的值,并将控制台记录该值,使用下一个函数传递给其他组件(我打算这样做)。

我的页面服务的整个代码是:

import { Injectable } from '@angular/core';

import { ApiService } from '../../apiService/api.service';
import { Platform } from '../../platforms/shared/platform.model';
import { Page } from './page.model';
import { Playlists } from '../shared/playlists.model';
import { Subject, BehaviorSubject } from 'rxjs/Rx';


@Injectable()
export class PagesService {

  private currentPlaylists: Subject<Playlists> = new  BehaviorSubject<Playlists>(new Playlists());


  constructor(private service: ApiService) {
    this.currentPlaylists.subscribe((v) => console.log(v, 'subscriber from pages service is printing out the incoming value'));
  }

  getPages(platform: Platform) {
    return this.service.getPages(platform.value);
  }

  setCurrentPage(page: Page) {
    this.service.setCurrentPage(page.pageId);
  }

  getCurrentPage():string {
    return this.service.getCurrentPage();
  }

  getCurrentPlaylists() {
    return this.currentPlaylists;
  }

  setCurrentPlaylists(playlists: Playlists) {
    console.log("Pages Service receive an value of playlists:", playlists);
    this.currentPlaylists.next(playlists);
  }
}

我的页面组件代码是:

import { Component, OnInit, Input, Output, OnChanges, EventEmitter, Injectable } from '@angular/core';
import { Http, Response } from '@angular/http';
import { Observable } from 'rxjs/Observable';

import { Platform } from '../platforms/shared/platform.model';
import { Page } from './shared/page.model';
import { Playlists } from './shared/playlists.model';
import { PagesService } from './shared/pages.service';
import { PlaylistService } from '../playlist/shared/playlist.service';
import { Subject,BehaviorSubject } from 'rxjs/Rx';


@Component({
  selector: 'pages',
  styleUrls: ['app/pages/pages.css'],
  templateUrl: 'app/pages/pages.html',
  providers: [PagesService, PlaylistService]
})

export class PagesComponent {

  @Input() platform: Platform;

  @Output() onPlaylistsChange: EventEmitter<Playlists>;

  currentPageName: string;

  currentPage: Page;

  pages: Array<Page>;

  playlists: Playlists;

  constructor(private pageServer: PagesService, private playlistService: PlaylistService) {
    this.pages = [];
    this.currentPage = new Page();
    this.pageServer.setCurrentPage(this.currentPage);
    this.playlists = new Playlists();
    this.onPlaylistsChange = new EventEmitter<Playlists>();
  }

  ngOnInit() {
    this.pageServer.getCurrentPlaylists().subscribe((playlists) => {
      console.log('subscriber in pages component is printing out the incoming value', playlists);
      this.playlists = playlists;
    }, error => {
      console.log(error);
    });
  }

  getPages(platform: Platform): void {
    this.pageServer.getPages(platform)
      .subscribe(
      res => {
        if (res.pages.length > 0) {
          this.pages = [];
          for (let page of res.pages) {
            if (page.pageName !== "Shows" && page.pageName !== "All Shows" && page.pageName !== "Moives" && page.pageName !== "All Movies") {
              this.pages.push(page);
            }
          }
          this.currentPage = this.pages[0];
          this.pageServer.setCurrentPage(this.currentPage);
          this.currentPageName = this.pages[0].pageName;
          this.getPlaylist(this.currentPage, this.platform);
        } else {
          this.pages = [];
          this.currentPage = new Page();
          this.pageServer.setCurrentPage(this.currentPage);
          this.playlists = new Playlists();
          this.onPlaylistsChange.emit(this.playlists);
        }
      },
      error => console.log(error)
      );
  }

  getPlaylist(page: Page, platform: Platform): void {
    this.currentPage = page;
    this.pageServer.setCurrentPage(this.currentPage);
    this.playlistService.getPlaylist(page, platform)
      .subscribe(
      res => {
        if (res.hasOwnProperty('pages') && res.pages.length > 0) {
          if (res.pages[0].hasOwnProperty('bodyPlaylists') && res.pages[0].hasOwnProperty('headerPlaylists')) {
            this.playlists.bodyPlaylists = res.pages[0].bodyPlaylists || [];
            this.playlists.headerPlaylists = res.pages[0].headerPlaylists || [];
          } else {
            this.playlists.bodyPlaylists = [];
            this.playlists.headerPlaylists = [];
            this.playlists.wholePlaylists = res.pages[0].playlists || [];
          }
          this.onPlaylistsChange.emit(this.playlists);
        } else {
          this.playlists = new Playlists();
          this.onPlaylistsChange.emit(this.playlists);
        }
      },
      error => console.error(error)
      );
  }

  ngOnChanges() {
    // Get all Pages when the platform is set actual value;
    if (this.platform.hasOwnProperty('value')) {
      this.getPages(this.platform);
    }
  }

}

当我触发 setCurrentPlaylists 函数时,播放列表没有传递给 pages 组件。我需要使用传递的值来更新页面组件的播放列表。

这是我触发 setCurrentPlaylsts 函数后的控制台输出。没有来自页面组件的消息。 在此处输入图像描述

任何建议表示赞赏!

我从此组件调用 setCurrentPlaylists 函数

/// <reference path="../../../typings/moment/moment.d.ts" />
import moment from 'moment';

import { Component, ViewChild, ElementRef, Input, Output, EventEmitter } from '@angular/core';
import { CORE_DIRECTIVES } from '@angular/common';
import { Http, Response } from '@angular/http';
import { MODAL_DIRECTVES, BS_VIEW_PROVIDERS } from 'ng2-bootstrap/ng2-bootstrap';
import {
  FORM_DIRECTIVES,
  REACTIVE_FORM_DIRECTIVES,
  FormBuilder,
  FormGroup,
  FormControl,
  Validators
} from '@angular/forms';

import { PagesService } from '../../pages/shared/pages.service';
import { ApiService } from '../../apiService/api.service';

@Component({
  selector: 'assign-playlist-modal',
  providers: [PagesService],
  exportAs: 'assignModal',
  directives: [MODAL_DIRECTVES, CORE_DIRECTIVES, FORM_DIRECTIVES, REACTIVE_FORM_DIRECTIVES ],
  viewProviders: [BS_VIEW_PROVIDERS],
  styleUrls: ['app/channel/shared/assignPlaylist.css'],
  templateUrl: 'app/channel/modals/assignPlaylistModal.html'
})

export class AssignPlaylistModalComponent {

  @ViewChild('assignPlaylistModal') modal: any;

  private addPlaylistForm: FormGroup;

  private playlistType: string;

  private currentPage: string;

  private editDate: string;

  constructor(private apiService: ApiService, private pagesService: PagesService, fb: FormBuilder) {
    this.currentPage = '';
    this.editDate = this.apiService.getDate();
    this.addPlaylistForm = fb.group({
      'longPlaylistName': ['', Validators.required],
      'shortPlaylistName': ['', Validators.required],
      'startOn': ['', Validators.compose([
        Validators.required, this.validTimeFormat
      ])],
      'expireOn': ['', Validators.compose([
        Validators.required, this.validTimeFormat
      ])],
      'isExpire': ['']
    });

    this.addPlaylistForm.controls['startOn'].valueChanges.subscribe((value: string) => {
      if (moment(value, 'YYYY-MM-DDThh:mm').isValid()) {
        if (this.playlistType == 'dynamic') {
          this.apiService.setGlobalStartTime(moment(value).format("YYYYMMDDHHmm"));
        }
      }
    });

    this.addPlaylistForm.controls['expireOn'].valueChanges.subscribe((value: string) => {
      if (moment(value, 'YYYY-MM-DDThh:mm').isValid()) {
        if (this.playlistType == 'dynamic') {
          this.apiService.setGlobalEndTime(moment(value).format("YYYYMMDDHHmm"));
        }
      }
    });
  }

  showModal(type: string) {
    this.playlistType = type;
    this.currentPage = this.apiService.getCurrentPage();
    this.modal.show();
  }

  validTimeFormat(control: FormControl): { [s: string]: boolean} {
    if (!moment(control.value, 'YYYY-MM-DDThh:mm').isValid()) {
      return { invalidTime: true};
    }
  }

  setCloseStyle() {
    let styles = {
      'color': 'white',
      'opacity': 1
    }
    return styles;
  }

  createNewPlaylist(stDate: string, etDate: string, playlistTitle: string, shortTitle: string, callback?: any):any {
    this.apiService.createNewPlaylist(stDate, etDate, playlistTitle, shortTitle)
    .subscribe(
      data => {
          let playlistId = data[0].id;
          this.apiService.addPlaylistToPage(playlistId, stDate, etDate, this.apiService.getGlobalRegion(), callback)
          .subscribe(
            data => {
              if (this.apiService.g_platform == 'DESKTOP') {
                this.apiService.getPlaylist(this.apiService.getCurrentPage(), 'true' )
                .subscribe(
                  res => {
                    if (res.hasOwnProperty('pages') && res.pages.length > 0) {
                      if (res.pages[0].hasOwnProperty('bodyPlaylists') && res.pages[0].hasOwnProperty('headerPlaylists')) {
                        this.apiService.getCurrentPlaylists().bodyPlaylists = res.pages[0].bodyPlaylists || [];
                        this.apiService.getCurrentPlaylists().headerPlaylists = res.pages[0].headerPlaylists || [];
                        console.log('assign playlist component is calling the pages service setCurrentPlaylists function.');
                        this.pagesService.setCurrentPlaylists(this.apiService.getCurrentPlaylists());
                      } else {
                        this.apiService.getCurrentPlaylists().bodyPlaylists = [];
                        this.apiService.getCurrentPlaylists().headerPlaylists = [];
                        this.apiService.getCurrentPlaylists().wholePlaylists = res.pages[0].playlists || [];
                        console.log('assign playlist component is calling the pages service setCurrentPlaylists function.');
                        this.pagesService.setCurrentPlaylists(this.apiService.getCurrentPlaylists());
                      }
                    }
                  }
                );
            } else {
              this.apiService.getPlaylist(this.apiService.getCurrentPage(), 'false' )
              .subscribe(
                res => {
                  if (res.hasOwnProperty('pages') && res.pages.length > 0) {
                      this.apiService.getCurrentPlaylists().bodyPlaylists = [];
                      this.apiService.getCurrentPlaylists().headerPlaylists = [];
                      this.apiService.getCurrentPlaylists().wholePlaylists = res.pages[0].playlists || [];
                      console.log('assign playlist component is calling the pages service setCurrentPlaylists function.');
                      this.pagesService.setCurrentPlaylists(this.apiService.getCurrentPlaylists());
                  }
                }
              );
            }
            }
          );
      },
      error => console.log(error)
    );

  }

  onSubmit(form: FormGroup) {


    // get start time, the format from input will be like 2016-06-07T00:05
    let startTime = moment(form.value.startOn).format("YYYYMMDDHHmm");
    let expireTime = moment(form.value.expireOn).format("YYYYMMDDHHmm");
    let playlistTitle = form.value.longPlaylistName;
    let shortTitle = form.value.shortPlaylistName;
    if (this.playlistType == 'smart' || this.playlistType == 'new') {
      this.createNewPlaylist(startTime, expireTime, playlistTitle, shortTitle);
    }
  }

}

这是我的组件树: 在此处输入图像描述

4

2 回答 2

4

我假设您的组件树如下:

AssignPlaylistModalComponent (Parent or higher level than PagesComponent in the tree)
  PagesComponent (lowest level child as it does not import any directive)

问题

您应该只将您的服务放在顶级(父)组件provider中。尽管所有组件仍然需要执行导入和构造函数。

将服务放在组件的提供者中将创建服务的新副本,并沿着组件树向下而不是向上共享。

在有问题的代码中,PagesComponent 作为树中最低级别的子项,具有自己的provider行,实际上是在启动其自己的 PagesService 副本 PlaylistService。所以 PagesComponent 的每个实例基本上都只听自己的。它不会收到来自其他人的任何消息。

使固定

@Component({
  selector: 'pages',
  styleUrls: ['app/pages/pages.css'],
  templateUrl: 'app/pages/pages.html',
  providers: [PagesService, PlaylistService] // <--- Delete this line
})

export class PagesComponent {

  @Input() platform: Platform;

  @Output() onPlaylistsChange: EventEmitter<Playlists>;

放在哪里providers

假设以下组件树:

   Component A1 (root component)
     Component B1
       Component C1
       Component C2
     Component B2
       Component C3
       Component C4

最简单的方法是将它放在 A1 中providers,所有组件将共享同一个服务实例,并且能够相互发送消息。

如果你把它放在 B1 中providers,那么只有 B1、C1 和 C2 可以相互交谈。

根据最新更新,项目的根组件是 AppComponent.ts。providers应该添加进去。

于 2016-08-19T08:20:46.800 回答
1

从您提供的代码中,我看不到这种方法

  setCurrentPlaylists(playlists: Playlists) {
    console.log(playlists, 'i am here');
    this.currentPlaylists.next(playlists);
  }

叫做。因此,您的列表是空的。

这样做

this.pageServer.getCurrentPlaylists().subscribe((playlists) => {
      console.log(playlists, 'new playlists coming');
      this.playlists = playlists;
    }, error => {
      console.log(error);
    });

只创建对 observable 的订阅。您需要从某个地方发布数据。

另外,最好把这段代码挪一下

this.pageServer.getCurrentPlaylists().subscribe((playlists) => {
      console.log(playlists, 'new playlists coming');
      this.playlists = playlists;
    }, error => {
      console.log(error);
    });

ngOnInit()

于 2016-08-12T20:17:31.063 回答