首页 > 解决方案 > Angular12/rxjs:更新模板中的可观察数据并显示模板中的更改

问题描述

所以我有一个实时搜索,根据用户输入获取数据。

例子:

export class MyComponent implements OnInit {
      constructor(private httpHandler: HttpHandlerService) { }

      defaultSearchParams: SearchParams = { search: 'bla' }
      searchParams = new BehaviorSubject<SearchParams>(this.defaultSearchParams);
      myData$?: Observable<PageObjects<MyDataObject>>;
    
      ngOnInit(): void {
        this.myData$ = this.searchParams.pipe(
          debounceTime(300),
          switchMap((searchParams: SearchParams) => this.fetchMyData(searchParams)),
        );
      }
    
      fetchMyData(searchParams: SearchParams): Observable<MyDataObject> {
        return this.httpHandler.getMyData(searchParams);
      }
}

我的模板显示数据:

  <div *ngIf="(myData$ | async) as resultset$">
      <div *ngIf="resultset$.elements && resultset$.elements.length">
          <div *ngFor="let dataObject of resultset$.elements">
                ID: {{dataObject.id}}, name {{dataObject.name}}, status {{dataObject.status}}
          </div>
      </div>
  </div>

好吧,挑战来了:在我的模板中,我希望能够更改数据(即新名称、新状态)。

使用像我这样的可观察对象时,如何在模板中反映这些更改的数据?

期望结果的样本:


  <div *ngIf="(myData$ | async) as resultset$">
      <div *ngIf="resultset$.elements && resultset$.elements.length">
          <div *ngFor="let dataObject of resultset$.elements">
                ID: {{dataObject.id}}, name {{dataObject.name}}, status {{dataObject.status}}
                <button (click)="changeStatus(dataObject)" type="button">Change status</button>
          </div>
      </div>
  </div>
    changeStatus(MyDataObject dataObject) {
         this.httpHandler.changeStatusOfObject(dataObject, 'newStatus')
                .subscribe(newDataObject => //WHERE should I put the newDataObject to, to show the new value in the template???);
    }

标签: angulartypescriptrxjsangular12

解决方案


尝试更改changeStatus函数以将更改推送到预定义的BehaviorSubject changes$,与 searchParams observable 结合形成myData$observable。

您可以尝试以下方法:

  changes$ = new BehaviorSubject<MyDataObject[]>([]);

  ngOnInit(): void {
    this.myData$ = combineLatest([
      this.searchParams.pipe(
        debounceTime(300),
        switchMap((searchParams: SearchParams) =>
          this.fetchMyData(searchParams)
        )
      ),
      this.changes$,
    ]).pipe(
      map(([data, changes]) => {
        if (changes?.length && data?.elements) {
          changes.forEach((changedItem) => {
            const ndx = data.elements.findIndex(
              (item) => item.id === changedItem.id
            );
            if (ndx !== -1) data.elements[ndx] = changedItem;
          });
        }
        return data;
      })
    );
  }
  changeStatus(dataObject: MyDataObject) {
    this.httpHandler
      .changeStatusOfObject(dataObject, 'newStatus')
      // take one value from this observable and then complete it, to avoid memory leak
      .pipe(take(1))
      .subscribe((newDataObject) => {
        // push the newDataObject to the chagnes$ subject.
        this.changes$.next([newDataObject]);
      });
  }

推荐阅读