如何在Angular中可选地添加Material Autocomplete组件
解决Angular Material输入框可选自动完成的重复代码问题
我完全懂你的痛点——不想重复编写输入框和表单字段的代码,同时要实现可选的自动完成功能,之前尝试给mat-autocomplete加*ngIf或者把matAutocomplete设为null都触发了报错,这是因为Angular Material的matAutocomplete指令在初始化时就会尝试关联对应的Autocomplete组件实例,哪怕组件被*ngIf隐藏或者你手动设为null,都会导致找不到实例的错误。
这里有个优雅的解决方案,既能复用输入框代码,又能彻底避免报错:
方案:动态控制输入框的Autocomplete关联
我们可以通过组件类的视图查询,在不需要自动完成时手动断开输入框与Autocomplete的关联,同时用*ngIf控制Autocomplete组件的渲染:
1. 组件类代码
import { Component, ViewChild, OnInit } from '@angular/core'; import { FormControl } from '@angular/forms'; import { MatInput } from '@angular/material/input'; import { MatAutocomplete } from '@angular/material/autocomplete'; import { Observable } from 'rxjs'; import { map, startWith } from 'rxjs/operators'; @Component({ selector: 'app-autocomplete-overview', templateUrl: './autocomplete-overview-example.html', styleUrls: ['./autocomplete-overview-example.css'] }) export class AutocompleteOverviewExample implements OnInit { myControl = new FormControl(''); options: string[] = ['One', 'Two', 'Three']; filteredOptions!: Observable<string[]>; showAutocomplete = false; // 控制自动完成开关的变量 @ViewChild(MatAutocomplete) auto!: MatAutocomplete; @ViewChild(MatInput) input!: MatInput; ngOnInit() { this.filteredOptions = this.myControl.valueChanges.pipe( startWith(''), map(value => this._filter(value || '')), ); // 初始化时如果不需要自动完成,断开关联 if (!this.showAutocomplete) { this.input.autocomplete = undefined; } } private _filter(value: string): string[] { const filterValue = value.toLowerCase(); return this.options.filter(option => option.toLowerCase().includes(filterValue)); } // 切换自动完成状态的方法 toggleAutocomplete() { this.showAutocomplete = !this.showAutocomplete; // 切换时同步更新关联状态 this.input.autocomplete = this.showAutocomplete ? this.auto : undefined; } }
2. 模板代码
<form class="example-form"> <mat-form-field class="example-full-width"> <input type="text" placeholder="Pick one" matInput [formControl]="myControl" matAutocomplete="auto" > <!-- 仅当需要时才渲染自动完成组件 --> <mat-autocomplete #auto="matAutocomplete" *ngIf="showAutocomplete"> <mat-option *ngFor="let option of filteredOptions | async" [value]="option"> {{option}} </mat-option> </mat-autocomplete> </mat-form-field> </form> <button mat-button (click)="toggleAutocomplete()"> {{ showAutocomplete ? '关闭自动完成' : '开启自动完成' }} </button>
为什么这个方案可行?
- 当
showAutocomplete为false时,我们通过this.input.autocomplete = undefined手动断开了输入框与Autocomplete组件的关联,彻底避免了Angular Material找不到实例的报错。 - 输入框和表单字段代码只写一次,完全复用,满足你不想重复编写的需求。
- 切换自动完成状态时,能动态更新关联关系,保证功能正常切换。
如果你不想在组件类里写逻辑,也可以试试更简洁的模板写法(兼容性略差,部分Angular Material版本可能仍有报错):
<input type="text" placeholder="Pick one" matInput [formControl]="myControl" [matAutocomplete]="showAutocomplete ? auto : null" > <ng-container *ngIf="showAutocomplete"> <mat-autocomplete #auto="matAutocomplete"> <mat-option *ngFor="let option of filteredOptions | async" [value]="option"> {{option}} </mat-option> </mat-autocomplete> </ng-container>
内容的提问来源于stack exchange,提问作者Curtis
相关产品推荐
相关产品推荐

