Angular:尝试将我的函数转换为 rxjs

Angular: Trying to turn my function into rxjs

我有一个功能已经实现并且可以正常工作 我想在 rxjs 目录中使用 pipe 和 includes

使其成为带有过滤器的 rxjs

并订阅更新

  posts: Post[] = [];
   validPosts: Post[] = [];
   authorName: string = "";

这是我的职能:

SearchPostsByName($event: Event) {
    const searchKey = ($event.target as HTMLInputElement).value;

    if (searchKey === '') {
      this.validPosts = this.posts;
      return;
    }
    
    this.validPosts = this.posts.filter(
      value => value.authorName.includes(this.searchName)
    );
  }

要使用输入字段构建搜索,请将输入元素绑定到 @ViewChild

<label>Search Posts </label>
<div>
  <input #search type="text" [value]="filterInput" />
</div>
export class AppComponent implements OnInit, AfterViewInit, OnDestroy {

  @ViewChild('search', { static: true }) search: ElementRef;

  private subscription: Subscription;

  public posts$: Observable<Post[]>;
  public filterInput: string = '';
  public errorMessage: string = '';

  constructor(
    private router: Router,
    private route: ActivatedRoute,
    private appService: AppService
  ) {}

  ...

}

AfterViewInit 中,您将一个可观察对象添加到元素的 keyup 事件。通过一个pipe,你map事件给它赋值。您添加了一个 debounceTime 这样可观察对象就不会经常发出,并且您只通过 distinctUntilChanged.

监听变化

在订阅本身中,您检查输入值并根据输入更改 url queryParams

ngAfterViewInit() {
  this.subscription = fromEvent(this.search.nativeElement, 'keyup')
    .pipe(
      map((event: KeyboardEvent) => (event.target as HTMLInputElement).value),
      debounceTime(500),
      distinctUntilChanged()
    )
    .subscribe((filter) => {
      const queryParams = filter ? { queryParams: { filter } } : undefined;
      this.router.navigate(['.'], {
        relativeTo: this.route,
        ...queryParams,
      });
    });
}

OnInit 期间,您 switchMap 路由 queryParams 的可观察对象到一个新的可观察对象,它将通过服务从您的数据库中获取过滤后的帖子。在 window 刷新后,来自 url 的过滤器查询也将设置为输入值。

private fetchPosts() {
  this.posts$ = this.route.queryParams
    .pipe(
      switchMap((params) => {
        if (params.filter) this.filterInput = params.filter;
        return this.appService.fetchPosts(params.filter);
      })
    )
    .pipe(
      catchError((err) => {
        this.errorMessage = err;
        return EMPTY;
      })
    );
}

ngOnInit() {
  this.fetchPosts();
}

为了显示内容,您通过 html 中的 async 管道订阅了可观察对象。

<div *ngIf="posts$ | async as posts; else loadingOrError">
  <div *ngIf="!posts.length">
    <h3>No posts found</h3>
  </div>
  <div *ngFor="let post of posts">
    <b>{{ post?.content }}</b>
    <br/>
    <i>
      by <b>{{ post?.authorName }}</b> at
      <b>{{ post?.date | date: 'dd MMMM YYYY' }}</b>
    </i>
    <hr />
  </div>
</div>

<ng-template #loadingOrError>
  <span *ngIf="errorMessage; else loading">
    An error occured while loading the posts: {{ errorMessage }}
  </span>
  <ng-template #loading> ...loading... </ng-template>
</ng-template>

State management, using RxJS | URL vs local client state

StackBlitz | Filter through RxJS