繁体   English   中英

Angular 自定义校验:确保表单组有校验错误时表单控件无效

[英]Angular custom validation: ensure form control is invalid when the form group has validation errors

我正在研究 angular 中的反应性 forms。 我已经设置了PasswordConfirm password字段,如下所示。 我正在使用自定义验证来确保Password字段与Confirm password字段匹配。 问题是,尽管在控制台日志记录中,我可以看到 forms error属性的mismatch设置为trueconfirm password字段仍然有效,因此表单仍然有效。

  1. 当表单在errors属性中设置了mismatch属性时,如何确保Confirm Password字段也无效?
  2. 如果我将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)
  }
}

我在 passwordMatchValidator 中设置了一个调试器并尝试了控制台日志记录,如下所示在此处输入图像描述

我已使用以下代码进行密码验证。

 //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 }">&nbsp? &nbsp.HINT_8_CHARACTERS</span> <br> <span [ngClass]="{'hint-error'? signUpForm.get('password'),:errors.?pattern && letterError. ''? .signUpForm;get('password');:errors.?pattern &&.letterError }">&nbsp? &nbsp. HINT_UPPER_AND_LOWER</span> <br> <span [ngClass]="{'hint-error', signUpForm:get('password').?errors.?pattern && numberError. ''; ;signUpForm?get('password'):.errors?:pattern &&.numberError }">&nbsp. &nbsp. 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM