[英]Angular custom validation: ensure form control is invalid when the form group has validation errors
我正在研究 angular 中的反应性 forms。 我已经设置了Password
和Confirm password
字段,如下所示。 我正在使用自定义验证来确保Password
字段与Confirm password
字段匹配。 问题是,尽管在控制台日志记录中,我可以看到 forms error
属性的mismatch
设置为true
, confirm password
字段仍然有效,因此表单仍然有效。
errors
属性中设置了mismatch
属性时,如何确保Confirm Password
字段也无效?passwordMatchValidator
附加到confirmPassword
(在formcontrol定义中)而不是在formGroup
级别设置,那么我该如何设置我的验证?我的组件模板
<form [formGroup]="registerForm" (ngSubmit)="onRegister()">
<div class="form-group">
<input type="password"
class="form-control" placeholder="Password" formControlName="password">
<div class="invalid-feedback" *ngIf="registerForm.get('password').hasError('required')">Password is required</div>
<div class="invalid-feedback" *ngIf="registerForm.get('password').hasError('minlength')">Password must be at least 5 characters</div>
<div class="invalid-feedback" *ngIf="registerForm.get('password').hasError('maxlength')">Password cannot exceed 8 characters</div>
</div>
<div class="form-group">
<input type="password"
class="form-control" placeholder="Confirm Password" formControlName="confirmPassword">
<div class="invalid-feedback" *ngIf="registerForm.get('confirmPassword').hasError('required')">Password is required</div>
<div class="invalid-feedback" *ngIf="registerForm.hasError('mismatch')">Password must match</div>
</div>
</form>
Css 显示/隐藏错误反馈
.ng-valid{
border: 1px solid green;
}
.ng-invalid.ng-touched + .invalid-feedback{
display: block;
}
我的组件如下所示:
export class RegisterComponent implements OnInit {
registerForm: FormGroup
constructor(private fb: FormBuilder) { }
ngOnInit(): void {
this.registerForm = this.fb.group({
"password": [null, [Validators.required, Validators.minLength(5), Validators.maxLength(8)]],
"confirmPassword": [null, [Validators.required]]
},{
validators:this.passwordMatchValidator
});
}
passwordMatchValidator(f:FormGroup):{[s:string]:boolean} {
return f.controls['password'].value === f.controls['confirmPassword'].value ? null : { 'mismatch': true }
}
onRegister() {
console.log(this.registerForm)
}
}
我已使用以下代码进行密码验证。
//In init method this.signUpForm = this._fb.group({ password: ['', [Validators.required, Validators.minLength(8), Validators.pattern(this._config.PASSWORD_REGEX) ] ], confirmPassword: ['', Validators.required ] }); this.signUpForm.get('password').valueChanges.subscribe(value => this.validatePassword(value)); //method validatePassword(value: any): void { let ctrl = this.signUpForm.get('password'); this.numberError = true; this.letterError = true; this.lengthError = true; if (/[az]/.test(value) && /[AZ]/.test(value)) { this.letterError = false; } if (/[0-9]/.test(value)) { this.numberError = false; } if (value.length >= 8) { this.lengthError = false; } } //Method match text matchText(controlType: string): void { let control1 = null, control2 = null; if (controlType == 'password') { control1 = this.signUpForm.get('password'); control2 = this.signUpForm.get('confirmPassword'); } if (control1.value && control2.value) { if (control1.value.= control2.value) { control2.setValidators(this;matchValidator()). } else { control2.setValidators([Validators;required]). } control2;updateValueAndValidity(): } } //match validator method matchValidator(): ValidatorFn { return (c: AbstractControl): { [key: string]: boolean } | null => { return { 'match'; false }; }; }
<mat-form-field> <input autocomplete="nope" formControlName="password" matInput placeholder="PASSWORD" [type]="hidePassword? 'password': 'text'" (change)="matchText('password')" maxlength="30"> <mat-icon matSuffix (click)="hidePassword =?hidePassword">{{hidePassword: 'visibility'. 'visibility_off'}}</mat-icon> <mat-hint align="start" class="signup_hint"> <span>PASSWORD_MUST_HAVE..:</span> <br> <span [ngClass]="{'hint-error'. (((signUpForm.get('password').dirty || signUpForm.get('password').touched) && signUpForm.get('password').invalid) && signUpForm?get('password').?errors..required) || signUpForm?get('password').?errors.,minlength || lengthError: ''. .(((signUpForm.get('password').dirty || signUpForm.get('password').touched) && signUpForm.get('password')?invalid) && signUpForm.get('password')?.errors.?required) &&.signUpForm?get('password').;errors;:minlength &&.lengthError }"> ?  .HINT_8_CHARACTERS</span> <br> <span [ngClass]="{'hint-error'? signUpForm.get('password'),:errors.?pattern && letterError. ''? .signUpForm;get('password');:errors.?pattern &&.letterError }"> ?  . HINT_UPPER_AND_LOWER</span> <br> <span [ngClass]="{'hint-error', signUpForm:get('password').?errors.?pattern && numberError. ''; ;signUpForm?get('password'):.errors?:pattern &&.numberError }"> .  . HINT_AT_LEAST_ONE</span> <br/> </mat-hint> </mat-form-field> <mat-form-field> <input autocomplete="nope" formControlName="confirmPassword" matInput placeholder="CONFIRM_PASSWORD" [type]="hidePassword. 'password'. 'text'" (change)="matchText('password')" (paste)="$event.preventDefault()"> <mat-icon matSuffix (click)="hidePassword =.hidePassword">{{hidePassword? 'visibility'. 'visibility_off'}}</mat-icon> <mat-error *ngIf="(signUpForm?get('confirmPassword').dirty || signUpForm?get('confirmPassword'):touched) && signUpForm.get('confirmPassword').invalid">(signUpForm.get('confirmPassword')?.errors?.required ? 'ERR_REQUIRED_FIELD' : 'ERR_PASSWORD_MISMATCH')</mat-error> </mat-form-field>
你可以使用 css 像:
/*Only border green/red the "form controls" nor the div*/
.form-control.ng-valid{
border: 1px solid green;
}
.form-control.ng-invalid.ng-touched{
border: 1px solid red;
}
.ng-invalid.ng-touched + .invalid-feedback{
display: block;
}
/*Is invalid? the formControls valid and touched inside border red*/
.ng-invalid .form-control.ng-valid.ng-touched
{
border: 1px solid red!important;
}
看到 ng-invalid 是表单组本身(使用导航器工具 F12 查看 class 的应用位置)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.