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

Angular Material Autocomplete选择复杂对象后如何正确显示属性?

解决Angular Material Autocomplete选中对象后输入框显示[object Object]的问题

核心问题分析

你的FormControl定义为FormControl<string>,但mat-option绑定的是TokenNameWithId对象,选中后输入框会将对象直接转为字符串,导致显示[object Object]。同时原有过滤逻辑未兼容对象类型的输入值,会引发后续逻辑错误。

解决方案步骤

1. 调整FormControl类型

将tokenNamesControl的类型改为支持用户输入的字符串和选中的对象两种情况:

public tokenNamesControl = new FormControl<TokenNameWithId | string>('', {
  nonNullable: true,
});

2. 添加displayWith函数

在组件中定义函数,指定输入框需要显示的文本内容:

displayTokenName(token?: TokenNameWithId | string): string {
  // 区分处理用户输入的字符串和选中的对象
  return typeof token === 'string' ? token : token?.displayName || '';
}

3. 修正过滤逻辑

更新ngOnInit中的过滤逻辑,兼容字符串和对象类型的输入值:

ngOnInit(): void {
  this.filteredTokenNames = combineLatest([
    this.tokenNamesControl.valueChanges.pipe(startWith('')),
    this.tokenNames$,
  ]).pipe(
    debounceTime(250),
    map(([value, tokenNamesWithId]) => {
      // 将输入值统一转为过滤用的字符串
      const filterValue = typeof value === 'string' 
        ? value.toLowerCase() 
        : value.displayName.toLowerCase();
      return filterValue ? this._filter(filterValue, tokenNamesWithId) : tokenNamesWithId;
    })
  );
}

保持_filter函数不变(此时传入的value已确保是字符串):

private _filter(value: string, tokenNamesWithId: TokenNameWithId[]): TokenNameWithId[] {
  return tokenNamesWithId.filter(token => 
    token.displayName.toLowerCase().includes(value)
  );
}

4. 配置模板中的displayWith属性

在mat-autocomplete上绑定刚定义的displayWith函数:

<mat-autocomplete #auto="matAutocomplete" [displayWith]="displayTokenName">
  @for (tokenName of filteredTokenNames | async ; track tokenName) {
    <mat-option [value]="tokenName">{{tokenName.displayName}}</mat-option>
  }
</mat-autocomplete>

修改后的完整组件代码

import { Component, OnInit } from '@angular/core';
import {FormControl, FormsModule, ReactiveFormsModule} from '@angular/forms';
import {AsyncPipe} from '@angular/common';
import {MatAutocompleteModule} from '@angular/material/autocomplete';
import {MatInputModule} from '@angular/material/input';
import {MatFormFieldModule} from '@angular/material/form-field';
import { TokenNameWithId } from '../../../shared/models/card.model';
import { Observable, combineLatest, debounceTime, map, startWith } from 'rxjs';
import { Store } from '@ngrx/store';
import { selectAllTokenNames } from '../+state/token-names.selectors';

@Component({
  selector: 'tokenator-tokens-dropdown',
  standalone: true,
  imports: [FormsModule,
    MatFormFieldModule,
    MatInputModule,
    MatAutocompleteModule,
    ReactiveFormsModule,
    AsyncPipe
  ],
  templateUrl: './tokens-dropdown.component.html',
  styleUrl: './tokens-dropdown.component.scss',
})
export class TokensDropdownComponent implements OnInit {
  public tokenNamesControl = new FormControl<TokenNameWithId | string>('', {
    nonNullable: true,
  });
  public filteredTokenNames!: Observable<TokenNameWithId[]>;
  private tokenNames$ = this.store.select(selectAllTokenNames);

  constructor(private store: Store) {
  }

  ngOnInit(): void {
    this.filteredTokenNames = combineLatest([
      this.tokenNamesControl.valueChanges.pipe(startWith('')),
      this.tokenNames$,
    ]).pipe(
      debounceTime(250),
      map(([value, tokenNamesWithId]) => {
        const filterValue = typeof value === 'string' 
          ? value.toLowerCase() 
          : value.displayName.toLowerCase();
        return filterValue ? this._filter(filterValue, tokenNamesWithId) : tokenNamesWithId;
      })
    );
  }

  displayTokenName(token?: TokenNameWithId | string): string {
    return typeof token === 'string' ? token : token?.displayName || '';
  }

  private _filter(value: string, tokenNamesWithId: TokenNameWithId[]): TokenNameWithId[] {
    return tokenNamesWithId.filter(token => 
      token.displayName.toLowerCase().includes(value)
    );
  }
}

组件选择说明

mat-autocomplete搭配matInput是Angular Material中实现复杂对象选择+自动完成的标准方案,完全匹配你的需求,无需更换其他组件。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.29 21:55:23