Angular Material Chips字段无法随表单提交问题求助
问题:Angular Material Chips字段无法随表单提交
问题描述
我搭建了一个表单,所有字段均可正常提交,但用于填写Technologies的Angular Material Chips(类似其他框架的标签组件)字段无法随表单提交。
HTML代码
<!--MAIN CONTAINER--> <div class="container"> <div class="row"> <div class="col"> <!--RESUME FORM--> <mat-card class=""> <mat-card-content> <form #resumeForm="ngForm" (ngSubmit)="submit(resumeForm)" class="m-3"> <mat-form-field> <mat-label>Full Name</mat-label> <input matInput type="text" [(ngModel)]="resume.fullname" name="fullname" disabled="true"> </mat-form-field> <mat-form-field> <mat-label>Current Role</mat-label> <input matInput type="text" [(ngModel)]="resume.currentRole" name="currentRole"> </mat-form-field> <mat-form-field> <mat-label>Email</mat-label> <input matInput type="text" [(ngModel)]="resume.email" name="email" disabled="true"> </mat-form-field> <mat-form-field> <mat-label>Description</mat-label> <textarea matInput [(ngModel)]="resume.description" name="description"></textarea> </mat-form-field> <!--TECHNOLOGIES FIELD--> <mat-form-field> <mat-label>Technologies</mat-label> <mat-chip-grid #chipGridTech> <mat-chip-row *ngFor="let tech of techs" (removed)="removeTech(tech)"> {{ tech }} <button matChipRemove> <mat-icon>cancel</mat-icon> </button> </mat-chip-row> </mat-chip-grid> <input #techInput matInput type="text" [(ngModel)]="resume.technologies" placeholder="add new technology..." [formControl]="techControl" [matAutocomplete]="autoComplete" [matChipInputFor]="chipGridTech" [matChipInputSeparatorKeyCodes]="separatorKeysCodesTech" (matChipInputTokenEnd)="addTech($event)" name="technologies" /> <mat-autocomplete #autoComplete (optionSelected)="selectTech($event)"> <mat-option *ngFor="let tech of filteredTechs | async"> {{ tech }} </mat-option> </mat-autocomplete> </mat-form-field> <!--CERTIFICATIONS FIELD--> <mat-form-field> <mat-label>Certifications</mat-label> <input matInput type="text" [(ngModel)]="resume.certifications" name="certifications"> </mat-form-field> <!--WORK EXPERIENCE FIELD--> <mat-form-field> <mat-label>Work Experience</mat-label> <input matInput type="text" [(ngModel)]="resume.workExperience" name="workExperience"> </mat-form-field> <mat-form-field> <mat-label>Education</mat-label> <input matInput type="text" [(ngModel)]="resume.education" name="education"> </mat-form-field> <button mat-raised-button color="primary">Submit</button> </form> </mat-card-content> </mat-card> </div> </div> </div>
提交函数
submit(resumeForm: any) { console.log(resumeForm); }
控制台日志
提交表单后,控制台打印的表单数据中无technologies字段,其余字段(如fullname、currentRole等)均正常显示。
已尝试操作
- 添加/移除
matInput属性 - 添加/移除
[(ngModel)]="resume.technologies"绑定 - 添加/移除
name="technologies"属性
警告信息
控制台出现警告:在同一个表单字段上同时使用了ngModel和formControl。Angular v6已弃用在响应式表单指令中混用ngModel输入属性与ngModelChange事件的方式,该特性将在未来版本中移除。
解决方法
核心问题有两个:一是模板驱动表单(ngModel)与响应式表单(formControl)混用导致的数据同步异常;二是Chips的展示数组techs与绑定的resume.technologies未关联,提交时无法获取标签数据。
方案1:改用纯响应式表单(推荐)
移除ngModel相关绑定,用formControl统一管理,同时同步更新resume.technologies:
- 组件类中同步标签数组与resume对象:
import { FormControl } from '@angular/forms'; import { Observable } from 'rxjs'; import { startWith, map } from 'rxjs/operators'; import { MatChipInputEvent } from '@angular/material/chips'; import { MatAutocompleteSelectedEvent } from '@angular/material/autocomplete'; techs: string[] = []; techControl = new FormControl(''); filteredTechs: Observable<string[]>; ngOnInit() { // 初始化时将resume的technologies加载到标签数组 this.techs = [...this.resume.technologies]; // 保留原有的自动补全过滤逻辑 this.filteredTechs = this.techControl.valueChanges.pipe( startWith(''), map(value => this._filter(value || '')) ); } addTech(event: MatChipInputEvent) { const value = (event.value || '').trim(); if (value) { this.techs.push(value); // 同步更新resume的technologies字段 this.resume.technologies = [...this.techs]; } event.chipInput!.clear(); this.techControl.setValue(''); } removeTech(tech: string) { const index = this.techs.indexOf(tech); if (index >= 0) { this.techs.splice(index, 1); this.resume.technologies = [...this.techs]; } } selectTech(event: MatAutocompleteSelectedEvent) { const value = event.option.viewValue; if (!this.techs.includes(value)) { this.techs.push(value); this.resume.technologies = [...this.techs]; } this.techControl.setValue(''); } private _filter(value: string): string[] { // 保留原有的过滤逻辑 const filterValue = value.toLowerCase(); return this.allTechs.filter(tech => tech.toLowerCase().includes(filterValue)); }
- 修改HTML中的input,移除ngModel和name属性:
<input #techInput matInput type="text" placeholder="add new technology..." [formControl]="techControl" [matAutocomplete]="autoComplete" [matChipInputFor]="chipGridTech" [matChipInputSeparatorKeyCodes]="separatorKeysCodesTech" (matChipInputTokenEnd)="addTech($event)" />
- 提交时直接使用resume对象:
submit() { console.log(this.resume); // 直接提交this.resume即可获取完整数据 }
方案2:改用纯模板驱动表单
移除formControl绑定,统一用ngModel管理,同时让标签展示数组直接引用resume.technologies:
- 组件类中修改标签操作逻辑:
addTech(event: MatChipInputEvent) { const value = (event.value || '').trim(); if (value) { this.resume.technologies.push(value); } event.chipInput!.clear(); } removeTech(tech: string) { const index = this.resume.technologies.indexOf(tech); if (index >= 0) { this.resume.technologies.splice(index, 1); } } selectTech(event: MatAutocompleteSelectedEvent) { const value = event.option.viewValue; if (!this.resume.technologies.includes(value)) { this.resume.technologies.push(value); } }
- 修改HTML中的Chips和input:
<!-- 修改Chips的遍历源 --> <mat-chip-row *ngFor="let tech of resume.technologies" (removed)="removeTech(tech)"> {{ tech }} <button matChipRemove> <mat-icon>cancel</mat-icon> </button> </mat-chip-row> <!-- 移除formControl属性 --> <input #techInput matInput type="text" [(ngModel)]="resume.technologies" placeholder="add new technology..." [matAutocomplete]="autoComplete" [matChipInputFor]="chipGridTech" [matChipInputSeparatorKeyCodes]="separatorKeysCodesTech" (matChipInputTokenEnd)="addTech($event)" name="technologies" />
内容的提问来源于stack exchange,提问作者Arturo Lozano
相关产品推荐
相关产品推荐

