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

Angular Material多自动完成组件显示相同下拉框问题求助

问题排查与修复方案

嘿,我帮你梳理了代码里的问题,这几个点是导致下拉框显示相同内容、还有报错的根源,咱们一步步来修复:


问题根源拆解

  • 两个下拉框共用同一个FormControl:你把所有输入变化都绑定到myControl上,导致输入时两个过滤器同时响应同一个值,内容自然会混乱。
  • 过滤函数逻辑写错了:你的filter函数里用逗号分隔了两个过滤操作,在JavaScript里逗号运算符只会返回最后一个表达式的结果,所以不管你想过滤国家还是国籍,最终返回的都是国籍的过滤结果。
  • 模板引用串了:第二个输入框的[matAutocomplete]还指向第一个的#auto,这会导致下拉框关联错误,肯定会报错。

修复后的组件代码

import { Component, OnInit } from '@angular/core';
import { FormControl } from '@angular/forms';
import { Observable } from 'rxjs';
import { startWith, map } from 'rxjs/operators';

// 注意:UsersComponent是UI组件,不该用来当数据模型!换成简单的接口更合适
interface Option {
  name: string;
}

@Component({
  selector: 'app-accommodation',
  templateUrl: './accommodation.component.html',
  styleUrls: ['./accommodation.component.css']
})
export class AccommodationComponent implements OnInit {
  // 给每个下拉框单独创建FormControl,确保状态互不干扰
  countryControl = new FormControl();
  nationalityControl = new FormControl();

  // 用接口定义数据,不再实例化组件当作数据载体
  country: Option[] = [
    { name: 'United States' },
    { name: 'Canada' },
    { name: 'Brazil' },
    { name: 'India' },
    { name: 'China' },
    { name: 'Japan' },
  ];
  nationality: Option[] = [
    { name: 'American' },
    { name: 'Canadian' },
    { name: 'Indian' },
    { name: 'Chinese' },
    { name: 'African' },
    { name: 'Japanese' },
  ];

  countryFilter: Observable<Option[]>;
  nationalityFilter: Observable<Option[]>;

  ngOnInit() {
    // 国家下拉框的过滤流,绑定专属的control
    this.countryFilter = this.countryControl.valueChanges
      .pipe(
        startWith<string | Option>(''),
        map(value => typeof value === 'string' ? value : value.name),
        map(name => name ? this.filterOptions(name, this.country) : this.country.slice())
      );

    // 国籍下拉框的过滤流,绑定专属的control
    this.nationalityFilter = this.nationalityControl.valueChanges
      .pipe(
        startWith<string | Option>(''),
        map(value => typeof value === 'string' ? value : value.name),
        map(name => name ? this.filterOptions(name, this.nationality) : this.nationality.slice())
      );
  }

  // 改成通用过滤函数,传入要过滤的数组,避免重复代码与逻辑错误
  filterOptions(name: string, options: Option[]): Option[] {
    const filterValue = name.toLowerCase();
    return options.filter(option => 
      option.name.toLowerCase().startsWith(filterValue)
    );
  }

  displayFn(option?: Option): string | undefined {
    return option ? option.name : undefined;
  }
}

修复后的HTML代码

<div class="col-sm-6">
  <mat-form-field class="example-full-width">
    <input type="text" placeholder="Country" aria-label="Country" 
           matInput [formControl]="countryControl" [matAutocomplete]="autoCountry">
    <mat-autocomplete #autoCountry="matAutocomplete" [displayWith]="displayFn">
      <mat-option *ngFor="let option of countryFilter | async" [value]="option">
        {{ option.name }}
      </mat-option>
    </mat-autocomplete>
  </mat-form-field>
</div>
<!-- col end -->
<div class="col-sm-6">
  <mat-form-field class="example-full-width">
    <input type="text" placeholder="Nationality" aria-label="Nationality" 
           matInput [formControl]="nationalityControl" [matAutocomplete]="autoNationality">
    <mat-autocomplete #autoNationality="matAutocomplete" [displayWith]="displayFn">
      <mat-option *ngFor="let option of nationalityFilter | async" [value]="option">
        {{ option.name }}
      </mat-option>
    </mat-autocomplete>
  </mat-form-field>
</div>
<!-- col end -->

关键修改说明

  1. 独立FormControl:每个下拉框使用专属的control,输入时各自的过滤流只响应自身的输入状态,彻底解决内容互相干扰的问题。
  2. 修正数据模型:组件是用来渲染UI的,不能当作数据模型使用,换成简单的接口既符合Angular设计思路,也避免了不必要的组件实例化开销。
  3. 通用过滤函数:将过滤逻辑抽成通用方法,传入目标数组,既解决了之前的逗号运算符错误,还能复用代码。
  4. 模板引用修正:每个自动完成组件使用独立的模板引用,确保输入框和对应的下拉框正确绑定,消除关联错误的报错。
  5. 过滤逻辑优化:用startsWith替代indexOf === 0,代码更易读,功能完全一致。

这样改完之后,两个下拉框就会独立工作,过滤逻辑正确,也不会有报错啦~

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 08:01:57