如何实现带搜索功能的Angular下拉选择框
为Angular Material mat-select实现动态数据搜索功能
实现思路
在mat-form-field内添加搜索输入框,结合组件内的过滤逻辑对SupplierDTO[]动态数据做实时过滤,实现带搜索的下拉选择功能。
修改后的HTML代码
<mat-form-field class="box" appearance="fill"> <mat-label>Supplier</mat-label> <!-- 新增搜索输入框,绑定关键词并触发过滤 --> <input matInput placeholder="搜索供应商" [(ngModel)]="searchKeyword" (input)="filterSuppliers()"> <mat-select formControlName="supplierId" (selectionChange)="selectedSupplier($event)"> <!-- 遍历过滤后的供应商数组 --> <mat-option *ngFor="let item of filteredSuppliers" [value]="item.id"> {{item.companyName}} </mat-option> </mat-select> </mat-form-field>
修改后的TS代码
import { Component, OnInit } from '@angular/core'; import { MatSelectChange } from '@angular/material/select'; import { FormBuilder, FormGroup, Validators } from '@angular/forms'; import { SupplierDTO } from './your-supplier-dto-path'; // 替换为实际文件路径 import { YourSupplierService } from './your-supplier-service-path'; // 替换为实际服务路径 export class DeliveryReceiptComponent implements OnInit { supplier: SupplierDTO[] = []; filteredSuppliers: SupplierDTO[] = []; searchKeyword: string = ''; deliveryReceiptForm: FormGroup; selectedSupplierID: number | undefined; APRDisplayed: boolean = false; dbmRequired: string = 'your-dbm-target-value'; // 替换为实际判断值 constructor( private supplierSvc: YourSupplierService, private fb: FormBuilder ) { // 初始化表单结构 this.deliveryReceiptForm = this.fb.group({ supplierId: [''], Bank: [''], AccountName: [''], AccountNumber: [''], Branch: [''], purchaseRequestNumber: [''], purchaseRequestDate: [''], drNumFrSupplier: [''], drDate: [''], aprNum: [''], aprDate: [''], purchaseOrderNumber: [''], purchaseOrderDate: [''], saleInvoiceDate: [''], saleInvoiceNumber: [''] }); } ngOnInit(): void { // 从服务拉取动态供应商数据 this.supplierSvc.getSuppliers().subscribe((data: SupplierDTO[]) => { this.supplier = data; this.filteredSuppliers = [...this.supplier]; // 初始化过滤数组 }); } // 供应商过滤逻辑 filterSuppliers(): void { if (!this.searchKeyword.trim()) { this.filteredSuppliers = [...this.supplier]; return; } const keyword = this.searchKeyword.toLowerCase(); this.filteredSuppliers = this.supplier.filter(item => item.companyName.toLowerCase().includes(keyword) // 可扩展搜索字段,比如:item.id.toString().includes(keyword) ); } selectedSupplier(trigger: MatSelectChange) { this.selectedSupplierID = trigger.value; this.supplierSvc.getSupplierDR(this.selectedSupplierID).subscribe((response: any) => { const splitted = response.split(":", 4); this.deliveryReceiptForm.get('Bank')?.patchValue(splitted[0]); this.deliveryReceiptForm.get('AccountName')?.patchValue(splitted[1]); this.deliveryReceiptForm.get('AccountNumber')?.patchValue(splitted[2]); this.deliveryReceiptForm.get('Branch')?.patchValue(splitted[3]); if (this.deliveryReceiptForm.get('AccountName')?.value === this.dbmRequired) { this.APRDisplayed = true; this.setFieldValidators([ 'purchaseRequestNumber', 'purchaseRequestDate', 'drNumFrSupplier', 'drDate', 'aprNum', 'aprDate' ], true); this.deliveryReceiptForm.get('purchaseOrderDate')?.setValue('0001-01-01'); this.deliveryReceiptForm.get('saleInvoiceDate')?.setValue('0001-01-01'); this.deliveryReceiptForm.get('aprDate')?.reset(); } else { this.APRDisplayed = false; this.setFieldValidators([ 'purchaseOrderNumber', 'purchaseOrderDate', 'purchaseRequestNumber', 'purchaseRequestDate', 'saleInvoiceDate', 'saleInvoiceNumber', 'drNumFrSupplier', 'drDate' ], true); this.deliveryReceiptForm.get('aprDate')?.setValue('0001-01-01'); } }); } // 复用的表单验证器设置方法 private setFieldValidators(controlNames: string[], required: boolean): void { controlNames.forEach(name => { const control = this.deliveryReceiptForm.get(name); if (control) { required ? control.addValidators(Validators.required) : control.clearValidators(); control.updateValueAndValidity(); } }); } }
关键说明
- 搜索交互:通过双向绑定
searchKeyword和输入事件触发过滤,实现实时搜索 - 过滤逻辑:统一转为小写避免大小写敏感,支持扩展多个搜索字段(如供应商ID)
- 数据初始化:从服务获取动态数据后同步初始化过滤数组,保证初始状态显示全量数据
- 代码优化:提取验证器设置为复用方法,简化分支逻辑
内容的提问来源于stack exchange,提问作者Help please
相关产品推荐
相关产品推荐

