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

Angular中如何为mat-select下拉框实现内置搜索筛选功能

Angular Material mat-select 内置搜索实现

你直接在<mat-select>标签内插入原生<input>是没法正常用的:一方面mat-select的下拉面板会拦截普通元素的焦点、点击事件,点输入框会直接收起面板;另一方面没有绑定过滤逻辑,输入内容也不会筛选选项。按下面的步骤改就能实现你要的效果:


具体实现

1. 组件逻辑部分

先在组件类里加搜索控件、过滤逻辑,记得处理订阅回收避免内存泄漏:

import { Component, OnDestroy, OnInit } from '@angular/core';
import { FormControl } from '@angular/forms';
import { Subject, takeUntil } from 'rxjs';

// 对应你的选项数据结构
interface TargetOption {
  id: string | number;
  name: string;
}

@Component({
  selector: 'app-target-select',
  templateUrl: './target-select.component.html',
  styles: [`
    .search-box-wrapper {
      padding: 8px 16px;
      position: sticky;
      top: 0;
      background: #fff;
      z-index: 10;
      border-bottom: 1px solid #f0f0f0;
    }
    .search-box-wrapper mat-form-field {
      width: 100%;
      margin-bottom: 0 !important;
    }
  `]
})
export class TargetSelectComponent implements OnInit, OnDestroy {
  // 原始全量选项数据
  targetListOptions: TargetOption[] = [];
  // 实时过滤后展示的选项
  filteredOptions: TargetOption[] = [];
  // 搜索框绑定的表单控件
  searchCtrl = new FormControl('');

  private destroy$ = new Subject<void>();

  ngOnInit(): void {
    // 这里替换成你实际加载选项的逻辑,比如接口请求返回后给两个列表赋值
    this.filteredOptions = [...this.targetListOptions];

    // 监听搜索输入实时过滤
    this.searchCtrl.valueChanges
      .pipe(takeUntil(this.destroy$))
      .subscribe(keyword => {
        const searchKey = (keyword || '').trim().toLowerCase();
        if (!searchKey) {
          this.filteredOptions = [...this.targetListOptions];
          return;
        }
        // 按选项名称模糊匹配,可根据业务需求调整匹配规则
        this.filteredOptions = this.targetListOptions.filter(item =>
          item.name.toLowerCase().includes(searchKey)
        );
      });
  }

  // 面板关闭时重置搜索词,避免下次打开残留上次搜索结果
  onPanelOpenChange(isOpen: boolean): void {
    if (!isOpen) {
      this.searchCtrl.reset('', { emitEvent: false });
    }
  }

  ngOnDestroy(): void {
    this.destroy$.next();
    this.destroy$.complete();
  }
}

2. 模板改造

核心是给搜索框容器阻止事件冒泡,避免点击输入框时面板被默认逻辑收起,同时遍历过滤后的选项列表而不是原始列表:

<mat-select 
  formControlName="targetListValue"
  (openedChange)="onPanelOpenChange($event)"
>
  <!-- 搜索框容器,阻止事件冒泡是核心 -->
  <div class="search-box-wrapper" (click)="$event.stopPropagation()">
    <mat-form-field appearance="outline" subscriptSizing="dynamic">
      <input 
        matInput 
        [formControl]="searchCtrl" 
        placeholder="输入关键词搜索"
        autocomplete="off"
      >
      <button 
        mat-icon-button 
        matSuffix 
        *ngIf="searchCtrl.value" 
        (click)="searchCtrl.reset()"
        type="button"
      >
        <mat-icon>close</mat-icon>
      </button>
    </mat-form-field>
  </div>

  <!-- 默认空选项 -->
  <mat-option [value]="null">请选择</mat-option>
  <!-- 遍历过滤后的选项 -->
  <mat-option 
    *ngFor="let targetItem of filteredOptions" 
    [value]="targetItem.id"
  >
    {{ targetItem.name }}
  </mat-option>
  <!-- 无匹配结果提示 -->
  <mat-option *ngIf="filteredOptions.length === 0" disabled>
    没有找到匹配的选项
  </mat-option>
</mat-select>

注意事项

  • 记得在所属的Angular模块里导入ReactiveFormsModule、MatFormFieldModule、MatInputModule、MatIconModule,否则相关组件会报错
  • 搜索框设置sticky定位是为了选项较多滚动时,搜索框能固定在面板顶部,不用滚回顶部就能改搜索词,体验更好
  • 如果需要支持拼音搜索、多字段匹配,直接改filter里的判断逻辑就行,不用动模板结构

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 22:48:17