#angular #angular-validation
Вопрос:
Я реализовал проверку пароля подтверждения в Angular с помощью пользовательского валидатора. Вот пользовательский класс валидатора:
import { AbstractControl, ValidatorFn } from '@angular/forms';
export class Validation {
static match(controlName: string, checkControlName: string): ValidatorFn {
return (controls: AbstractControl) => {
const control = controls.get(controlName);
const checkControl = controls.get(checkControlName);
if (checkControl?.errors amp;amp; !checkControl.errors.matching) {
return null;
}
if (control?.value !== checkControl?.value) {
controls?.get(checkControlName)?.setErrors({ matching: true });
return { matching: true };
} else {
return null;
}
};
}
}
Я использую реактивную форму, вот как я ее создаю:
initSignupForm() {
this.signupForm = new FormGroup(
{
email: new FormControl(this.formData.email, [
Validators.required,
Validators.email,
]),
password: new FormControl(this.formData.password, [
Validators.required,
]),
passwordConfirm: new FormControl(this.formData.passwordConfirm, [
Validators.required,
]),
},
{ validators: [Validation.match('password', 'passwordConfirm')] }
);
}
И это компонент html:
<div class="card">
<kendo-card width="320px">
<h2>Regisztráció</h2>
<form [formGroup]="signupForm">
<kendo-formfield>
<kendo-textbox placeholder="E-mail cím" formControlName="email">
<ng-template kendoTextBoxPrefixTemplate>
<kendo-svg-icon [icon]="icons.user"></kendo-svg-icon>
<div id="empty-div"></div>
</ng-template>
</kendo-textbox>
<kendo-formerror *ngIf="signupForm.controls.email.errors?.required"
>Kötelező mező</kendo-formerror
>
<kendo-formerror *ngIf="signupForm.controls.email.errors?.email"
>Hibás e-mail formátum</kendo-formerror
>
</kendo-formfield>
<kendo-formfield>
<kendo-textbox
placeholder="Jelszó"
#tbxPassword
formControlName="password"
>
<ng-template kendoTextBoxPrefixTemplate>
<button
id="tbxPassword"
kendoButton
icon="eye"
(click)="togglePass()"
></button>
</ng-template>
</kendo-textbox>
<kendo-formerror>Kötelező mező</kendo-formerror>
</kendo-formfield>
<kendo-formfield>
<kendo-textbox
placeholder="Jelszó még egyszer"
#tbxRepeatPassword
formControlName="passwordConfirm"
>
<ng-template kendoTextBoxPrefixTemplate>
<button kendoButton icon="eye" (click)="togglePassRep()"></button>
</ng-template>
</kendo-textbox>
<kendo-formerror
*ngIf="signupForm.controls.passwordConfirm.errors?.required"
>Kötelező mező</kendo-formerror
>
<kendo-formerror *ngIf="signupForm.errors?.matching"
>A két jelszó nem egyezik</kendo-formerror
>
</kendo-formfield>
<button class="btn" kendoButton [primary]="true" (click)="submitForm()">
ÚJ FIÓK LÉTREHOZÁSA
</button>
<div class="link">
<span>Már van fiókod? </span>
<a href="#" (click)="backToLogin()">Jelentkezz be</a>
</div>
</form>
</kendo-card>
<lang-selector></lang-selector>
</div>
Это работает, но со следующим побочным эффектом. Например, если я введу » a «в поле пароля, а затем» b » в поле подтверждения пароля, я получу сообщение об ошибке. Хорошо. Теперь, если я изменю » b » на «a», сообщение об ошибке исчезнет, форма может быть отправлена. Хорошо. Но если я изменю первый пароль («a») на «b», сообщение об ошибке тоже исчезнет, но поле подтверждения пароля останется красным, и я не смогу отправить форму. В самой форме больше нет ошибок (я проверил это в консоли), но в самом поле все еще есть эта matching
ошибка. Почему это происходит?
Комментарии:
1. Решена ли ваша проблема?
Ответ №1:
Проблема в том, что здесь Validation.match
controls?.get(checkControlName)?.setErrors({ matching: true });
Вы вручную устанавливаете проверку checkControlName
, но она должна быть включена в FormGroup. Из-за чего каким-то образом проверка смешивается и что приводит к неожиданной проверке. Я попытался разгадать сценарий, но не смог его найти.
Чтобы решить вашу проблему.
Удалите controls?.get(checkControlName)?.setErrors({ matching: true });
то, что находится внутри if (control?.value !== checkControl?.value)
Добавьте ниже getter в component.ts: — Чтобы получить FormGroup, чтобы мы могли использовать его в нашем шаблоне для проверки.
get fg(): FormGroup {
return this.signupForm as FormGroup;
}
Изменить
<kendo-formerror *ngIf="signupForm.errors?.matching">
A két jelszó nem egyezik
</kendo-formerror>
Для
<kendo-formerror *ngIf="fg.hasError('matching')">
A két jelszó nem egyezik
</kendo-formerror>
Вот и все : Аналогичная демонстрация
Комментарии:
1. У меня тоже была подобная мысль, и я прокомментировал это
controls?.get(checkControlName)?.setErrors({ matching: true });
, когда пытался отследить проблему. Но безуспешно. Оказалось, что мне пришлось убратьkendo-formerror
тег изkendo-formfield
тега, и теперь даже с этим кодомsignupForm.errors?.matching
я получаю правильное поведение. Спасибо за вашу помощь, а также спасибо @TotallyNewb.2. Это смутило меня, когда я использовал
matching
имя, Так как ошибка была такой, как{ matching: true }
я думаю{ notMatching : true }
, будет более точной.3. Да, вы правы. Я уже исправил это.
Ответ №2:
Это связано с тем, что вы вручную устанавливаете ошибки в passwordConfirm
элементе управления, но вы проверяете наличие ошибок в самой форме, чтобы отобразить сообщение об ошибке. Поскольку значение passwordConfirm
не было изменено, список ошибок не был очищен.
Это означает, что ошибка не будет отображаться (так как вы возвращаете значение null из своего валидатора), но форма недействительна (так как в ней все еще есть ошибка passwordConfirm
).
Таким образом, вам нужно либо удалить строку, которая задает ошибки в самом элементе управления ( controls?.get(checkControlName)?.setErrors({ matching: true });
), либо убедиться, что при каждой оценке вашего валидатора вы либо добавляете, либо удаляете ошибку в массив существующих ошибок.