29

I have a parent component which is the main FormGroup. Inside this <my-parent></my-parent> component I have a child component, <my-child></my-child>.

The child component has a *ngIf="some-conditional", and inside the child component, I have a quick fill button which basically does patchValue on a couple of the child FormGroup controls.

It successfully adds the child FormGroup to parent FormGroup, but the values of the child inside of the parent are always empty.

I've tried to add the controls two ways(both unsuccessful), with a setter inside the parent component, and by emitting from inside the child component and reassigning the new value to the parent FormGroup.

Here's a stackblitz with a demo of what im trying to do. Thanks in advance!

// PARENT COMPONENT

import {
  Component,
  ViewChild
} from '@angular/core';
import {
  FormBuilder,
  FormGroup,
  Validators
} from '@angular/forms';

import {
  ChildComponent
} from './child.component';

@Component({
  selector: 'my-parent',
  templateUrl: './parent.component.html',
  styleUrls: ['./app.component.scss']
})
export class ParentComponent {
  isChildFormSet = false;
  showChildComponent = false;
  exampleParentForm: FormGroup;

  // @ViewChild(ChildComponent)
  // set userForm(childForm: ChildComponent) {
  //   if (childForm && !this.isChildFormSet) {
  //     this.isChildFormSet = true;
  //     setTimeout(() => {
  //       this.exampleParentForm.addControl('child', new FormGroup(childForm.exampleChildForm.controls));
  //     });
  //   }
  // }

  constructor(private fb: FormBuilder) {
    this.exampleParentForm = this.fb.group({
      parent: ['', Validators.required]
    })
  }

  submitForm(): void {
    console.log(this.exampleParentForm)
  }

  addChildComponent(): void {
    this.showChildComponent = true;
  }

  onChange(form) {
    // reset the form value to the newly emitted form group value.
    this.exampleParentForm = form;
  }
}


// CHILD COMPONENT

import {
  Component,
  OnInit,
  Input,
  Output,
  EventEmitter
} from '@angular/core';
import {
  FormBuilder,
  FormGroup,
  Validators
} from '@angular/forms';

@Component({
  selector: 'my-child',
  templateUrl: './child.component.html',
  styleUrls: ['./app.component.scss']
})
export class ChildComponent implements OnInit {
  exampleChildForm: FormGroup;

  @Input() formData: FormGroup;
  @Output() onFormGroupChange: EventEmitter < FormGroup > = new EventEmitter < FormGroup > ();


  constructor(private fb: FormBuilder) {}

  ngOnInit() {
    this.exampleChildForm = this.fb.group({
      child: ['', Validators.required]
    });

    this.addGroupToParent();
  }

  fillWithText() {
    this.exampleChildForm.patchValue({
      child: 'This is an exmple.'
    });
  }

  clearText(): void {
    this.exampleChildForm.get('child').setValue('');
  }

  private addGroupToParent(): void {
    this.formData.addControl('child', new FormGroup(this.exampleChildForm.controls));
    this.onFormGroupChange.emit(this.formData);
  }
}
<!-- PARENT COMPONENT -->

<div class="parent-container">
  <form [formGroup]="exampleParentForm" (submit)="submitForm()" novalidate>
    <div class="col-3">
      <input class="effect-1" type="text" placeholder="Parent Input" formControlName="parent" />
      <span class="focus-border"></span>
    </div>
    <my-child *ngIf="showChildComponent" [formData]="exampleParentForm" (onFormGroupChange)="onChange($event)">
    </my-child>
    <div>
      <button class="button parent" type="submit">Log Form Value</button>
    </div>
  </form>
  <button class="button small" type="button" (click)="addChildComponent()">Add Child Component</button>
</div>

<!-- CHILD COMPONENT -->

<div class="child-container" [formGroup]="exampleChildForm">
  <div class="col-3">
    <input class="effect-1" type="text" placeholder="Child Input" formControlName="child">
    <span class="focus-border"></span>
  </div>
  <div>
    <button class="button child" type="button" (click)="fillWithText()">Patch Value</button>
  </div>
</div>

1 Answer 1

54

Instead of adding new FormGroup instance to the parent group simply add the child form group itself.

So

this.formData.addControl('child', new FormGroup(this.exampleChildForm.controls));

becomes

this.formData.addControl('child', this.exampleChildForm);

Forked Stackblitz

Sign up to request clarification or add additional context in comments.

2 Comments

This seems to have done the job, thank you! Not sure why you were downvoted but I'd be interested to find out why,
I suspect you won't get the answer why I was downvoted since that's how SO users respect each other.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.