Angular Material MatChipList - 如何在动态 FormArray 上使用它?
Posted
技术标签:
【中文标题】Angular Material MatChipList - 如何在动态 FormArray 上使用它?【英文标题】:Angular Material MatChipList - how to use it on a Dynamic FormArray? 【发布时间】:2019-04-06 04:22:36 【问题描述】:StackBlitz
这是我的 FormArray(变体):
this.productGroup = this.fb.group(
name: '',
variants: this.fb.array([
this.fb.group(
type: '',
options: ''
)
])
)
我使用MatChips
来存储一个字符串数组。这个数组需要传递给options
:
<div formArrayName="variants" *ngFor="let item of productGroup.controls['variants'].controls; let i = index;">
<div [formGroupName]="i">
<div class="row">
<mat-form-field class="col-12">
<input formControlName="type">
</mat-form-field>
</div>
<div class="row">
<mat-form-field class="col-12">
<mat-chip-list #chipList>
<mat-chip *ngFor="let opt of typesOptions" [selectable]="true"
[removable]="true" (removed)="removeOpt(opt)">
opt
<mat-icon matChipRemove>cancel</mat-icon>
</mat-chip>
<input placeholder="Conjunto de opções deste Tipo"
formControlName="options"
[matChipInputFor]="chipList"
[matChipInputSeparatorKeyCodes]="separatorKeysCodes"
[matChipInputAddOnBlur]="true"
(matChipInputTokenEnd)="addOpt($event)">
</mat-chip-list>
</mat-form-field>
</div>
</div>
<div class="row">
<a href="javascript:" (click)="addItem()"> Add Variants </a>
<a href="javascript:" (click)="removeItem(i)" *ngIf="i > 0"> Remove Variants </a>
</div>
</div>
方法如下:
// Dynamic Methods
addItem(): void
this.variantsArray = this.productGroup.get('variants') as FormArray;
this.variantsArray.push(this.fb.group(
type: '',
options: ''
));
removeItem(index: number)
this.variantsArray.removeAt(index);
// MatChip Methods
addOpt(item: number, event: MatChipInputEvent): void
const input = event.input;
const value = event.value;
// Add our fruit
if ((value || '').trim())
this.typesOptions.push(value.trim());
// Reset the input value
if (input)
input.value = '';
removeOpt(opt: string): void
const index = this.typesOptions.indexOf(opt);
if (index >= 0)
this.typesOptions.splice(index, 1);
我已成功将动态字段添加到我的variants
formArray。但是 MatChipList
对于每个动态字段都是相同的。我还需要使MatChipList
动态化。有没有办法做到这一点?比如更改<mat-chip-list #chipList+i>
或类似的东西。
编辑:StackBlitz
【问题讨论】:
【参考方案1】:我不确定 dom 引用变量 #chiplist 是否存在问题。看起来 matChipList 由 typesOptions 数组支持,但您只有一个数组。因此,每次添加 matChipList 组件时,它仍然由与所有其他组件相同的数组支持。你需要有一个typesOptions数组,一个数组数组。然后,当您添加项目时,您还将一个新的子数组推送到 typesOptions(并且类似地为 removeItem 删除一个)。
我没有编写代码,只是查看代码的建议。
编辑 - 根据 James 的 stackblitz 编写解决方案。
https://stackblitz.com/edit/angular-3od6rd-jkidxf
注意我没有详细研究删除变体是如何组合在一起的,理想情况下,我可能想使用键/值对来跟踪变体选项,使用 dom 输入元素 id 作为键(在MatChipInputEvent),而不是依赖于外部循环索引。
stackblitz 中的一些代码:
export class ChipsOverviewExample
productGroup: FormGroup;
variantsArray: FormArray;
typesOptionsArray: string[][] = [];
readonly separatorKeysCodes: number[] = [ENTER, COMMA];
constructor(private fb: FormBuilder)
ngOnInit()
this.productGroup = this.fb.group(
name: '',
variants: this.fb.array([
this.fb.group(
type: '',
options: ''
)
]),
);
this.typesOptionsArray.push([]);
saveProduct(form: FormGroup)
console.log(form);
// Add new item to FormArray
addItem(): void
this.variantsArray = this.productGroup.get('variants') as FormArray;
this.variantsArray.push(this.fb.group(
type: '',
options: ''
));
this.typesOptionsArray.push([]);
removeItem(index: number)
this.variantsArray.removeAt(index);
addOpt(event: MatChipInputEvent, index: number): void
const input = event.input;
const value = event.value;
// Add our fruit
if ((value || '').trim())
this.typesOptionsArray[index].push(value.trim());
// Reset the input value
if (input)
input.value = '';
removeOpt(opt: string, index: number): void
const optIndex = this.typesOptionsArray[index].indexOf(opt);
if (optIndex >= 0)
this.typesOptionsArray[index].splice(optIndex, 1);
【讨论】:
this.typesOptions.push(value.trim()); this.typesOptionsArray.push(this.typesOptions);
如何使用这个数组来停止重复值?
James 如果您提出了一个有效的 StackBlitz 来说明问题,您应该很快就能得到有效的答案。也许 fork Angular 示例之一,stackblitz.com/angular/…【参考方案2】:
尝试将formGroup作为一个新组件并输入formGroup(不是formGroupName)。
<div formArrayName="variants" *ngFor="let item of productGroup.controls['variants'].controls; let i = index;">
<variant [varientGroup]="item"><varient>
<div class="row">
<a href="javascript:" (click)="addItem()"> Add Variants </a>
<a href="javascript:" (click)="removeItem(i)" *ngIf="i > 0"> Remove Variants </a>
</div>
</div>
各种组件.html
<div [formGroup]="varientGroup">
<div class="row">
<mat-form-field class="col-12">
<input formControlName="type">
</mat-form-field>
</div>
<div class="row">
<mat-form-field class="col-12">
<mat-chip-list #chipList>
<mat-chip *ngFor="let opt of typesOptions" [selectable]="true"
[removable]="true" (removed)="removeOpt(opt)">
opt
<mat-icon matChipRemove>cancel</mat-icon>
</mat-chip>
<input placeholder="Conjunto de opções deste Tipo"
[matChipInputFor]="chipList"
[matChipInputSeparatorKeyCodes]="separatorKeysCodes"
[matChipInputAddOnBlur]="true"
(matChipInputTokenEnd)="addOpt($event)">
</mat-chip-list>
</mat-form-field>
</div>
</div>
在varient.component.ts中
@Input()varientGroup: FormGroup
【讨论】:
这是最干净的方法。谢谢!以上是关于Angular Material MatChipList - 如何在动态 FormArray 上使用它?的主要内容,如果未能解决你的问题,请参考以下文章
AngularCLI 和 Angular Material(原理图)错误:无法解析集合“@angular/material”
Angular2 Material:Angular 材质输入的自定义验证