Angular 4 个验证器同时检查 2 个控件
Angular 4 validator to check 2 controls at the same time
我有一个带有 2 个控件(port_start 和 port_end)的响应式表单,它们具有以下要求:
- 两者都必须有一个值
- 它们的值必须在 0 到 65535 之间
- port_start 值必须小于 port_end 值
这是我到目前为止尝试过的:
[...]
this.formModel.addControl('port_start',
new FormControl(object.port_start ? object.port_start : 0,
[Validators.required, Validators.min(0), Validators.max(65535), this.minMaxValidator('port_start', 'port_end').bind(this)]));
this.formModel.addControl('port_end',
new FormControl(object.ort_end ? object.port_end : 0,
[Validators.required, Validators.min(0), Validators.max(65535), this.minMaxValidator('port_start', 'port_end').bind(this)]));
[...]
这是自定义验证器函数:
minMaxValidator = function(startControl : string, endControl : string): ValidatorFn {
return (control: FormControl): {[key: string]: any} => {
let valid = true;
let valStart = 0;
let valEnd = 0;
if(this.formModel.controls[startControl] && this.formModel.controls[endControl]) {
valStart = <number>this.formModel.controls[startControl].value;
valEnd = <number>this.formModel.controls[endControl].value;
}
valid = valEnd >= valStart;
return valid ? null : { minmax : true };
};
}
这工作正常,除了这个问题:
- 假设我在 'port_start' 字段中键入“2”。 Angular 将其标记为无效,因为它大于 'port_end' 的值(默认为 0)。如果我在 'port_end' 字段中键入“5”,应用程序仍将 'port_start' 显示为无效,尽管现在它是正确的。
我明白问题是我每次更改另一个的值时都需要重新检查关联字段,但我不知道该怎么做。
有什么想法吗?谢谢,
min
、max
和 required
验证器可以保持原样。如果要根据另一个控件的值来验证一个控件,则需要将验证提升到父控件。
import { Component } from '@angular/core';
import { ValidatorFn, FormBuilder, FormGroup, Validators } from '@angular/forms';
const portStartEnd: ValidatorFn = (fg: FormGroup) => {
const start = fg.get('portStart').value;
const end = fg.get('portEnd').value;
return start && end && start < end ? null : { startEnd: true };
}
@Component({
selector: 'my-app',
template: `
<input [formControl]="form.get('portStart')" type="number" >
<input [formControl]="form.get('portEnd')" type="number" >
{{ form.valid }}
`,
styleUrls: ['./app.component.css']
})
export class AppComponent {
form: FormGroup;
constructor(private fb: FormBuilder) {
this.form = this.fb.group({
portStart: [null, [Validators.required, Validators.min(0), Validators.max(65535)]],
portEnd: [null, [Validators.required, Validators.min(0), Validators.max(65535)]]
}, { validator: portStartEnd } );
}
}
与@Tomasz 所说的不同,您可以将验证保持在控制级别。
秘诀:监听表单的变化,当它发生时,用当前值设置验证器。
Here is a stackblitz 向您展示它是如何工作的。
这是我使用的代码:
import { Component } from '@angular/core';
import { FormBuilder, FormGroup, ValidatorFn, AbstractControl } from '@angular/forms';
@Component({
selector: 'my-app',
template: `
<form [formGroup]="form">
<input type="number" formControlName="start">
<input type="number" formControlName="end">
</form>
<div *ngIf="form.get('start').hasError('lessThan')">Min should be less than max</div>
<div *ngIf="form.get('end').hasError('moreThan')">Max should be less than min</div>
`,
styleUrls: ['./app.component.css']
})
export class AppComponent {
form: FormGroup;
constructor(private fb: FormBuilder) {
this.form = fb.group({
start: [0],
end: [65535]
});
this.form.valueChanges.subscribe(changes => {
this.form.get('start').setValidators(LessThanEnd(+this.form.value.end));
this.form.get('end').setValidators(MoreThanStart(+this.form.value.start));
});
}
}
export function LessThanEnd(end: number): ValidatorFn {
return (control: AbstractControl): { [key: string]: any } => {
return control.value > end ? { 'lessThan': true } : null;
};
}
export function MoreThanStart(end: number): ValidatorFn {
return (control: AbstractControl): { [key: string]: any } => {
return control.value < end ? { 'moreThan': true } : null;
};
}
我有一个带有 2 个控件(port_start 和 port_end)的响应式表单,它们具有以下要求:
- 两者都必须有一个值
- 它们的值必须在 0 到 65535 之间
- port_start 值必须小于 port_end 值
这是我到目前为止尝试过的:
[...]
this.formModel.addControl('port_start',
new FormControl(object.port_start ? object.port_start : 0,
[Validators.required, Validators.min(0), Validators.max(65535), this.minMaxValidator('port_start', 'port_end').bind(this)]));
this.formModel.addControl('port_end',
new FormControl(object.ort_end ? object.port_end : 0,
[Validators.required, Validators.min(0), Validators.max(65535), this.minMaxValidator('port_start', 'port_end').bind(this)]));
[...]
这是自定义验证器函数:
minMaxValidator = function(startControl : string, endControl : string): ValidatorFn {
return (control: FormControl): {[key: string]: any} => {
let valid = true;
let valStart = 0;
let valEnd = 0;
if(this.formModel.controls[startControl] && this.formModel.controls[endControl]) {
valStart = <number>this.formModel.controls[startControl].value;
valEnd = <number>this.formModel.controls[endControl].value;
}
valid = valEnd >= valStart;
return valid ? null : { minmax : true };
};
}
这工作正常,除了这个问题:
- 假设我在 'port_start' 字段中键入“2”。 Angular 将其标记为无效,因为它大于 'port_end' 的值(默认为 0)。如果我在 'port_end' 字段中键入“5”,应用程序仍将 'port_start' 显示为无效,尽管现在它是正确的。
我明白问题是我每次更改另一个的值时都需要重新检查关联字段,但我不知道该怎么做。
有什么想法吗?谢谢,
min
、max
和 required
验证器可以保持原样。如果要根据另一个控件的值来验证一个控件,则需要将验证提升到父控件。
import { Component } from '@angular/core';
import { ValidatorFn, FormBuilder, FormGroup, Validators } from '@angular/forms';
const portStartEnd: ValidatorFn = (fg: FormGroup) => {
const start = fg.get('portStart').value;
const end = fg.get('portEnd').value;
return start && end && start < end ? null : { startEnd: true };
}
@Component({
selector: 'my-app',
template: `
<input [formControl]="form.get('portStart')" type="number" >
<input [formControl]="form.get('portEnd')" type="number" >
{{ form.valid }}
`,
styleUrls: ['./app.component.css']
})
export class AppComponent {
form: FormGroup;
constructor(private fb: FormBuilder) {
this.form = this.fb.group({
portStart: [null, [Validators.required, Validators.min(0), Validators.max(65535)]],
portEnd: [null, [Validators.required, Validators.min(0), Validators.max(65535)]]
}, { validator: portStartEnd } );
}
}
与@Tomasz 所说的不同,您可以将验证保持在控制级别。
秘诀:监听表单的变化,当它发生时,用当前值设置验证器。
Here is a stackblitz 向您展示它是如何工作的。
这是我使用的代码:
import { Component } from '@angular/core';
import { FormBuilder, FormGroup, ValidatorFn, AbstractControl } from '@angular/forms';
@Component({
selector: 'my-app',
template: `
<form [formGroup]="form">
<input type="number" formControlName="start">
<input type="number" formControlName="end">
</form>
<div *ngIf="form.get('start').hasError('lessThan')">Min should be less than max</div>
<div *ngIf="form.get('end').hasError('moreThan')">Max should be less than min</div>
`,
styleUrls: ['./app.component.css']
})
export class AppComponent {
form: FormGroup;
constructor(private fb: FormBuilder) {
this.form = fb.group({
start: [0],
end: [65535]
});
this.form.valueChanges.subscribe(changes => {
this.form.get('start').setValidators(LessThanEnd(+this.form.value.end));
this.form.get('end').setValidators(MoreThanStart(+this.form.value.start));
});
}
}
export function LessThanEnd(end: number): ValidatorFn {
return (control: AbstractControl): { [key: string]: any } => {
return control.value > end ? { 'lessThan': true } : null;
};
}
export function MoreThanStart(end: number): ValidatorFn {
return (control: AbstractControl): { [key: string]: any } => {
return control.value < end ? { 'moreThan': true } : null;
};
}