4
votes

I have a template driven form which contains a group of inputs contained within an ngFor.

I am trying to separate the 'sub group' which repeats into its own child component, but I am having trouble having the parent ngForm include the validation included within the child component.

Here is a simplified version of what I am talking about:

Parent template:

<form #parentForm="ngForm">
    <input name="firstName" ngModel required>
    <input name="lastName" ngModel required>

    <child-component *ngFor="let child of children;"></child-component>
</form>

Child template:

<div>
    <input name="foo" required ngModel>
    <input name="bar" required ngModel>
</div>

I am not able to have the parent form pick up on the required's of the child inputs. I tried having the child within its own form and passing the #parentForm instance through to the child, and having the child call:

this.parentForm.addFormGroup(this.childForm.form)

but this still doesn't work.

I have also child doing this the reverse way where the parent gets the ContentChildren of the sub forms and adds each one to the form, but still the validation doesn't work.

I know I could have the subcomponent implement ControlValueAccessor but then I would need to implement a custom validator which I'd rather not do since none of the validation is actually new, it's just required's.

Please help me figure out why I can't add a sub-form to the parent and have it use the child's validations.

2

2 Answers

4
votes

One possible solution might be addition controls from child component to parent form as follows:

child.component.ts

@Component({
  selector: 'child-component',
  template: `
   <div>
    <input name="foo" required ngModel>
    <input name="bar" required ngModel>
  </div>
  `
})
export class ChildComponent {
  @ViewChildren(NgModel) controls: QueryList<NgModel>;

  constructor(private parentForm: NgForm) { }

  ngAfterViewInit() {
    this.controls.forEach((control: NgModel) => {
      this.parentForm.addControl(control);
    });
  }
}

Plunker Example

0
votes

You can use property binding and @Input for your problem which looks as

<form #parentForm="ngForm">
    <input name="firstName" ngModel required>
    <input name="lastName" ngModel required>

    <child-component #parentForm.childForm="ngForm" [children]="children"></child-component>
</form>

In your

  1. Declare a input variable as

    @Input() children:any[]=[];
    
  2. Modify the template as below

    <div *ngFor="let child of children;">
       <input name="foo" required [(ngModel)]="child.foo"/>
    </div>