0
votes

I have a component (in sample named: Hello) that has a FormGroup. The controls of the FormGroup have to be defined outside the component using ng-content.

A Simple sample in stackblitz: https://stackblitz.com/edit/angular-ivy-bqczmm?file=src%2Fapp%2Fhello.component.ts

Hello Component:

<form [formGroup]="fg">
  <ng-content select="[fg-controls]"></ng-content>
  <pre>{{fg.value | json}}</pre>
</form>

Parent Component:

<hello>
  <div fg-controls>
    <h1>Item 1</h1>
    aaa: <input formControlName="aaa" /><br /><br />
    bbb: <input formControlName="bbb" /><br /><br />
    ccc: <input formControlName="ccc" />
  </div>
</hello>

<hello>
  <div fg-controls>
    <h1>Item 2</h1>
    aaa: <input formControlName="aaa" /><br /><br />
    bbb: <input formControlName="bbb" /><br /><br />
  </div>
</hello>

I've got this error:

enter image description here

I know the variables are defined outside the FormGroup but in runtime in DOM its OK: enter image description here

Is there a right way to do it?

1
I don't think this will work, input directive is not in same component as FormGroup, even though it looks correct in HTML. - Bojan Kogoj
Bojan Kogoj, I Have FormGroup defined above the input (in runtime) - haya
It doesn't matter how HTML looks at runtime. If formControlName can't find a parent directive (FormGroupName, FormGroupDirective or FormArrayName) in same template it will throw an error. - Bojan Kogoj
@BojanKogoj, that is not 100%. it is possible via angular DI, but it seems that is not how it was supposed to be used and it can cause bugs - Andrei
Didn't know DI could be used this way. Either way I'm not sure if this is way to go. - Bojan Kogoj

1 Answers

1
votes

Here is an example of how it can be used https://stackblitz.com/edit/angular-ivy-uqosqh?file=src%2Fapp%2Fhello.component.ts

you can add provider to hello component, which will get a reference to its form

 providers: [
    {
      provide: ControlContainer,
      useFactory: hc => {
        return hc.form;
      },
      deps: [HelloComponent]
    }
  ]
...
ViewChild(FormGroupDirective) form;

but the problem is that controls are rendered before the form element is created, because the form element is in the HomeComponent element's view. To make that work you should postpone the rendering of inner inputs, in my case I did it with the help of setTimeout.

but it seems that is not how angular form APIs are supposed to work and it can cause issues on your application