javascript - Angular 2 - 在 View 中操作 rxjs Observable

标签 javascript angular typescript rxjs

我刚开始在 Angular 2 中使用 Observable,但我不知道如何在我的 View 中正确使用它们。

我将 Angular 2 与 angular-redux 结合使用,并使用 @select() 装饰器从 redux 存储中检索我的 selectedMovie$。这部分工作正常,该组件基本上派发一个 redux 事件以在初始化时设置默认 selectedMovie$。 redux 存储已正确更新,但当我尝试在 View 中使用它时,我遇到了一些问题。

import { Component, OnInit } from '@angular/core';
import { NgRedux, select } from '@angular-redux/store';
import { MovieActions} from '../store/app.actions';
import { IAppState} from '../store/reducers';
import { MovieService } from '../movie.service';
import { Observable } from 'rxjs/Observable';
import { IMovie } from '../movie.model';

@Component({
  selector: 'app-movies-container',
  templateUrl: './movies-container.component.html',
  styleUrls: ['./movies-container.component.css'],
  providers: [MovieService]
})
export class MoviesContainerComponent implements OnInit {
  movies: Array<IMovie>;
  @select() readonly selectedMovie$: Observable<IMovie>; // HERE - Get data from the redux store

  constructor(
    private movieService: MovieService,
    private movieActions: MovieActions,
    private ngRedux: NgRedux<IAppState>
  ) { }

  ngOnInit() {
    // Fetch movies and use the first one as default displayed movie.
    this.getMovies() // HERE - Takes the first movie and make it the default selectedMovie by dispatching a redux action
      .then(movies =>
        this.ngRedux.dispatch(this.movieActions.changeSelectedMovie(this.movies[0]))
      );
  }

  getMovies() { // HERE: Call an API, returns an array of movies in data.results
    return this.movieService.getMostPopular()
      .then(data => this.movies = data.results);
  }

  onSelect(movie: IMovie) {
    this.ngRedux.dispatch(this.movieActions.changeSelectedMovie(movie));
  }
}

这里是 View :

<div *ngIf="movies">
  <md-list>
    <h3 md-subheader>Most popular movies NOW!</h3>
    <pre>
      {{(selectedMovie$ | async | json).id}} // This fails and displays nothing. I'd expect it to display the movie id
    </pre>
    <md-list-item
      *ngFor="let movie of movies"
      [class.selected]="movie.id === (selectedMovie$ | async | json).id" // This is a real deal, I don't know what's the syntax to use. I wanted to compare ids
      (click)="onSelect(movie)"
    >
      <img src="https://image.tmdb.org/t/p/w92{{movie.poster_path}}" />
      {{movie.title}}
    </md-list-item>
  </md-list>

  <app-movie-card [movie]="selectedMovie$ | async | json"></app-movie-card> // This component gets the object correctly formatted
</div>

也许我只是没有使用正确的语法。或者我一开始就不应该在 View 中使用观察者?


编辑:解决方案

<div *ngIf="movies && (selectedMovie$ | async); let selectedMovie">
  <md-list>
    <h3 md-subheader>Most popular movies NOW!</h3>
    <md-list-item
      *ngFor="let movie of movies"
      [class.selected]="movie.id === selectedMovie.id"
      (click)="onSelect(movie)"
    >
      <img src="https://image.tmdb.org/t/p/w92{{movie.poster_path}}" />
      {{movie.title}}
    </md-list-item>
  </md-list>

  <app-movie-card [movie]="selectedMovie"></app-movie-card>
</div>

最佳答案

这个问题源于一个常见的误解,即 JSON 是普通对象的同义词。 不是

json 管道将输入转换为实际的 JSON 字符串。所以 (selectedMovie$ | async | json) 表达式的计算结果为一个字符串并且没有 id 属性。

使用 AoT 编译很有帮助,因为它允许检测模板中的类型问题,并且在这种情况下可能会导致类型错误。

它应该是 (selectedMovie$ | async).id 而不是。

如果 (selectedMovie$ | async) 被多次使用(如本例),它将导致多次订阅。可以通过将其分配给局部变量来优化它,如解释的那样 here :

<div *ngIf="movies">
  <ng-container *ngIf="(selectedMovie$ | async); let selectedMovie">
    ...
    {{selectedMovie.id}}
    ...
  </ng-container>
</div>

关于javascript - Angular 2 - 在 View 中操作 rxjs Observable,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46455277/

相关文章:

javascript - Angular 和 ngrx : problems during upgrading to version8

angular - 响应式(Reactive)表单 MinLength 验证未显示错误

reactjs - 类型 'onClick' 上不存在属性 '{ children?: ReactNode; }'

javascript - 在 ES6/TS 中通过 mutate 将对象设置为 null 以匹配 Set 中的条件

javascript - 我无法将变量与 SPservices 中的字符串 String 进行比较

javascript - 类型错误 : value is undefined jquery

angular - 安装 ng 添加 @ng-bootstrap/ng-bootstrap 时出错

json - 如何将定义 typescript 转换为 json?

javascript - 如何编写依赖于另一个套件变量的 Jasmine 测试套件? ( Jasmine 1.3)

javascript - 将嵌套的 if 语句转换为更优雅的 switch?