尝试添加验证至少选择最小一个项目来自mat-select multipe option
。目前在页面加载时显示错误信息,直到用户从选择选项中选择一个项目,这是正常工作的。
期望:
当我选择全部或单个选择时,错误信息应该消失。(预期和工作良好)。
但是发生了什么:
当我取消选中单个项目时,没有显示所需的错误信息。
我不知道我做错了什么。
skillForm.component.ts
skillList = [
{ skillId: '0', skillName: 'JS' },
{ skillId: '1', skillName: 'TS' },
{ skillId: '2', skillName: 'JAVA' },
{ skillId: '3', skillName: '.Net' },
];
@ViewChild('pickAllCourse') private pickAllCourse: MatOption;
trainerForm = FormGroup;
constructor(public formBuilder: FormBuilder) { }
this.trainerForm = this.formBuilder.group({
selectedSkills :['', Validators.required, Validators.minLength(1)]
})
pickAll(): void {
if(this.pickAllCourse.selected) {
this.trainerForm.controls.selectedSkills.patchValue([...this.skillList.map((item) => item.deviceId), 0]);
} else {
this.trainerForm.controls.selectedSkills.patchValue([]);
}
}
selectOneItem(all): any {
if (this.pickAllCourse.selected) {
this.pickAllCourse.deselect();
return false;
}
if (this.trainerForm.controls.selectedSkills.value.length === this.skillList.length) {
this.pickAllCourse.select();
}
}
onSubmit(): void{
console.log('form value', this.trainerForm.value)
//
}
skillForm.component.html
<mat-form-field class="selectedSkills">
<mat-select multiple ngDefaultControl formControlName="selectedSkills"
placeholder="Select Device Type">
<mat-option #pickAllCourse (click)="pickAll()" [value]="0">All</mat-option>
<mat-option *ngFor="let i of skillList" [value]="i.deviceId"
(click)="selectOneItem(pickAllCourse.viewValue)">{{ i.skillName }}
</mat-option>
</mat-select>
<span class="text-danger" *ngIf="trainerForm.controls['selectedSkills '].invalid ">This field is required</span>
</mat-form-field>
另外,我需要帮助如何构建对象像下面当提交表单后端。
skillList: [
{skillId: '0'},
{skillId: '1'}
];
当我执行console.logthis.trainerForm.value
时,我看到的是skillList: ['0']
Issue(s) &关注(s)
问题1:
trainerForm.controls['selectedSkills ']
的额外间距有打字错误。
<span class="text-danger" *ngIf="trainerForm.controls['selectedSkills '].invalid ">This field is required</span>
问题2:
如果表单控件需要多个Validators
,您应该将它们与Array分组。.
this.trainerForm = this.formBuilder.group({
selectedSkills :['', Validators.required, Validators.minLength(1)]
})
更改为:
this.trainerForm = this.formBuilder.group({
selectedSkills :['', [Validators.required, Validators.minLength(1)]]
})
关注1
从HTML和Typescript部分,selectedSkills
将返回number
的数组,但不是Object
的数组。当您使用item.deviceId
(返回string
)时,deviceId
不存在于skillLists
的Object
中。我假设您使用的是item.skillId
。
pickAll(): void {
if(this.pickAllCourse.selected) {
this.trainerForm.controls.selectedSkills.patchValue([...this.skillList.map((item) => item.deviceId), 0]);
} else {
this.trainerForm.controls.selectedSkills.patchValue([]);
}
}
<mat-option *ngFor="let i of skillList" [value]="i.deviceId"
(click)="selectOneItem(pickAllCourse.viewValue)">{{ i.skillName }}
</mat-option>
因此,当您执行console.log(this.trainerForm.value)
时,它将显示:
{ selectedSkills: [1, 2, 3] }
解决方案- 对于由
*ngFor
生成的<mat-option>
,设置[value]="{ skillId: i.skillId }"
返回所选值为object
。 - 为
<mat-select>
添加compareWith
。用于比较this.trainerForm.controls.selectedSkills
和[value]="{ skillId: i.skillId }"
,以便在选择/取消选择All时选中/取消选中选项。
<mat-form-field class="selectedSkills">
<mat-select
multiple
ngDefaultControl
formControlName="selectedSkills"
placeholder="Select Device Type"
[compareWith]="compareFn"
>
<mat-option #pickAllCourse (click)="pickAll()" [value]="0"
>All</mat-option
>
<mat-option
*ngFor="let i of skillList"
[value]="{ skillId: i.skillId }"
(click)="selectOneItem(pickAllCourse.viewValue)"
>{{ i.skillName }}
</mat-option>
</mat-select>
<span
class="text-danger"
*ngIf="trainerForm.controls['selectedSkills'].invalid"
>This field is required</span
>
</mat-form-field>
- 在Issue 2中提到的数组
[]
中设置多个Validators
。 pickAll()
topatchValue
forthis.trainerForm.controls.selectedSkills
as{ skillId: item.skillId }
Object
.onSubmit()
在将表单值传递给API之前,请确保仅用{ skillId: item.skillId }
Object
过滤skillSets
值。compareFn
用于将选中的skillSets
值与各<mat-option>
值进行比较。因此,当选择All时,所有<mat-option>
将被选中,反之亦然(2)。
trainerForm: FormGroup;
ngOnInit() {
this.trainerForm = this.formBuilder.group({
selectedSkills: ['', [Validators.required, Validators.minLength(1)]],
});
}
pickAll(): void {
if (this.pickAllCourse.selected) {
this.trainerForm.controls.selectedSkills.patchValue([
...this.skillList.map((item) => {
return {
skillId: item.skillId
};
}),
0,
]);
} else {
this.trainerForm.controls.selectedSkills.patchValue([]);
}
}
onSubmit(): void {
console.log('form value', this.trainerForm.value);
let postFormValue: any = {
...this.trainerForm.value,
selectedSkills: this.trainerForm.value.selectedSkills.filter(
(x: any) => typeof x === 'object'
),
};
console.log(postFormValue);
}
compareFn(obj1: any, obj2: any): boolean {
return obj1 && obj2 ? obj1.skillId === obj2.skillId : obj1 === obj2;
}
*ngFor
生成的<mat-option>
,设置[value]="{ skillId: i.skillId }"
返回所选值为object
。<mat-select>
添加compareWith
。用于比较this.trainerForm.controls.selectedSkills
和[value]="{ skillId: i.skillId }"
,以便在选择/取消选择All时选中/取消选中选项。<mat-form-field class="selectedSkills">
<mat-select
multiple
ngDefaultControl
formControlName="selectedSkills"
placeholder="Select Device Type"
[compareWith]="compareFn"
>
<mat-option #pickAllCourse (click)="pickAll()" [value]="0"
>All</mat-option
>
<mat-option
*ngFor="let i of skillList"
[value]="{ skillId: i.skillId }"
(click)="selectOneItem(pickAllCourse.viewValue)"
>{{ i.skillName }}
</mat-option>
</mat-select>
<span
class="text-danger"
*ngIf="trainerForm.controls['selectedSkills'].invalid"
>This field is required</span
>
</mat-form-field>
[]
中设置多个Validators
。pickAll()
topatchValue
forthis.trainerForm.controls.selectedSkills
as{ skillId: item.skillId }
Object
.onSubmit()
在将表单值传递给API之前,请确保仅用{ skillId: item.skillId }
Object
过滤skillSets
值。compareFn
用于将选中的skillSets
值与各<mat-option>
值进行比较。因此,当选择All时,所有<mat-option>
将被选中,反之亦然(2)。trainerForm: FormGroup;
ngOnInit() {
this.trainerForm = this.formBuilder.group({
selectedSkills: ['', [Validators.required, Validators.minLength(1)]],
});
}
pickAll(): void {
if (this.pickAllCourse.selected) {
this.trainerForm.controls.selectedSkills.patchValue([
...this.skillList.map((item) => {
return {
skillId: item.skillId
};
}),
0,
]);
} else {
this.trainerForm.controls.selectedSkills.patchValue([]);
}
}
onSubmit(): void {
console.log('form value', this.trainerForm.value);
let postFormValue: any = {
...this.trainerForm.value,
selectedSkills: this.trainerForm.value.selectedSkills.filter(
(x: any) => typeof x === 'object'
),
};
console.log(postFormValue);
}
compareFn(obj1: any, obj2: any): boolean {
return obj1 && obj2 ? obj1.skillId === obj2.skillId : obj1 === obj2;
}
StackBlitz的样例解决方案