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

如何基于对象数据源实现Angular Material Autocomplete组件?

解决Angular Material Autocomplete绑定对象数据源的类型错误问题

你的核心问题是嵌套订阅导致的类型不匹配,以及对象数据源未正确转换为Autocomplete所需的可遍历结构。以下是分步修复方案:

1. 修正数据源与过滤逻辑(组件类)

不要在map里直接订阅currencies$,这会返回Subscription而非预期的Observable。改用combineLatest结合表单值变化与数据源,同时将对象转换为可遍历数组:

import { Component, OnInit } from '@angular/core';
import { FormBuilder, FormGroup } from '@angular/forms';
import { Observable, combineLatest, startWith, map } from 'rxjs';
import { CurrencyService } from './currency.service';

interface Currencies {
  currency: Record<string, string>; // 匹配你的currencies.json结构:{ currency: { USD: "US Dollar", ... } }
}

@Component({
  selector: 'app-autocomplete-example',
  templateUrl: './autocomplete-example.component.html',
})
export class AutocompleteExampleComponent implements OnInit {
  formMain: FormGroup;
  currencies$: Observable<Currencies>;
  filteredCurrencies$: Observable<{ key: string; value: string }[]>;

  constructor(
    private fb: FormBuilder,
    private _currencyService: CurrencyService
  ) {
    this.formMain = this.fb.group({
      currency: ['']
    });
    this.currencies$ = this._currencyService.list();
  }

  ngOnInit(): void {
    // 组合表单输入变化与数据源,生成实时过滤的货币列表
    this.filteredCurrencies$ = combineLatest([
      this.formMain.get('currency')!.valueChanges.pipe(startWith('')),
      this.currencies$
    ]).pipe(
      map(([inputValue, currencies]) => {
        const filterValue = inputValue.toString().toUpperCase();
        // 将currency对象转为键值对数组后过滤
        return Object.entries(currencies.currency)
          .map(([key, value]) => ({ key, value }))
          .filter(item => item.key.toUpperCase().includes(filterValue));
      })
    );
  }
}

2. 修正模板绑定

直接使用过滤后的filteredCurrencies$,无需keyvalue管道,确保async管道正确处理Observable:

<mat-form-field appearance="fill">
  <mat-label>Currency</mat-label>
  <input 
    id="currency" 
    type="text" 
    matInput 
    placeholder="Select a currency. E.g. USD" 
    [matAutocomplete]="auto" 
    formControlName="currency"
  >
  <mat-autocomplete autoActiveFirstOption #auto="matAutocomplete">
    <mat-option 
      *ngFor="let currency of filteredCurrencies$ | async" 
      [value]="currency.key"
    >
      {{ currency.key }} ({{ currency.value }})
    </mat-option>
  </mat-autocomplete>
</mat-form-field>

错误原因说明

你之前的代码中,map函数返回的是this.currencies$.subscribe(...)的结果(即Subscription对象),但currencies$的类型是Observable<Currencies>,这直接导致了TypeScript类型不匹配错误。通过combineLatest同时监听表单输入和数据源,既避免了嵌套订阅,也正确处理了类型转换。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.25 17:01:36