Angular 2 validation together with the child compo

2020-04-01 07:41发布

问题:

Inside the parent component I have a child component. Both have their required fields. At the end I need the enable the submit button only if both components are valid (all their required fields are filled in this case).

How can I accomplish this, especially with template-driven validation?

Seed code

parent component

@Component({
    selector: 'parent-comp',
    templateUrl: 'parent.html'
})
export class Parent {

}

<input pInputText name="txt1" id="txt1"
                       required/>

<child-comp></child-comp>

<button pButton type="button" label="Submit"
            [disabled]="IF ONE OF THE COMPS IS NOT VALID"></button>

child component

@Component({
    selector: 'child-comp',
    templateUrl: 'child.html'
})
export class Child {

}

<input pInputText name="txt2" id="txt2"
                       required/>

回答1:

For validating both parent and child component, a single form need to be divided into multiple component.

Parent html

<form #parentForm="ngForm">
            <input pInputText name="txt1" id="txt1"
                   required/>

      <child-comp></child-comp>

        <button pButton type="button" label="Submit"
        [disabled]="!parentForm.valid"></button>
        </form>

Parent Component

 import { Component } from '@angular/core';
 @Component({
       selector: 'parent-comp',
        templateUrl: 'parent.html'
})
export class Parent {

}

Child Form must not have form tag

<input pInputText name="txt2" id="txt2"
                   required/>

Child Component

import { Component } from '@angular/core';
import { ControlContainer, NgForm } from '@angular/forms';
@Component({
selector: 'child-comp',
templateUrl: 'child.html',
viewProviders: [{ provide: ControlContainer, useExisting: NgForm }]
 })
 export class Child {
 }


回答2:

You can create @Output variable in child that will emit form.valid value. You need to use FormBuilder and FormGroup (don't see it here).

Every time you change something inside form, you need to call a function that will emit onchange.

Example for child:

@Output onchange: EventEmitter<Boolean> = new EventEmitter(false);
formInChild: FormGroup;

constructor(private fb: FormBuilder) {
  this.formInChild = fb.group(...)
  this.formInChild.valueChanges.subscribe(() => {
    this.onchange.emit(this.form.valid);
  }
}

Now in parent:

(view)

<child-comp (onchange)="setButtonState($event)"></child-comp>
<button pButton type="button" label="Submit"
            [disabled]="!allvalid"></button>

(component)

formInParent: FormGroup;
allvalid: boolean = false;

constructor(private fb: FormBuilder) {
  this.formInParent = fb.group(...);
}

setButtonState(formFromChildValid) {
  this.allvalid = this.formInParent.valid && formFromChildValid;
}

In this case every time you change something in child's form, child's form valid state will be emitted to parent which will update allvalid variable which is listened by button.



标签: angular