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
相关产品推荐
相关产品推荐

