如何根据之前的字段输入更改验证 angular
How can I change the validations based on previous field input angular
我在 angular 中有两个反应形式的字段。我需要验证第二个字段并根据选择的第一个字段选项显示错误消息。
字段一:
<label>ID proof </b><span class="asterisk">*</span></label>
<mat-form-field appearance="outline">
<mat-select name="idproofs" placeholder="IDProof name" required formControlName="idProof" class="form-control">
<mat-option *ngFor="let idproof of idproofs" [value]="idproof.value">
{{idproof.viewValue}}
</mat-option>
</mat-select>
</mat-form-field>
字段二:
<label>ID proof number </b><span class="asterisk">*</span></label>
<mat-form-field appearance="outline">
<input matInput placeholder="ID Proof Number" required formControlName="idFroofNumber" class="form-control">
<mat-error *ngIf="PGroup.controls['idProofNumber'].hasError('required')">
ID proof number is required!
</mat-error>
</mat-form-field>
Example 在第一个字段中如果我选择选项 Adhaar number 那么在第二个字段中验证必须是只有 12 位字符的数字最大长度。
如果我选择 PAN 编号,那么只有验证将是最大长度为 10 个字符的字母数字。因此,如果我也可以提供错误消息验证。我怎样才能做到这一点
编辑 添加了 ts formcontrol
this.PGroup = this._formBuilder.group({
idProof: ['', Validators.required],
idProofNumber: ['', [Validators.required,Validators.pattern(/^[\w\s]+$/)]]
});
你能提供你的ts代码吗?我看到您将 ngModel 与 formControlName 结合使用,我认为它是反应式方法与模板驱动方法的结合。
无论如何,这是我的建议。
以这种方式使用反应式方法,(仅建议,您可以根据自己的喜好了解并实施)
// attr declarations
fieldOne = new FormControl('',[]); // initial value and validators inside array
fieldTwo = new FormControl('', []); // initialValue and validators
// ngOnInit
fieldOne.valueChanges.
.pipe(
debounceTime(100), // dalay after every change to update your validations
distinctUntilChanged(), // only update validators when value change
tap(value => {
// depend on your options you can use switch here
if(value === 'Adhaar number'){
this.fieldTwo.setValidators([Validators.required,Validators.maxLength(12)]);
this.fieldTwo.updateValueAndValidity();
} else
if(value === 'PAN number'){
this.fieldTwo.setValidators([Validators.required,Validators.maxLength(10)]);
this.fieldTwo.updateValueAndValidity();
} else {
this.fieldTwo.setValidators([Validators.required]);
this.fieldTwo.updateValueAndValidity();
}
})
)
.subscribe()
根据您可能的错误更新您的html。
您也可以使用带有两个字段的 formGroup 而不是单独的 formControl,并且只需将订阅从 this.fieldOne.valueChanges 更改为 this.form.get('fieldOne').valueChanges
请记住取消订阅此订阅。我建议 https://www.npmjs.com/package/@ngneat/until-destroy
我想你可以这样做,
假设您有一个名为 AppComponent 的组件,
import { Component } from '@angular/core';
import {
FormBuilder,
FormGroup,
FormControl,
ValidationErrors,
AbstractControl,
ValidatorFn
} from '@angular/forms';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss']
})
export class AppComponent {
title = 'Whosebug-examples';
panelOpenState = false;
idproofOptions: string[] = ['Aadhar','PAN'];
idproofsForm: FormGroup;
get idproofsFormControl(): FormControl {
// debugger
return this.idproofsForm.controls['idproofs'] as FormControl;
}
get idproofsInputFormControl(): FormControl {
// debugger
return this.idproofsForm.controls['idproofsInput'] as FormControl;
}
idproofInputAadharValidation(): ValidatorFn {
return (control: AbstractControl): ValidationErrors | null => {
// debugger
const pattern = new RegExp("^[0-9]{10}$");
if (pattern.test(control.value)) {
return null;
} else {
return {
aadharError: 'Aadhar number is not correct'
};
}
};
}
idproofInputPANValidation(): ValidatorFn {
return (control: AbstractControl): ValidationErrors | null => {
// debugger
const pattern = new RegExp("^[a-zA-Z0-9]+$");
if (pattern.test(control.value)) {
return null;
} else {
return {
panError: 'PAN number is not correct'
};
}
};
}
constructor(
private fb: FormBuilder
) {
this.idproofsForm = new FormGroup(
{
idproofs: new FormControl(''),
idproofsInput: new FormControl('')
}
);
}
ngOnInit() {
this.idproofsForm.valueChanges.subscribe(
field => {
// debugger
console.log(this.idproofsForm.controls['idproofsInput']);
if (field['idproofs'] && field['idproofs'] === 'PAN') {
this.idproofsInputFormControl.clearValidators();
this.idproofsInputFormControl.setValidators(this.idproofInputPANValidation());
} else if (field['idproofs'] && field['idproofs'] === 'Aadhar') {
this.idproofsInputFormControl.clearValidators();
this.idproofsInputFormControl.setValidators(this.idproofInputAadharValidation());
}
// debugger
}
);
}
}
您的 HTML 可以看起来像这样,
<label>ID proof<span class="asterisk">*</span></label>
<mat-form-field appearance="outline">
<mat-select [formControl]="idproofsFormControl" name="idproofs" placeholder="IDProof name" required class="form-control">
<mat-option *ngFor="let idproof of idproofOptions" [value]="idproof">
{{idproof}}
</mat-option>
</mat-select>
</mat-form-field>
<br/>
<!-- {{idproofsInputFormControl|json}} -->
<label>ID proof number<span class="asterisk">*</span></label>
<mat-form-field appearance="outline">
<input matInput placeholder="ID Proof Number" required [formControl]="idproofsInputFormControl" class="form-control">
<mat-error *ngIf="idproofsInputFormControl.errors">
{{idproofsInputFormControl.errors['aadharError']}}
</mat-error>
</mat-form-field>
看下面截图中的错误
注意:我的建议是您不要使用 ngModel,反应式方法要好得多,您可能需要稍微更改此代码以满足您的要求,但我相信它应该会有帮助
我在 angular 中有两个反应形式的字段。我需要验证第二个字段并根据选择的第一个字段选项显示错误消息。
字段一:
<label>ID proof </b><span class="asterisk">*</span></label>
<mat-form-field appearance="outline">
<mat-select name="idproofs" placeholder="IDProof name" required formControlName="idProof" class="form-control">
<mat-option *ngFor="let idproof of idproofs" [value]="idproof.value">
{{idproof.viewValue}}
</mat-option>
</mat-select>
</mat-form-field>
字段二:
<label>ID proof number </b><span class="asterisk">*</span></label>
<mat-form-field appearance="outline">
<input matInput placeholder="ID Proof Number" required formControlName="idFroofNumber" class="form-control">
<mat-error *ngIf="PGroup.controls['idProofNumber'].hasError('required')">
ID proof number is required!
</mat-error>
</mat-form-field>
Example 在第一个字段中如果我选择选项 Adhaar number 那么在第二个字段中验证必须是只有 12 位字符的数字最大长度。
如果我选择 PAN 编号,那么只有验证将是最大长度为 10 个字符的字母数字。因此,如果我也可以提供错误消息验证。我怎样才能做到这一点
编辑 添加了 ts formcontrol
this.PGroup = this._formBuilder.group({
idProof: ['', Validators.required],
idProofNumber: ['', [Validators.required,Validators.pattern(/^[\w\s]+$/)]]
});
你能提供你的ts代码吗?我看到您将 ngModel 与 formControlName 结合使用,我认为它是反应式方法与模板驱动方法的结合。 无论如何,这是我的建议。 以这种方式使用反应式方法,(仅建议,您可以根据自己的喜好了解并实施)
// attr declarations
fieldOne = new FormControl('',[]); // initial value and validators inside array
fieldTwo = new FormControl('', []); // initialValue and validators
// ngOnInit
fieldOne.valueChanges.
.pipe(
debounceTime(100), // dalay after every change to update your validations
distinctUntilChanged(), // only update validators when value change
tap(value => {
// depend on your options you can use switch here
if(value === 'Adhaar number'){
this.fieldTwo.setValidators([Validators.required,Validators.maxLength(12)]);
this.fieldTwo.updateValueAndValidity();
} else
if(value === 'PAN number'){
this.fieldTwo.setValidators([Validators.required,Validators.maxLength(10)]);
this.fieldTwo.updateValueAndValidity();
} else {
this.fieldTwo.setValidators([Validators.required]);
this.fieldTwo.updateValueAndValidity();
}
})
)
.subscribe()
根据您可能的错误更新您的html。
您也可以使用带有两个字段的 formGroup 而不是单独的 formControl,并且只需将订阅从 this.fieldOne.valueChanges 更改为 this.form.get('fieldOne').valueChanges
请记住取消订阅此订阅。我建议 https://www.npmjs.com/package/@ngneat/until-destroy
我想你可以这样做,
假设您有一个名为 AppComponent 的组件,
import { Component } from '@angular/core';
import {
FormBuilder,
FormGroup,
FormControl,
ValidationErrors,
AbstractControl,
ValidatorFn
} from '@angular/forms';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss']
})
export class AppComponent {
title = 'Whosebug-examples';
panelOpenState = false;
idproofOptions: string[] = ['Aadhar','PAN'];
idproofsForm: FormGroup;
get idproofsFormControl(): FormControl {
// debugger
return this.idproofsForm.controls['idproofs'] as FormControl;
}
get idproofsInputFormControl(): FormControl {
// debugger
return this.idproofsForm.controls['idproofsInput'] as FormControl;
}
idproofInputAadharValidation(): ValidatorFn {
return (control: AbstractControl): ValidationErrors | null => {
// debugger
const pattern = new RegExp("^[0-9]{10}$");
if (pattern.test(control.value)) {
return null;
} else {
return {
aadharError: 'Aadhar number is not correct'
};
}
};
}
idproofInputPANValidation(): ValidatorFn {
return (control: AbstractControl): ValidationErrors | null => {
// debugger
const pattern = new RegExp("^[a-zA-Z0-9]+$");
if (pattern.test(control.value)) {
return null;
} else {
return {
panError: 'PAN number is not correct'
};
}
};
}
constructor(
private fb: FormBuilder
) {
this.idproofsForm = new FormGroup(
{
idproofs: new FormControl(''),
idproofsInput: new FormControl('')
}
);
}
ngOnInit() {
this.idproofsForm.valueChanges.subscribe(
field => {
// debugger
console.log(this.idproofsForm.controls['idproofsInput']);
if (field['idproofs'] && field['idproofs'] === 'PAN') {
this.idproofsInputFormControl.clearValidators();
this.idproofsInputFormControl.setValidators(this.idproofInputPANValidation());
} else if (field['idproofs'] && field['idproofs'] === 'Aadhar') {
this.idproofsInputFormControl.clearValidators();
this.idproofsInputFormControl.setValidators(this.idproofInputAadharValidation());
}
// debugger
}
);
}
}
您的 HTML 可以看起来像这样,
<label>ID proof<span class="asterisk">*</span></label>
<mat-form-field appearance="outline">
<mat-select [formControl]="idproofsFormControl" name="idproofs" placeholder="IDProof name" required class="form-control">
<mat-option *ngFor="let idproof of idproofOptions" [value]="idproof">
{{idproof}}
</mat-option>
</mat-select>
</mat-form-field>
<br/>
<!-- {{idproofsInputFormControl|json}} -->
<label>ID proof number<span class="asterisk">*</span></label>
<mat-form-field appearance="outline">
<input matInput placeholder="ID Proof Number" required [formControl]="idproofsInputFormControl" class="form-control">
<mat-error *ngIf="idproofsInputFormControl.errors">
{{idproofsInputFormControl.errors['aadharError']}}
</mat-error>
</mat-form-field>
看下面截图中的错误
注意:我的建议是您不要使用 ngModel,反应式方法要好得多,您可能需要稍微更改此代码以满足您的要求,但我相信它应该会有帮助