使异步管道更新Angular 2中的视图

时间:2017-05-16 20:30:09

标签: angular asynchronous pipe

下面看到的组件会在初始化时显示模板中的事件列表(ngOnInit())。但是,调用addEvent()时,视图将不会更新。为什么会这样?

每当我将新数据发布到用于填充可观察属性(events: Observable<Event[]>)的数据存储时,如何使视图更新?

@Component({
    template:
        <ul>
            <li *ngFor="let event of events | async"
{{ event.title }}
</li>
</ul>
<button (click)="addEvent()">Add event</button>

})
export class EventCenterListComponent implements OnInit {
    events: Observable<Event[]>;

    constructor(
        private eventsService: EventsService,
    ) {}


    ngOnInit() {
        this.events = return this.eventsService.getEvents();
    }

    addEvent() {
        this.eventsService.createEvent('New event'); <--this would add one event to the data source
        this.events = this.eventsService.getEvents(); <-- that reassignment would not be seen in the template
    }
}

我已经看到许多教程,包括Angulat的官方教程,将Observable转换为普通数组,然后将push个新值转换为数组,例如:

heroes: Hero[];

addHero(name: string) {
  this.heroService.create(name)
                   .subscribe(
                     hero  => this.heroes.push(hero), <-- that would work 
                     error =>  this.errorMessage = <any>error);
} 

但上述真的有必要吗?我不能直接在observable上操作并更新视图吗?

1 个答案:

答案 0 :(得分:2)

是的,最好不要在组件中订阅。

这是一个想法。事件服务保留一系列私有事件,并在每次更改时触发主题。该组件可以使用异步管道,以便在该主题触发时更新其视图。

@Injectable()
export class EventsService {
  private events: Event[] = [];

  private eventsSubject = new Subject<Event[]>();
  private _events$ = this.eventsSubject.asObservable();

  createEvent(title: string) {
    const newEvent: Event = {title};
    this.events = [...this.events, newEvent];
    this.eventsSubject.next(this.events);
  }

  getEvents$() {
    return this._events$;
  }
}

@Component({
  template: `
    <ul>
      <li *ngFor="let event of events | async">{{ event.title }}</li>
    </ul>
    <button (click)="addEvent()">Add event</button>`
})
export class EventCenterListComponent {
  events: Observable<Event[]>;

  constructor(private eventsService: EventsService) {
    this.events = eventsService.getEvents$();
  }

  addEvent() {
    this.eventsService.createEvent('New event');
  }
}

<强>更新

仔细阅读您的问题后的新想法。假设EventService的工作方式如下:

createEvent(title: string): Observable<void> // post one new event to server
getEvents(): Observable<Event[]> // get list of events from server

...您只想在发布新事件后重新获取事件列表,然后像这样实现EventCenterListComponent:

export class EventCenterListComponent {
  events: Observable<Event[]>;

  private newEventSubject = new Subject<string>();

  constructor(eventsService: EventsService) {
    const eventWasCreated$ = this.newEventSubject.mergeMap(title =>
      eventsService.createEvent(title));

    const shouldRefresh$ = eventWasCreated$.startWith(undefined);

    this.events = shouldRefresh$.switchMap(() =>
      eventsService.getEvents());

    // optional, if you are going to subscribe to `events` in more
    // than one place:
    this.events = this.events.share();
  }

  addEvent() {
    this.newEventSubject.next('New event');
  }
}