Angular响应式表单验证和数据形成问题



尝试添加验证至少选择最小一个项目来自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不存在于skillListsObject中。我假设您使用的是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] }

解决方案
  1. 对于由*ngFor生成的<mat-option>,设置[value]="{ skillId: i.skillId }"返回所选值为object
  2. <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>
  1. Issue 2中提到的数组[]中设置多个Validators
  2. pickAll()topatchValueforthis.trainerForm.controls.selectedSkillsas{ skillId: item.skillId }Object.
  3. onSubmit()在将表单值传递给API之前,请确保仅用{ skillId: item.skillId }Object过滤skillSets值。
  4. 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的样例解决方案

相关内容

  • 没有找到相关文章

最新更新