Angular 获取FormGroup/FormControl中存在的验证程序
我在我的应用程序中使用Material 2,但在这个问题中,我想用Material 2解决一个问题 正如您在API参考中所看到的,有一个名为Angular 获取FormGroup/FormControl中存在的验证程序,angular,typescript,angular-material2,angular2-forms,Angular,Typescript,Angular Material2,Angular2 Forms,我在我的应用程序中使用Material 2,但在这个问题中,我想用Material 2解决一个问题 正如您在API参考中所看到的,有一个名为required的属性绑定,它在占位符中显示为星号 因此,我想知道是否有一种方法可以检查表单控件在Angular中是否有特定的验证器,因为我真的不想为每个输入手动设置[必需]=“true/false” 我看了文件,没有发现任何关于它的东西。我遇到了hasrerror方法(讽刺的是,在中没有记录该方法,在FormGroup、FormControl和Abstra
required
的属性绑定,它在占位符中显示为星号
因此,我想知道是否有一种方法可以检查表单控件在Angular中是否有特定的验证器,因为我真的不想为每个输入手动设置[必需]=“true/false”
我看了文件,没有发现任何关于它的东西。我遇到了hasrerror
方法(讽刺的是,在中没有记录该方法,在FormGroup、FormControl和AbstractControl中都没有记录),但是这不是我想要的。它只是检查表单控件是否有错误,但正如您可能已经读到的,我想检查控件是否有一些特定的验证器
一些代码:
<md-input-container>
<input placeholder="Placeholder"
mdInput [formControl]="anyCtrl"
[required]="anyCtrl.hasValidator('required')"> <!-- something like this -->
</md-input-container>
我希望这个问题足够清楚。提前感谢。Angular并没有提供一个很好的、干净的方法来实现这一点,但这是可能的。我认为验证器存储在注入FormBuilder的服务中(
NG_validators
),我将研究劫持该服务或将其注入组件,但目前这将起作用:
和源代码显示了键入到ValidatorFn
的AbstractControl
上的validator
成员<代码>验证器fn不幸的是,它只是有一个null
类型,所以我们看不到发生了什么。但是,在浏览生成的源代码并探测应用程序之后,我们似乎可以将此验证程序
方法传递给控件
参数,该参数将返回该控件上存在的所有验证程序的对象,无论其是否传递
奇怪的是,这个只对FormControl
本身有效,而对FormGroup
无效(在FormGroup
上,validators
成员不是函数,在我的测试中总是null
)。编译后的JS表示该函数采用控件
参数;我已尝试传入FormControl
引用,但据我所知,只要此参数不为null,它将返回控件上的验证器
在FormControl上获取验证程序
更容易抓取:
在您的标记中:
<md-input-container>
<input placeholder="Placeholder"
mdInput [formControl]="anyCtrl"
[required]="hasValidator('anyCtrl', 'email')">
</md-input-container>
验证器的特殊情况。需要
required
验证器有一个快捷方式。[required]
绑定实际上是RequiredValidator
指令的一个实例(source/forms.js的第5022行)。此指令实际上会将必需的
验证器添加到表单控件
中,它处于启用状态。这相当于在初始化时向表单组
添加验证器。required
。因此,将绑定属性设置为false将从该控件中删除required
验证器,反之亦然……无论哪种方式,该指令都会影响FormControl.required
值,因此将其绑定到它更改的属性实际上不会有多大作用
唯一的区别是[required]
指令将星号添加到占位符中,而验证程序.required
不添加星号
我将继续研究
NG_验证器
,但我希望这对现在有所帮助 这个答案是这个问题的延续。他们写道:
public hasValidator(control: string, validator: string): boolean {
return !!this.myForm.controls[control].validators(control).hasOwnProperty(validator);
// returns true if control has the validator
}
但是没有AbstractControls.validators()
方法。我假设AbstractControls.validator()
就是这个意思
hasvalidater()
方法仅适用于“失败”的验证器(例如,值为“”(空)的控件上所需的验证器)。因为如果通过,则返回null。解决此问题的一种方法是设置该值,使其始终失败,然后恢复该值
public hasValidator(control: string, validator: string): boolean {
let control: AbstractControl = this.myForm.controls[control];
let lastValue: any = control.value;
switch(validator) {
case 'required':
control.setValue(''); // as is appropriate for the control
case 'pattern':
control.setValue('3'); // given you have knowledge of what the pattern is - say its '\d\d\d'
....
}
let hasValidator: boolean = !!control.validator(control).hasOwnProperty(validator);
control.setValue(lastValue);
return hasValidator;
}
这太可怕了。它引出了一个问题-为什么没有AbstractControl.getValidators():ValidatorFn[]| null
?
隐藏这一点的动机是什么?也许他们担心有人会在他们的代码中输入:
...
secretPassword: ['', [Validators.pattern('fjdfjafj734738&UERUEIOJDFDJj')]
...
我将代码从joh04667和HankCa调整为:
export const hasValidator = (form: FormGroup, controlPath: string, validator: string): boolean => {
const control = form.get(controlPath);
const validators = control.validator(control);
return !!(validators && validators.hasOwnProperty(validator));
};
我将其存储在名为util.ts的文件中,并导入包含以下格式的组件:
import * as util from '@app/shared/util';
[required]="util.hasValidator(myForm, 'path.to.control', 'required')"
并在类中定义util:
public util = util;
将指令添加到输入组件,如下所示:
import * as util from '@app/shared/util';
[required]="util.hasValidator(myForm, 'path.to.control', 'required')"
基于mtiner的推荐,我们构建了自己的指令来相应地标记必填字段
@Directive({
selector: '[mandatoryField]'
})
export class MandatoryFieldDirective implements OnInit {
hasRequiredField(abstractControl: AbstractControl) {
if (abstractControl.validator) {
const validator = abstractControl.validator({} as AbstractControl);
if (validator && validator.required) {
return true;
}
}
return false;
}
ngOnInit() {
const required = this.hasRequiredField(this.ngControl.control);
if (required) {
this.renderer.setAttribute(this.elementRef.nativeElement, 'required', '');
if (this.parentFormField && this.parentFormField._elementRef) { // required for Angular Material form-fields
this.renderer.setAttribute(this.parentFormField._elementRef.nativeElement, 'required', '');
}
}
}
constructor(
private ngControl: NgControl, @Optional() private parentFormField: MatFormField,
public renderer: Renderer2, public elementRef: ElementRef
) { }
}
该指令设置“必需”属性。这个属性可以通过CSS来处理。该指令适用于普通HTML输入标记以及角度材质表单字段。为了使用角度材质,我们必须添加一些变通方法,因为必须在封闭的表单字段标记上设置“required”属性;不仅在实际输入字段上。因此,父组件将传递给指令构造函数
<mat-form-field class="date-picker-form">
<input matInput class="label-value" [formControlName]="controlName" mandatoryField [matDatepicker]="picker">
<mat-datepicker #picker class="calendar"></mat-datepicker>
</mat-form-field>
没有直接或干净的方法可以做到这一点。这是我遇到的最干净的方法,有效。使用最新版本的Angular v10.2.0进行测试(截至今日) 进口这些
import {AbstractControl, FormControl, Validators} from '@angular/forms';
定义你的控制
anyCtrl = new FormControl('', [Validators.required]);
添加此方法
public hasRequiredField = (abstractControl: AbstractControl): boolean => {
if (abstractControl.validator) {
const validator = abstractControl.validator({}as AbstractControl);
if (validator && validator.required) {
return true;
}
}
return false;
}
如何从HTML中调用此方法
<input placeholder="Placeholder" [formControl]="anyCtrl" [required]="hasRequiredField(anyCtrl)">
请务必记住,使用setValidator方法将覆盖现有的验证器,因此您需要为正在重置的控件包含所有需要/想要的验证器
control.setValidators([myCustomValidator(owner)]);
没有这样干净的方法可以做到这一点,但是你可以通过
this.form.controls[key].validator
然后添加自定义控件,我们可以像
control.setValidators([control.validator, myCustomValidator(owner)]);
这将允许我们重新使用现有的验证器和新的自定义验证器是的,我检查了错误并意识到了一些其他问题,所以你最好等一个比我聪明的人:公司
control.setValidators([control.validator, myCustomValidator(owner)]);