无法将 observable 绑定到 mat 芯片自动完成

问题描述 投票:0回答:1

我有一个搜索引擎,我需要注册可观察并获取下拉自动完成建议,但即使触发了可观察,我可以在点击内看到我似乎无法将列表加载到我的模板下拉列表中

这是我的代码:

 <mat-form-field>
          <mat-chip-grid #chipGrid aria-label="Value selection">
            @for (fruit of fruits(); track $index) {
            <mat-chip-row (removed)="remove(fruit)">
              //logic for fow
            </mat-chip-row>
            }
          </mat-chip-grid>
          <input placeholder="Start typing to see suggestions" #fruitInput formControlName="value"
            [matChipInputFor]="chipGrid" [matAutocomplete]="auto"
            [matChipInputSeparatorKeyCodes]="separatorKeysCodes"/>

          </mat-form-field>
          <div *ngIf="getChipsValueDropdowns(select.value, i) | async as accounts">
            <mat-autocomplete #auto="matAutocomplete">
              <mat-option *ngFor="let account of accounts"
                [value]="account">{{account.name}}</mat-option>
            </mat-autocomplete>
          </div>
          <mat-autocomplete #auto="matAutocomplete">
            <mat-option> Loading ...</mat-option>
          </mat-autocomplete>

在我的 ts 文件中我有函数:

getChipsValueDropdowns(key: string, index: number): Observable<Account[]> {
if (key === 'account') {
  return this.registerAccountListener(key, index)
}
return of([])

}

registerAccountListener(key: string, index: number) {
    const control: FormControl = this.formArray.controls[index].get('key') as FormControl
    if (control.value === key) {
      return this.accountService.searchAccounts('SHE').pipe(
        debounceTime(300),
        distinctUntilChanged(),
        map((response: { body: Account[] | null }) => {
          return response.body ?? []
        }),
        tap((accounts) => {
          console.log('Emitting accounts:', accounts)
        }),
      )
    }
    return of([])
  }
angular rxjs angular-material
1个回答
0
投票

问题是你在模板中调用

getChipsValueDropdowns()
函数,并且每次该函数运行时都会返回一个新的 Observable。当 Observable 返回一个值时,异步管道会标记该组件进行检查并触发一个新的更改检测周期,该周期会再次调用该函数并重新启动该进程。这是非常糟糕的做法,因为它会触发大量请求,甚至可能引发无限循环。您已通过根据实际请求使用
distinctUntilChanged()
运算符解决了此问题,但它只能解决此问题的症状。

相反,您应该将表单中的

valueChanges
observable 与执行请求的 Observable 与
switchMap()
:

结合起来
export class YourComponent {
  drowdownValues$ = yourFormGroup.controls.select.valueChanges.pipe(
    debounceTime(300),
    distinctUntilChanged(),
    switchMap((value) => {
      const control: FormControl = this.formArray.controls[index].get(
        "key",
      ) as FormControl;
      if (control.value === key) {
        return this.accountService.searchAccounts("SHE").pipe(
          map((response: { body: Account[] | null }) => {
            return response.body ?? [];
          }),
          tap((accounts) => {
            console.log("Emitting accounts:", accounts);
          }),
        );
      }
      return of([]);
    }),
  );
}

并在模板中使用 Observable,如下所示:

<div *ngIf="drowdownValues$ | async as accounts">
© www.soinside.com 2019 - 2024. All rights reserved.