3

Using Angular 5 with reactive forms, I'm trying to create a nested form within a nested form in different components: Main Form Component contains a Contact Component which contains an Address Component. Contact and Address components both contain a FormGroup. I'm able to get one-level nesting working (Main Form and Contact) but the Address form doesn't work.

Here's what I've tried so far:

Main Form:

<form [formGroup]="testForm2">
    <input formControlName="test2" />
    <app-test-form [parent]="testForm2" formGroupName="testForm1"></app-test-form>
</form>
{{testForm2.value | json}}

export class TestFormFormComponent implements OnInit {
    testForm2: FormGroup;

  constructor() {
      this.testForm2 = new FormGroup({
          test2: new FormControl(),
          testForm1: TestFormComponent.getFormGroup()
      });
   }

Test Form:

<div [formGroup]="parent">
    <div [formGroupName]="formGroupName">
        <input formControlName="test1" />
        <app-address formGroupName="address" [parent]="testForm"></app-address>
    </div>
</div>

export class TestFormComponent implements OnInit {
    testForm: FormGroup;
    @Input() parent: FormGroup;
    @Input() formGroupName: string;

    constructor() {
        this.testForm = TestFormComponent.getFormGroup();
    }

    static getFormGroup(): FormGroup {
        return new FormGroup({
            test1: new FormControl(),
            address: AddressComponent.getFormGroup()
        });
    }

    ngOnInit() {
    }
}

Address Form:

<div [formGroup]="parent">
    <div [formGroupName]="formGroupName">
        <mat-form-field>
            <input matInput type="text" formControlName="address1" placeholder="Address Line 1" />
        </mat-form-field>
        <mat-form-field>
            <input matInput type="text" formControlName="address2" placeholder="Address Line 2" />
        </mat-form-field>
        <mat-form-field>
            <input matInput type="text" formControlName="city" placeholder="City" />
        </mat-form-field>
        <mat-form-field>
            <mat-select formControlName="state" placeholder="State">
                <mat-option *ngFor="let state of states" [value]="state.id">
                    {{ state.description | titlecase }}
                </mat-option>
            </mat-select>
        </mat-form-field>
        <mat-form-field>
            <input matInput type="text" formControlName="zip" placeholder="Zip" />
        </mat-form-field>
    </div>
</div>

export class AddressComponent implements OnInit {
    states: Lookup[];
    @Input() parent: FormGroup;
    @Input() formGroupName: string;
    constructor(private lookupServce: LookupService) {
    }

    static getFormGroup() {
        return new FormGroup({
            address1: new FormControl(),
            address2: new FormControl(),
            city: new FormControl(),
            state: new FormControl(),
            zip: new FormControl()
        });
    }

    ngOnInit() {
        this.lookupServce.lookupStates().subscribe(data => {
            this.states = data;
        });
    }
}

Output: { "test2": "asdf", "testForm1": { "test1": "asdf", "address": { "address1": null, "address2": null, "city": null, "state": null, "zip": null } } }

As you can see, controls in Main Form and Test Form are getting values, but Address Form is null even after typing in values.

6
  • I think your [parent] should still be the "testForm2" from the very beginning. All of this is apart of the same form. So instead of [parent]="testForm" in your Test Form HTML, do [parent]="parent" Commented Mar 20, 2018 at 17:26
  • That works, but makes the two sub-forms siblings instead of children. It is possible to define multiple nested formgroups in one component but I can't get it to work when split into different components Commented Mar 20, 2018 at 17:33
  • 1
    What happens if you get rid of the testForm in your Test Form? I think that creating the TestForm within your main form as well as another creation in the test form is what is messing it up. So instead do [formGroup]="parent.get('testForm1')" in your test form html, and [parent]="parent.get('testForm1')" also in your test form html... Then in your address form html do [formGroup]="parent.get('address')" Commented Mar 20, 2018 at 17:46
  • Can't you build the form in the parent and just pass the nested groups to child and grandchild? Commented Mar 20, 2018 at 17:59
  • @Kevin thanks for the suggestion. Replacing with parent.get('testForm1') throws an error: cannot get control with name 'testform1' Commented Mar 20, 2018 at 18:29

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.