Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/angular/30.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/typescript/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Angular 获取FormGroup/FormControl中存在的验证程序_Angular_Typescript_Angular Material2_Angular2 Forms - Fatal编程技术网

Angular 获取FormGroup/FormControl中存在的验证程序

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

我在我的应用程序中使用Material 2,但在这个问题中,我想用Material 2解决一个问题

正如您在API参考中所看到的,有一个名为
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)]);