简体   繁体   English

Angular 反应式表单 - 当子 FormGroup 更改时手动触发父 FormGroup 的验证

[英]Angular reactive forms - manually trigger validation of parent FormGroup when child FormGroup changes

I have an Angular component that defines an FormGroup , which has a nested FormGroup as one of its controls.我有一个 Angular 组件,它定义了一个FormGroup ,它有一个嵌套的FormGroup作为其控件之一。

The child FormGroup is passed as an @Input parameter to a child component , and there are validators on some of the controls inside the child FormGroup .FormGroup作为@Input参数传递给子组件,并且子FormGroup一些控件上有验证器。

For some reason, the valid property of the parent FormGroup only updates once I update values in the child component, then make a random change to one of the inputs for the parent FormGroup (like adding an extra space to an input).出于某种原因,FormGroupvalid属性仅在我更新子组件中的值时更新,然后对父FormGroup的输入之一进行随机更改(例如向输入添加额外的空间)。

The setup is fairly complex (validators are added or removed from controls on the child FormGroup depending on certain conditions, which is probably why the validation isn't happening automatically).设置相当复杂(根据特定条件在FormGroup 上的控件中添加或删除验证器,这可能是验证不会自动发生的原因)。

How can I manually trigger the parent FormGroup to re-validate as soon as anything in the child FormGroup changes?如何在子FormGroup任何内容发生更改时手动触发父FormGroup重新验证? I tried this in the child component:我在组件中试过这个:

ngOnInit()

  this.myForm.valueChanges.subscribe(val => {
      this.myForm.updateValueAndValidity({onlySelf: false, emitEvent: true})
  });

This is supposed to trigger a re-validation of the child FormGroup whenever any of its inputs change, and broadcast the event to the parent component, which should trigger a re-validation of the parent FormGroup .这应该在其任何输入更改时触发child FormGroup 的重新验证,并将事件广播到parent组件,这应该触发父FormGroup的重新验证。 I get some kind of stack overflow error though, as this results in an infinite loop.但是,我遇到了某种堆栈溢出错误,因为这会导致无限循环。

How can I trigger the parent FormGroup to re-validate automatically?如何触发父FormGroup自动重新验证?

this.FormGroup.updateValueAndValidity(); this.FormGroup.updateValueAndValidity();


updateValueAndValidity() - this is a default method withing FormGroup updateValueAndValidity() - 这是 FormGroup 的默认方法

i did something like this for example it's my child formgroup:我做了这样的事情,例如这是我的孩子表单组:

my child formgroup component:我的子表单组组件:

import { Component, Input } from "@angular/core";
import { FormGroup } from "@angular/forms";

@Component({
    selector: 'input-form-control',
    templateUrl: './input-form-control.component.html'
})
export class InputFormControlComponent {

    public formGroup: FormGroup;
    @Input('label') formControlLabel: string;
    @Input('controlId') formControlId: string;
    @Input('name') formControlName: string;
    @Input('type') formControlType: string;
    @Input('errorText') formControlErrorText: string;
    @Input('helpText') formControlHelpText: string;

    @Input('group')
    set formControl(group) {
        this.formGroup = group;
    }
    @Input('required') isRequired: boolean;
    @Input('value')
    set value(value: string) {
        this.currentValue = value;
        this.store({ value });
        this.setAsTouched();
    }
}
    get value(): string {
        return this.currentValue;
}
    @Output('valueChange') valueChange: EventEmitter<any> = new EventEmitter();

    setAsTouched() {
    this.formGroup.controls[this.formControlName].markAsTouched();
}
    store(data) {

    if (!this.formGroup.controls[this.formControlName]) {
        return;
    }
    if (data.value === EMPTY_ITEM) {
        this.formGroup.controls[this.formControlName].setValue('');
        this.valueChange.emit({ value: '' });
        return;
    }
    this.formGroup.controls[this.formControlName].setValue(data.value);
    this.valueChange.emit(data);

}
}

it's template:它的模板:

<form [formGroup]="formGroup" class="m-form m-form--fit">
    <div class="form-group m-form__group row" [ngClass]="{
                    'has-danger': formGroup.controls[formControlName].invalid && formGroup.controls[formControlName].touched,
                    'has-success': formGroup.controls[formControlName].valid && formGroup.controls[formControlName].touched,
                    'has-no-action': formGroup.controls[formControlName].untouched
                                }">
        <label class="col-form-label col-lg-3 col-sm-12" [for]="formControlId">
            {{formControlLabel}}
            <span *ngIf="isRequired" class="required" aria-required="true"> * </span>

        </label>
        <div class="col-lg-4 col-md-9 col-sm-12">
            <input [type]="formControlType || 'text'" class="form-control m-input" [formControlName]="formControlName" [name]="formControlName" [id]="formControlId" [placeholder]="formControlLabel" (click)="setAsTouched()" (valueChanged)="store($event)">
            <div class="form-control-feedback">{{formControlErrorText || 'Required Field May Not Be Empty'}}</div>
            <span class="m-form__help">{{formControlHelpText}}</span>
        </div>
    </div>
    <div class="form-group m-form__group"></div>
</form>

in parent template:在父模板中:

<form [formGroup]="parentFormGroup">
    <input-form-control
        [required]="false"
        [group]="parentFormGroup"
        label="Description"
        name="description"
        controlId="description"
        helpText="Enter the Description"
        [value]="someValue"                    
        (valueChange)="checkParentValidity($event)">
    </input-form-control>
<form>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM