求Angular Material 2 Autocomplete实现:无匹配时支持添加新项(优先Formly)
嘿,我刚好做过类似的需求,给你两种方案参考——先从常规的Angular Material Autocomplete实现说起,再给你Formly版本的代码,都包含了无匹配时添加选项的功能~
常规Angular Material Autocomplete实现
这个方案直接用Angular Material原生组件,逻辑清晰,容易调试。
1. 组件模板(HTML)
<form [formGroup]="myForm"> <mat-form-field appearance="fill"> <input type="text" matInput formControlName="selectedOption" [matAutocomplete]="auto"> <mat-autocomplete #auto="matAutocomplete"> <!-- 显示过滤后的匹配选项 --> <mat-option *ngFor="let option of filteredOptions | async" [value]="option"> {{ option }} </mat-option> <!-- 无匹配且输入非空时,显示添加选项 --> <mat-option *ngIf="(filteredOptions | async)?.length === 0 && myForm.get('selectedOption')?.value.trim() !== ''" (click)="addNewOption()"> 添加 "{{ myForm.get('selectedOption')?.value }}" </mat-option> </mat-autocomplete> </mat-form-field> </form>
2. 组件逻辑(TS)
import { Component, OnInit } from '@angular/core'; import { FormBuilder, FormGroup } from '@angular/forms'; import { Observable } from 'rxjs'; import { map, startWith } from 'rxjs/operators'; @Component({ selector: 'app-autocomplete-add', templateUrl: './autocomplete-add.component.html', styleUrls: ['./autocomplete-add.component.css'] }) export class AutocompleteAddComponent implements OnInit { myForm!: FormGroup; originalOptions: string[] = ['Angular', 'React', 'Vue']; filteredOptions!: Observable<string[]>; constructor(private fb: FormBuilder) {} ngOnInit(): void { this.myForm = this.fb.group({ selectedOption: [''] }); // 监听输入变化,实时过滤选项 this.filteredOptions = this.myForm.get('selectedOption')!.valueChanges.pipe( startWith(''), map(value => this.filterOptions(value)) ); } // 过滤逻辑:返回包含输入值的选项(不区分大小写) private filterOptions(value: string): string[] { const filterValue = value.toLowerCase(); return this.originalOptions.filter(option => option.toLowerCase().includes(filterValue) ); } // 添加新选项到列表 addNewOption(): void { const newOption = this.myForm.get('selectedOption')?.value.trim(); // 避免添加空值或重复选项 if (newOption && !this.originalOptions.includes(newOption)) { this.originalOptions.push(newOption); // 添加后自动选中新选项,提升用户体验 this.myForm.get('selectedOption')?.setValue(newOption); } } }
使用Angular Formly实现
如果你的项目已经在用Formly,这个方案可以无缝集成,减少冗余模板代码。
1. 组件模板(HTML)
<form [formGroup]="form" (ngSubmit)="onSubmit()"> <formly-form [form]="form" [fields]="fields" [model]="model"> </formly-form> </form>
2. 组件逻辑(TS)
import { Component } from '@angular/core'; import { FormGroup } from '@angular/forms'; import { FormlyFieldConfig } from '@ngx-formly/core'; import { Observable } from 'rxjs'; import { map, startWith } from 'rxjs/operators'; @Component({ selector: 'app-formly-autocomplete-add', templateUrl: './formly-autocomplete-add.component.html', }) export class FormlyAutocompleteAddComponent { form = new FormGroup({}); model: any = { techStack: '' }; originalOptions: string[] = ['Angular', 'React', 'Vue']; filteredOptions!: Observable<string[]>; fields: FormlyFieldConfig[] = [ { key: 'techStack', type: 'input', templateOptions: { label: '技术栈', required: true, matAutocomplete: true, options: this.filteredOptions, }, // 自定义Autocomplete模板,嵌入添加选项逻辑 template: ` <input matInput [formControl]="formControl" [matAutocomplete]="auto" [placeholder]="to.label"> <mat-autocomplete #auto="matAutocomplete"> <mat-option *ngFor="let option of to.options | async" [value]="option"> {{ option }} </mat-option> <mat-option *ngIf="(to.options | async)?.length === 0 && formControl.value.trim() !== ''" (click)="addNewOption()"> 添加 "{{ formControl.value }}" </mat-option> </mat-autocomplete> `, }, ]; constructor() { // 初始化过滤Observable this.filteredOptions = this.form.get('techStack')!.valueChanges.pipe( startWith(''), map(value => this.filterOptions(value)) ); // 同步更新字段的选项数据源 this.fields[0].templateOptions.options = this.filteredOptions; } private filterOptions(value: string): string[] { const filterValue = value.toLowerCase(); return this.originalOptions.filter(option => option.toLowerCase().includes(filterValue) ); } addNewOption(): void { const newOption = this.form.get('techStack')?.value.trim(); if (newOption && !this.originalOptions.includes(newOption)) { this.originalOptions.push(newOption); this.form.get('techStack')?.setValue(newOption); } } onSubmit(): void { if (this.form.valid) { console.log('提交值:', this.model); } } }
额外提示
- 确保项目已正确导入
MatAutocompleteModule、ReactiveFormsModule(常规方案)和@ngx-formly/material(Formly方案)。 - 如果需要将新选项持久化到后端,可以在
addNewOption方法里加入API调用逻辑,等请求成功后再更新本地选项列表。
内容的提问来源于stack exchange,提问作者Somnath Swami
相关产品推荐
相关产品推荐

