#javascript #angular #typescript #angular-reactive-forms #angular-forms
Вопрос:
Пытаюсь добавить проверку хотя бы для выбора минимум одного элемента mat-select multipe option
. В настоящее время отображается сообщение об ошибке при загрузке страницы, пока пользователь не выберет один элемент из опции выбора, который работает нормально.
ожидание:
Когда я выбираю all или single select, сообщение об ошибке должно исчезнуть. (ожидается и работает нормально).
Но что происходит:
Требуемое сообщение об ошибке не отображается, когда я отменяю выбор выбранного отдельного элемента.
Не знаю, что я делаю не так.
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'}
];
когда я делаю консоль.войдите this.trainerForm.value
в систему, я вижу skillList: ['0']
Комментарии:
1. Не могли бы вы поделиться своим сообщением об ошибке?
2. ДА. Я уже обновил свой SO, @Batajus, который вы можете использовать под
mat-select
3. Не уверен, что это проблема, но кое-что я видел. Когда вы инициализировали свою форму в файле TS, это
selectedSkills =['', Validators.required, Validators.minLength(1)]
, вероятно, должно бытьselectedSkills: ['', Validators.required, Validators.minLength(1)]
с a:
вместо=
.4. @JasonWhite это не проблема. на самом деле это моя опечатка. см. Обновленный so. Спасибо
Ответ №1:
Проблемы и проблемы
Проблема 1:
Существует ошибка опечатки для дополнительного интервала trainerForm.controls['selectedSkills ']
.
<span class="text-danger" *ngIf="trainerForm.controls['selectedSkills '].invalid ">This field is required</span>
Проблема 2:
Если для элементов управления формы требуется несколько Validators
, вы должны сгруппировать их с помощью массива.
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
(return string
) и deviceId
не существует в Object
for skillLists
. Я предполагаю, что вы используете 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] }
Решение
- Для
<mat-option>
сгенерированного с*ngFor
помощью, установите[value]="{ skillId: i.skillId }"
для возврата выбранного значения какobject
. - Добавьте
compareWith
для вашего<mat-select>
. Цель сравненияthis.trainerForm.controls.selectedSkills
с[value]="{ skillId: i.skillId }"
для проверки / снятия флажков с параметров при выборе / отмене выбора всех.
<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
в массив[]
, как указано в выпуске 2. pickAll()
patchValue
дляthis.trainerForm.controls.selectedSkills
as{ skillId: item.skillId }
Object
.onSubmit()
прежде чем передавать значение формы в API, убедитесь, что вы фильтруетеskillSets
значение{ skillId: item.skillId }
Object
только с помощью.compareFn
предназначен для сравнения выбранногоskillSets
значения с каждым<mat-option>
значением. Следовательно, при выборе всех<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 amp;amp; obj2 ? obj1.skillId === obj2.skillId : obj1 === obj2;
}
Комментарии:
1. Это потрясающе. то, как вы объяснили ошибку и реализацию, очень хорошо. это так чисто. следовательно, принимая это. Спасибо, приятель 🙂 @Ен Шун