【问题标题】:Angular reactive forms - manually trigger validation of parent FormGroup when child FormGroup changesAngular 反应式表单 - 当子 FormGroup 更改时手动触发对父 FormGroup 的验证
【发布时间】:2018-05-16 05:15:18
【问题描述】:

我有一个 Angular 组件,它定义了一个 FormGroup,它有一个嵌套的 FormGroup 作为它的控件之一。

FormGroup 作为@Input 参数传递给子组件,子FormGroup 内的某些控件上有验证器。

出于某种原因,父级 FormGroupvalid 属性仅在我更新子组件中的值时更新,然后随机更改父级@ 的输入之一987654328@ (例如在输入中添加额外的空格)。

设置相当复杂(根据特定条件从 child FormGroup 的控件中添加或删除验证器,这可能是验证没有自动进行的原因。

如何在子 FormGroup 中的任何内容发生变化时手动触发父 FormGroup 重新验证?我在 child 组件中试过这个:

ngOnInit()

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

这应该会触发child FormGroup 的任何输入更改时的重新验证,并将事件广播到parent 组件,这应该会触发父FormGroup 的重新验证。我得到了某种堆栈溢出错误,因为这会导致无限循环。

如何触发父FormGroup自动重新验证?

【问题讨论】:

    标签: javascript angular angular-reactive-forms angular-validation


    【解决方案1】:

    this.FormGroup.updateValueAndValidity();


    updateValueAndValidity() - 这是 FormGroup 的默认方法

    【讨论】:

    • 仅供参考,这也会触发 valueChanges。您可能不想触发。一个示例是,如果您在 valueChange 上修改 FormGroup,然后希望它再次验证。调用它会创建一个无限循环。您可以将 emitEvent 设置为 false,但验证将永远不会被触发。
    【解决方案2】:

    我做了这样的事情,例如它是我的子表单组:

    我的子表单组组件:

    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>
    

    【讨论】:

    • 感谢@Fateme Fazli,在某些情况下这可能是一种有用的方法。我发现在我的情况下,我的子 FormGroup 在一个阶段被动态替换,这破坏了父组件和子组件之间的连接。如果我为子 FormGroup 中的每个控件执行“patchValue”,一切都会自动运行。
    • @ChrisHalcrow 您的欢迎,如果您发布您的答案将是好的和有帮助的。
    猜你喜欢
    • 1970-01-01
    • 2017-12-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-04-23
    • 2018-05-14
    • 2021-05-28
    • 2018-08-06
    相关资源
    最近更新 更多