如何找到角度4反应形式的无效控件


89

我在Angular中有一个反应形式,如下所示:

this.AddCustomerForm = this.formBuilder.group({
    Firstname: ['', Validators.required],
    Lastname: ['', Validators.required],
    Email: ['', Validators.required, Validators.pattern(this.EMAIL_REGEX)],
    Picture: [''],
    Username: ['', Validators.required],
    Password: ['', Validators.required],
    Address: ['', Validators.required],
    Postcode: ['', Validators.required],
    City: ['', Validators.required],
    Country: ['', Validators.required]
});

createCustomer(currentCustomer: Customer) 
{
    if (!this.AddCustomerForm.valid)
    {
        //some app logic
    }
}

this.AddCustomerForm.valid返回false,但是一切看起来不错。

我试图通过检查控件集合中的status属性来查找。但是我想知道是否有一种方法可以找到无效的并显示给用户?


您只想显示带有错误的字段,就可以使用css突出显示或给无效字段上色。每个无效字段的类列表中都附加了一个“ ng-invalid”类
LookForAngular

Answers:


168

您可以简单地遍历每个控件并检查状态:

public findInvalidControls() {
    const invalid = [];
    const controls = this.AddCustomerForm.controls;
    for (const name in controls) {
        if (controls[name].invalid) {
            invalid.push(name);
        }
    }
    return invalid;
}

1
谢谢你,但是我尝试了这个,甚至没有返回我的表格仍然无效,这很奇怪。我的意思是这段代码看起来不错,但是form.valid为什么返回false
毫无

什么findInvalidControls()回报你?
Max Koretskyi

1
它不返回任何内容,invalid为空。我在调试监视屏幕中一一检查,所有控件均有效,但是this.AddCustomerForm.valid仍返回false。
sa_

我想我发现了。有一个电子邮件字段和正则表达式,但是控件的状态为“ PENDING”,可能是原因所在
sa_

6
@ AngularInDepth.com-如果控件之一是表单组,则您的函数将返回无效的表单组,而不是无效的特定表单控件
约翰·史密斯

35

我刚刚解决了这个问题:每个表单字段都有效,但是表单本身仍然无效。

原来,我已经在动态添加/删除控件的FormArray上设置了“ Validator.required”。因此,即使FormArray为空,它仍然是必需的,因此即使正确地填充了每个可见控件,该窗体也始终无效。

我没有找到表单的无效部分,因为我的'findInvalidControls'函数仅检查FormControl而不检查FormGroup / FormArray。所以我更新了一下:

/* 
   Returns an array of invalid control/group names, or a zero-length array if 
   no invalid controls/groups where found 
*/
public findInvalidControlsRecursive(formToInvestigate:FormGroup|FormArray):string[] {
    var invalidControls:string[] = [];
    let recursiveFunc = (form:FormGroup|FormArray) => {
      Object.keys(form.controls).forEach(field => { 
        const control = form.get(field);
        if (control.invalid) invalidControls.push(field);
        if (control instanceof FormGroup) {
          recursiveFunc(control);
        } else if (control instanceof FormArray) {
          recursiveFunc(control);
        }        
      });
    }
    recursiveFunc(formToInvestigate);
    return invalidControls;
  }

3
有用的答案。非常感谢
Mikki

1
同意,非常有用的答案。
nenea

20

在Chrome中的DevTools下,选择控制台标签。

在控制台提示符下,键入命令:

document.getElementsByClassName('ng-invalid')

输出应类似于以下内容: 在此处输入图片说明

在这种情况下,带下划线的文本用于表格控件listen-address。带有圆圈的文本:.ng-invalid表示该控件无效。

注意:经过镀铬测试


2
在我看来,这似乎是回答问题的最直接方法。
ckapilla

2
如果让我为您买一杯饮料,您就
可以避免

3

窗体和所有控件都扩展了角度类AbstractControl。每个实现都有验证错误的访问器。

let errors = this.AddCustomerForm.errors
// errors is an instance of ValidatorErrors

api文档包含所有参考 https://angular.io/api/forms/AbstractControl

编辑

我以为错误访问器以这种方式工作,但是到github的链接表明还有其他一些人认为与我一样 https://github.com/angular/angular/issues/11530

无论如何,通过使用控件访问器,您可以遍历表单中的所有formControl。

Object.keys(this.AddCustomerForm.controls)
    .forEach( control => {
        //check each control here
        // if the child is a formGroup or a formArray
        // you may cast it and check it's subcontrols too
     })

1
即使有空控件也将返回null
sa_

1
没有错误时,它应该返回null。您可以发布您的模板吗?
LookForAngular

是的,这是行不通的,在每个表单控件上设置的验证不同,每个表单控件都包含错误,而表单则无效。您需要迭代Maximus给出的答案等控件。
AJT82

我可以访问每个错误的错误,例如this.form.controls ['Email']。errors
Nazrul Muhaimin 18/12/21

@ AJT_82实际上,如果为formGroup设置了验证器,则窗体本身可能会显示错误(请查看有关跨字段验证的文档,这对于在组而不是在控件中进行验证是有意义的)
LookForAngular

3

现在,在角度9中,您可以使用markAllAsTouched()方法显示无效的控件验证器:

this.AddCustomerForm.markAllAsTouched();

给它一个+1,因为它帮助我找出了我需要知道的---当用户不一定要触摸输入时显示验证消息。
肖恩·霍尔斯

1

如果表单中没有太多字段,则只需按F12键并将鼠标悬停在控件上,即可看到带有该字段原始/有效/有效值的弹出窗口-“#fieldname.form-control.ng- untouched.ng-invalid”。



1

试试这个

 findInvalidControls(f: FormGroup) {
    const invalid = [];
    const controls = f.controls;
    for (const name in controls) {
      if (controls[name].invalid) {
        invalid.push(name);
      }
    }
    return invalid;
  }

1

这将记录所有控件的名称

for (let el in this.ReactiveForm.controls) {
      if (this.ReactiveForm.controls[el].errors) {
        console.log(el)
      }
 }          

您可以从中制作一个数组或字符串并显示给用户


0

我自由地改进了AngularInDepth.com -s代码,以便它也以嵌套形式递归搜索无效输入。它是否由FormArray或FormGroup嵌套。只需输入顶级formGroup,它将返回所有无效的FormControl。

如果您要将FormControl检查和无效数组功能的添加分开到一个单独的函数中,则可以略去一些“ instanceof”类型的检查。这会使函数看起来更加整洁,但是我需要一个全局的单个函数选项来获取所有无效formControl的平面数组,这就是解决方案!

findInvalidControls( _input: AbstractControl, _invalidControls: AbstractControl[] ): AbstractControl[] {
    if ( ! _invalidControls ) _invalidControls = [];
    if ( _input instanceof FormControl  ) {
        if ( _input.invalid ) _invalidControls.push( _input );
        return _invalidControls;
    }

    if ( ! (_input instanceof FormArray) && ! (_input instanceof FormGroup) ) return _invalidControls;

    const controls = _input.controls;
    for (const name in controls) {
        let control = controls[name];
        switch( control.constructor.name )
        {
            case 'AbstractControl':
            case 'FormControl':
                if (control.invalid) _invalidControls.push( control );
                break;

            case 'FormArray':
                (<FormArray> control ).controls.forEach( _control => _invalidControls = findInvalidControls( _control, _invalidControls ) );
                break;

            case 'FormGroup':
                _invalidControls = findInvalidControls( control, _invalidControls );
                break;
        }
    }

    return _invalidControls;
}

只针对那些需要它的人,因此他们不必自己编写代码。

编辑#1

有人要求它还返回无效的FormArray-s和FormGroups,因此,如果您还需要使用此代码

findInvalidControls( _input: AbstractControl, _invalidControls: AbstractControl[] ): AbstractControl[] {
    if ( ! _invalidControls ) _invalidControls = [];
    if ( _input instanceof FormControl  ) {
        if ( _input.invalid ) _invalidControls.push( _input );
        return _invalidControls;
    }

    if ( ! (_input instanceof FormArray) && ! (_input instanceof FormGroup) ) return _invalidControls;

    const controls = _input.controls;
    for (const name in controls) {
        let control = controls[name];
        if (control.invalid) _invalidControls.push( control );
        switch( control.constructor.name )
        {    
            case 'FormArray':
                (<FormArray> control ).controls.forEach( _control => _invalidControls = findInvalidControls( _control, _invalidControls ) );
                break;

            case 'FormGroup':
                _invalidControls = findInvalidControls( control, _invalidControls );
                break;
        }
    }

    return _invalidControls;
}

1
我试过了,但是没有找到任何无效的FormGroup或FormArray ...只是无效的FormControl。我犯了同样的错误...请参阅答案。
杰特(Jette)

我改进了答案,以适合您的用例。
Karl Johan Vallner

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.