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

求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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.26 08:38:42