0

I have an Angular 15 application (see source code on Stackblitz) that uses reactive forms and a ControlValueAccessor pattern to create a parent form which includes child form groups. When I add a form group and annotate it as a FormGroup in the parent html template, the data is not passed to the child. When I annotate it as a FormControl it is passing and accessing the data of the child form correctly, but I get the error

ERROR Error: control.registerOnChange is not a function

Furthermore I can't access the individual controls inside the FormGroup if I annotate it as a FormControl.

In the code example childGroupForm2 receives the passed values but childGroupForm does not.

My optimal solution would be to annotate the FormGroup as a FormGroup and pass the values from the parent component to the child.

Does anyone know why this is not working with FormGroups but works with FormControl?

Edit for minimal code:

// parent.component.html

<form [formGroup]="parentForm">
   <child-group [formGroup]="childGroupForm"> </child-group>
   <child-group [formControl]="childGroupForm2"> </child-group>
</form>  



// parent.component.ts

get childGroupForm(): FormGroup {
    return this.parentForm.get('childGroupForm') as FormGroup;
}

get childGroupForm2(): FormControl {
    return this.parentForm.get('childGroupForm2') as FormControl;
}

ngOnInit() {
    this.parentForm = this.fb.group({
      childGroupForm: this.fb.group({
        elementInput: 'Test1',
        elementsSelectionInput: 'Test2',
      }),
      childGroupForm2: this.fb.group({
        elementInput: 'Test3',
        elementsSelectionInput: 'Test4',
      }),
    });
}
Fynn
  • 210
  • 1
  • 6
  • 28

2 Answers2

2

Your child-group is a custom form control (a component that implements ControlValueAccessor). A Custom form control is "feed" with a FormControl -not with a FormGroup-.

So your Form in parent should be

this.parentForm = this.fb.group({
  name: 'Test0',
  childGroupForm: this.fb.control({ //<--are FormControl that "store" an object
    elementInput: 'Test1',
    elementsSelectionInput: 'Test2',
  }),
  childGroupForm2: this.fb.control({ //<--are FormControl that "store" an object
    elementInput: 'Test3',
    elementsSelectionInput: 'Test4',
  }),
}); 

And you parent like

<form [formGroup]="parentForm">
  <child-group formControlName="childGroupForm"></child-group>
  <child-group formControlName="childGroupForm2"></child-group>
</form>

Personal opinion: A custom form control should be used to make some "more complex" that mannage a serie of inputs. You can get the same using a simple component if you use viewProvider like this SO

An example with a formGroup, you can see the stackblitz

//child
@Component({
  selector: 'hello',
  template: `<h1>Hello </h1>
  <div [formGroupName]="group">
    <input formControlName="elementInput"/>
    <input formControlName="elementsSelectionInput"/>
  </div>      `,
  styles: [`h1 { font-family: Lato; }`],
  viewProviders:[{ provide: ControlContainer, useExisting: FormGroupDirective }]
})
export class HelloComponent  {
  @Input() group: string;
  
  constructor(){}
}

Then the parent use

  <form [formGroup]="form">
     <hello [group]="'childGroupForm'"  > </hello>
  </form>

  form=new FormGroup({
    childGroupForm:new FormGroup({
      elementInput:new FormControl(),
      elementsSelectionInput:new FormControl()
  
    })
  })

NOTE: In the example I use new Form and new FormGroup instead of formBuilder, but it's the same

Eliseo
  • 50,109
  • 4
  • 29
  • 67
1

In your parent component you are passing formgroup to formgroup aka childGroupForm should be form (not group):

ngOnInit() {
    this.parentForm = this.fb.group({
      name: 'Test0',
      childGroupForm: this.fb.group({ //change this.fb.group to this.fb.control
        elementInput: 'Test1',
        elementsSelectionInput: 'Test2',
      }),
      childGroupForm2: this.fb.group({  //change this.fb.group to this.fb.control
        elementInput: 'Test3',
        elementsSelectionInput: 'Test4',
      }),
    });
  }

Happy coding!

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
Bozhinovski
  • 2,496
  • 3
  • 20
  • 38
  • But then I can't access the controls of the childGroups, right? I would only get a FormControls-Object, which does not include the controls attribute – Fynn Dec 12 '22 at 14:11