You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

无法将Observable绑定到Mat Chips自动完成组件的问题

问题:Observable触发但MatAutocomplete下拉列表不加载数据

我搭建了一个搜索引擎,需要通过Observable获取下拉自动补全建议。Observable已经触发(tap操作里能看到日志输出),但模板里的下拉列表始终加载不出数据。

原HTML代码

<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([])
}

问题分析与修正方案

1. 重复模板引用导致绑定错误

模板里存在两个#auto="matAutocomplete",输入框的[matAutocomplete]="auto"会优先匹配最后一个(即显示Loading的那个),导致承载数据的autocomplete从未被关联到输入框。

2. Observable未关联输入框实时值

registerAccountListener中固定传参'SHE'调用接口,没有响应输入框的实时输入内容,即使有数据也不是用户需要的结果。

3. 模板方法调用引发重复订阅

*ngIf="getChipsValueDropdowns(...) | async"会在每次变更检测时重新创建Observable,导致重复订阅,且无法和输入值变化联动。


修正后的代码

HTML部分

合并重复的autocomplete,统一处理加载状态和数据展示:

<mat-form-field>
  <mat-chip-grid #chipGrid aria-label="Value selection">
    @for (fruit of fruits(); track $index) {
    <mat-chip-row (removed)="remove(fruit)">
      <!-- 你的chip业务逻辑 -->
    </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>

<mat-autocomplete #auto="matAutocomplete">
  <!-- 加载状态 -->
  <mat-option *ngIf="!(accounts$ | async)">Loading ...</mat-option>
  <!-- 数据列表 -->
  <mat-option *ngFor="let account of accounts$ | async" [value]="account">
    {{account.name}}
  </mat-option>
</mat-autocomplete>

TS部分

将Observable与输入框的valueChanges绑定,避免重复创建Observable:

import { of, Observable } from 'rxjs';
import { debounceTime, distinctUntilChanged, switchMap, map, tap } from 'rxjs/operators';
import { FormControl, FormArray } from '@angular/forms';

// 组件内定义用于自动补全的Observable
accounts$: Observable<Account[]> = of([]);

// 假设组件初始化时获取对应的formArray索引
private index: number; // 替换为实际的formArray项索引

ngOnInit(): void {
  // 获取输入框对应的FormControl
  const valueControl = this.formArray.controls[this.index].get('value') as FormControl;
  
  // 绑定输入值变化到接口请求
  this.accounts$ = valueControl.valueChanges.pipe(
    debounceTime(300), // 防抖减少请求
    distinctUntilChanged(), // 输入值不变时不重复请求
    switchMap(inputValue => {
      // 使用输入框实时值调用搜索接口
      return this.accountService.searchAccounts(inputValue).pipe(
        map(response => response.body ?? []), // 处理空响应
        tap(accounts => console.log('Emitting accounts:', accounts))
      );
    })
  );
}

额外检查点

  • 确认Account接口的name字段拼写正确,与接口返回字段一致
  • 验证formArray的索引index正确,确保绑定的FormControl是目标输入框的控件
  • 确认accountService.searchAccounts返回的Observable能正常发出数据(日志已显示可忽略此条)

内容的提问来源于stack exchange,提问作者JackOrlen

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 13:10:57