Реактивные формы Angular - вручную запускать проверку родительской FormGroup при изменении дочерней FormGroup

У меня есть компонент Angular, который определяет FormGroup, который имеет вложенный FormGroup в качестве одного из элементов управления.

Дочерний элемент FormGroup передается как параметр @Input дочернему компоненту, а для некоторых элементов управления внутри дочернего FormGroup есть валидаторы.

По какой-то причине свойство valid parent FormGroup обновляется только после того, как я обновляю значения в дочернем компоненте, а затем произвольно изменяю один из входов для родительского FormGroup (например, добавляю дополнительное пространство в вход).

Настройка довольно сложна (валидаторы добавляются или удаляются из элементов управления дочерней FormGroup в зависимости от определенных условий, вероятно, поэтому проверка не происходит автоматически).

Как я могу вручную активировать родительский FormGroup для повторной проверки, как только что-либо в дочернем FormGroup изменится? Я пробовал это в дочернем компоненте:

ngOnInit()

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

Это должно запускать повторную проверку child FormGroup всякий раз, когда изменяется любой из ее входных параметров, и транслировать событие в компонент parent, который должен запускать повторную проверку родительского FormGroup. Однако у меня возникает какая-то ошибка переполнения стека, так как это приводит к бесконечному циклу.

Как я могу инициировать автоматическую повторную проверку родителя FormGroup?


person Chris Halcrow    schedule 16.05.2018    source источник


Ответы (2)


this.FormGroup.updateValueAndValidity ();


updateValueAndValidity () - это метод по умолчанию в FormGroup

person martcs    schedule 27.11.2019
comment
К вашему сведению, это также вызывает изменение значения. Который вы, возможно, не захотите запускать. Например, вы изменяете FormGroup в valueChange, а затем хотите, чтобы он снова прошел проверку. Вызов этого приведет к созданию бесконечного цикла. Вы можете установить для emitEvent значение false, но тогда проверка никогда не сработает. - person Alex; 19.06.2020

Я сделал что-то вроде этого, например, это моя дочерняя группа:

мой дочерний компонент группы форм:

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);

}
}

это шаблон:

<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>

в родительском шаблоне:

<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>
person Fateme Fazli    schedule 16.05.2018
comment
Спасибо @Fateme Fazli, в некоторых случаях это может оказаться полезным. Я обнаружил, что в моем случае моя дочерняя FormGroup динамически заменялась на одном этапе, что нарушало связь между родительским и дочерним компонентами. Если вместо этого я использую patchValue для каждого элемента управления в дочерней FormGroup, все будет работать автоматически. - person Chris Halcrow; 16.05.2018
comment
@ChrisHalcrow, добро пожаловать, будет хорошо и полезно, если вы опубликуете свой ответ. - person Fateme Fazli; 16.05.2018