[英]Angular 2+ material mat-chip-list formArray validation
How do I validate that a mat-chip
has been added to the mat-chip-list
.如何验证
mat-chip
已添加到mat-chip-list
。 I am using ReactiveForms.我正在使用 ReactiveForms。 I have tried with the
required
validator.我已尝试使用
required
验证器。
The value can be a list of names, so I need to make sure that there is atleast 1 name in my list of names before I can submit the form.该值可以是姓名列表,因此在提交表单之前,我需要确保姓名列表中至少有 1 个姓名。 If the list is empty then
mat-error
should display the error message.如果列表为空,则
mat-error
应显示错误消息。 Using the required
validator makes the form invalid, regardless of adding names to the list.无论向列表中添加名称,使用
required
验证器都会使表单无效。
EDIT: Reactive Forms编辑:反应形式
I have tried to make a custom validator, and I am now using Reactive Forms instead of Template driven forms, but I cannot get it to work.我试图制作一个自定义验证器,我现在使用的是反应式表单而不是模板驱动的表单,但我无法让它工作。 I have edited the below code to reflect my changes and I have created this https://stackblitz.com/edit/angular-4d5vfj
我编辑了以下代码以反映我的更改,并创建了此https://stackblitz.com/edit/angular-4d5vfj
HTML HTML
<form [formGroup]="myForm">
<mat-form-field class="example-chip-list">
<mat-chip-list #chipList formArrayName="names">
<mat-chip *ngFor="let name of myForm.get('names').controls; let i=index;"
[formGroupName]="i"
[selectable]="selectable"
[removable]="removable"
(removed)="remove(myForm, i)">
<mat-icon matChipRemove *ngIf="removable">cancel</mat-icon>
</mat-chip>
<input placeholder="Names"
[matChipInputFor]="chipList"
[matChipInputSeparatorKeyCodes]="separatorKeysCodes"
[matChipInputAddOnBlur]="addOnBlur"
(matChipInputTokenEnd)="add($event, asset)">
</mat-chip-list>
<mat-error>Atleast 1 name need to be added</mat-error>
</mat-form-field>
</form>
TS TS
import {COMMA, ENTER} from '@angular/cdk/keycodes';
import {Component} from '@angular/core';
import {FormGroup, FormControl, FormBuilder, FormArray} from '@angular/forms';
import {MatChipInputEvent} from '@angular/material';
@Component({
selector: 'chip-list-validation-example',
templateUrl: 'chip-list-validation-example.html',
styleUrls: ['chip-list-validation-example.css'],
})
export class ChipListValidationExample {
public myForm: FormGroup;
// name chips
visible = true;
selectable = true;
removable = true;
addOnBlur = true;
readonly separatorKeysCodes: number[] = [ENTER, COMMA];
// data
data = {
names: ['name1', 'name2']
}
constructor(private fb: FormBuilder) {
this.myForm = this.fb.group({
names: this.fb.array(this.data.names, this.validateArrayNotEmpty)
});
}
initName(name: string): FormControl {
return this.fb.control(name);
}
validateArrayNotEmpty(c: FormControl) {
if (c.value && c.value.length === 0) {
return {
validateArrayNotEmpty: { valid: false }
};
}
return null;
}
add(event: MatChipInputEvent, form: FormGroup): void {
const input = event.input;
const value = event.value;
// Add name
if ((value || '').trim()) {
const control = <FormArray>form.get('names');
control.push(this.initName(value.trim()));
console.log(control);
}
// Reset the input value
if (input) {
input.value = '';
}
}
remove(form, index) {
console.log(form);
form.get('names').removeAt(index);
}
}
The problem is that the chipList's errorState
isn't set to true
when the chipList's FormArray
status is INVALID
.问题是当chipList 的
FormArray
状态为INVALID
时,chipList 的errorState
未设置为true
。
I'm facing the same problem and don't know why this isn't working out of the box or how this can be achieved implicitly with the chipList's form being a FormArray
.我面临着同样的问题,不知道为什么这不是开箱即用的,或者如何通过 ChipList 的形式作为
FormArray
隐式实现这FormArray
。
As a workaround you can listen to status changes from the FormArray
and set the chipList's errorState
manually:作为一种解决方法,您可以从
FormArray
监听状态更改并手动设置chipList的errorState
:
@ViewChild('chipList') chipList: MatChipList;
ngOnInit() {
this.myForm.get('names').statusChanges.subscribe(
status => this.chipList.errorState = status === 'INVALID'
);
}
https://stackblitz.com/edit/angular-4d5vfj-gywxjz https://stackblitz.com/edit/angular-4d5vfj-gywxjz
Unfortunately, it's not possible to use any of Angular's predefined validators because they are not designed to work with arrays.不幸的是,不能使用任何 Angular 的预定义验证器,因为它们不是为处理数组而设计的。 I manage to do it with the help of this article:
在这篇文章的帮助下,我设法做到了:
https://www.dev6.com/Angular_Material_Chips_with_Reactive_Forms_and_Custom_Validation https://www.dev6.com/Angular_Material_Chips_with_Reactive_Forms_and_Custom_Validation
To be able to get the validation working on a mat-chip-list
we have to bind both the mat-input
and mat-chip-list
with same FormControl
like below为了能够在
mat-chip-list
上进行验证,我们必须使用相同的FormControl
绑定mat-input
和mat-chip-list
,如下所示
Working Stackblitz link here 在这里工作 Stackblitz 链接
<form [formGroup]='group'> <mat-form-field class="example-chip-list"> <mat-chip-list #chipList required formControlName="newFruit"> <mat-chip *ngFor="let fruit of fruits" (removed)="remove(fruit)"> {{fruit.name}} <mat-icon matChipRemove>cancel</mat-icon> </mat-chip> <input placeholder="New fruit..." formControlName="newFruit" [matChipInputFor]="chipList" [matChipInputSeparatorKeyCodes]="separatorKeysCodes" [matChipInputAddOnBlur]="addOnBlur" (matChipInputTokenEnd)="add($event)" required> </mat-chip-list> <!-- add mat-error --> <mat-error *ngIf="group.controls.newFruit.hasError('required')">required!</mat-error> </mat-form-field> </form>
As demonstrated by this example by mmalerba , you can use two separate form controls: one for the mat-chip-list (this one should be the one with the required flag), and a different one for the input.正如mmalerba的这个示例所示,您可以使用两个单独的表单控件:一个用于 mat-chip-list(这个应该是具有所需标志的那个),另一个用于输入。 Interestingly, you'll have to manually set the values of both on the addEvent:
有趣的是,您必须在 addEvent 上手动设置两者的值:
<!-- ... -->
<mat-chip-list #chipList formControlName="names" required>
<!-- ... -->
<input placeholder="Names"
[formControlName]="name"
[matChipInputFor]="chipList"
[matChipInputSeparatorKeyCodes]="separatorKeysCodes"
[matChipInputAddOnBlur]="addOnBlur"
(matChipInputTokenEnd)="add($event, asset)">
</mat-chip-list>
<!-- ... -->
import {Validators} from '@angular/forms';
# ...
constructor(private fb: FormBuilder) {
this.myForm = this.fb.group({
names: [this.data.names, Validators.required],
name: ['']
});
}
# ...
add(event: MatChipInputEvent, form: FormGroup): void {
const input = event.input;
const value = event.value;
// Add name
if ((value || '').trim()) {
const control = <FormArray>form.get('names');
control.push(this.initName(value.trim()));
console.log(control);
}
// Reset the input value
if (input) {
input.value = '';
}
// update form control (necessary for correct validation)
this.myForm.controls.name.setValue(null);
this.myForm.controls.names.setValue(this.data.names);
}
# ...
}
Here's their stackblitz example这是他们的stackblitz 示例
For somebody is facing with this problem.因为有人正面临这个问题。 After many hours, I have found the root cause of the issue and the solution for it as is:
几个小时后,我找到了问题的根本原因和解决方案:
At function add, remove, select of chiplist, you need to use function setValue in reactive form to make the validation work.在chiplist的add、remove、select函数中,需要使用reactive形式的setValue函数来进行校验。
For example:例如:
this.form.get('names').value.push('abc');
this.form.get('names').setValue(this.form.get('names').value); // => this line of code will make the validation work
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.