我正在Angular 16中开发一个React式注册表单。
我做了一个自定义验证来检查表单字段password
和confirm_password
中的值是否匹配:
import { AbstractControl, ValidationErrors, ValidatorFn } from "@angular/forms";
export const matchpassword : ValidatorFn = (control: AbstractControl):ValidationErrors|null => {
let password = control.get('password');
let confirm_password = control.get('confirm_password');
if (password && confirm_password && password?.value != confirm_password?.value) {
return { password_match : true }
}
return null;
}
在components\registration\registration.component.ts
中,我有:
import { Component, OnInit } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { matchpassword } from "../../custom-validators/matchpassword.validator";
@Component({
selector: 'app-registration',
templateUrl: './registration.component.html',
styleUrls: ['./registration.component.scss']
})
export class RegistrationComponent implements OnInit {
public registrationForm!: FormGroup;
public isSuccess: Boolean = false;
constructor(private formBuilder: FormBuilder) { }
get form() { return this.registrationForm.controls }
public registerUser() {
if (this.registrationForm.status !== 'INVALID') {
// Show success alert
this.isSuccess = true;
// Reset form
this.registrationForm.reset();
} else {
return;
}
}
ngOnInit() {
this.registrationForm = this.formBuilder.group({
firstName: ['', [Validators.required, Validators.minLength(3)]],
lastName: ['', [Validators.required, Validators.minLength(3)]],
email: ['', [Validators.required, Validators.email]],
password: ['', [Validators.required, Validators.minLength(6), matchpassword]],
confirm_password: ['', matchpassword],
terms: ['', Validators.requiredTrue],
}, {
validators: matchpassword
});
}
}
在components\registration\registration.component.html
中,我有:
<div *ngIf="isSuccess" class="alert alert-success alert-dismissible fade show text-center">
<button type="button" class="btn-close" data-bs-dismiss="alert"></button>
Your signup was successful!
</div>
<form
[formGroup]="registrationForm"
(ngSubmit)="registerUser()"
novalidate
>
<div class="form-element mb-2">
<label for="firstName" class="form-label"> First name </label>
<input
type="text"
id="firstName"
formControlName="firstName"
class="form-control form-control-sm"
/>
<span
class="invalid-feedback"
*ngIf="form['firstName']?.touched && form['firstName'].errors?.['required']"
>The <i>First name</i> field is required</span
>
<span
class="invalid-feedback"
*ngIf="form['firstName'].touched && form['firstName'].errors?.['minlength']"
>The <i>First name</i> must be at least 3 characters long</span
>
</div>
<div class="form-element mb-2">
<label for="lastName" class="form-label"> Last name </label>
<input
type="text"
id="lastName"
formControlName="lastName"
class="form-control form-control-sm"
/>
<span
class="invalid-feedback"
*ngIf="form['lastName'].touched && form['lastName'].errors?.['required']"
>The <i>Last name</i> field is required</span
>
<span
class="invalid-feedback"
*ngIf="form['lastName'].touched && form['lastName'].errors?.['minlength']"
>The <i>Last name</i> must be at least 3 characters long</span
>
</div>
<div class="form-element mb-2">
<label for="email" class="form-label"> Email address </label>
<input
type="email"
id="email"
formControlName="email"
class="form-control form-control-sm"
/>
<span
class="invalid-feedback"
*ngIf="form['email'].touched && form['email'].errors?.['required']"
>The <i>Email</i> field is required</span
>
<span
class="invalid-feedback"
*ngIf="form['email'].touched && form['email'].errors?.['email']"
>Please provide a valid email address</span
>
</div>
<div class="form-element mb-2">
<label for="password" class="form-label"> Password </label>
<input
type="password"
id="password"
formControlName="password"
class="form-control form-control-sm"
/>
<span
class="invalid-feedback"
*ngIf="form['password'].touched && form['password'].errors?.['required']"
>The <i>Password</i> field is required</span
>
<span
class="invalid-feedback"
*ngIf="form['password'].touched && form['password'].errors?.['minlength']"
>The password must have al least 6 characters</span
>
<span
class="invalid-feedback"
*ngIf="form['password'].touched && form['password'].errors?.['passwordcomplexity']"
>The password is not complex enough</span
>
<span
class="invalid-feedback"
*ngIf="form['password'].touched && registrationForm.errors?.['password_match']
"
>The passwords do not match</span
>
</div>
<div class="form-element mb-2">
<label for="confirm_password" class="form-label">
Confirm password
</label>
<input
type="password"
id="confirm_password"
formControlName="confirm_password"
class="form-control form-control-sm"
/>
</div>
<div class="form-element mb-2">
<input
type="checkbox"
formControlName="terms"
id="terms"
class="me-1"
/>
<span class="text-terms text-muted"
>I accept the
<a href="#" class="text-success">Terms & conditions</a></span
>
<span
class="invalid-feedback terms"
*ngIf="form['terms'].dirty && form['terms'].errors?.['required']"
>You must accept our Terms & conditions</span
>
</div>
<div class="pt-2">
<button
type="submit"
class="btn btn-sm btn-success w-100"
[disabled]="!registrationForm.valid"
>
Submit
</button>
</div>
</form>
Stackblitz
有一个stackblitz,所有代码都是**HERE**
目标
如果密码不匹配,我希望错误消息“密码不匹配”显示 * 在密码字段 *,如下所示:
问题
虽然密码被视为无效(提交按钮被禁用),但错误消息不会显示:
我做错了什么?
2条答案
按热度按时间mbyulnm01#
matchpassword
验证器需要添加到表单group中,而不是添加到某个单独的控件中。向控件添加验证程序并不给予对其他控件的访问权限。在解决这个问题之后,您需要调整错误消息,以便在表单组而不是表单控件出现错误时显示:
更新stackblitz:https://stackblitz.com/edit/stackblitz-starters-wbynzu?file=src%2Fapp%2Fcomponents%2Fregistration%2Fregistration.component.ts
注意:现在有一些重叠错误消息的问题,我没有修复,因为这与问题无关
g6ll5ycj2#
如果有人会发现完整的代码,为我工作有用.
自定义验证器
custom-validators\matchpassword.validator.ts
custom-validators\passwordcomplexity.validator.ts
在
app\components\registration\registration.component.ts
中,我有:在
src\app\components\registration\registration.component.html
中,我有:为了 * 防止验证消息重叠 *,在SCSS中,我这样做是为了 * 在DOM中只显示第一条消息 *:
DEMO
stackblitz**HERE**演示。