2

I have form with form controls in component A. I've decided to move some form controls to separate component B in order to prevent code duplicates in other components.

A.html:

<form [formGroup]="editForm">
  <B [formControllerName]="'name'" ></B>
  <!-- Other form controls -->
</form>

B.html:

<select class="form-select" formControlName="{{formControllerName}}">
  <!-- Options -->
</select>

I got this error: Error: NG01050: formControlName must be used with a parent formGroup directive. You'll want to add a formGroup directive and pass it an existing FormGroup instance (you can create one in your class).

How I can get access to form controller from component A?

Drompai
  • 111
  • 1
  • 7
  • for an individual control or full (sub) formgroup I recommend control value accessor. Recommend looking at Resources on a previous answer I've posted https://stackoverflow.com/a/57280011/4711754 – Andrew Allen Aug 23 '22 at 08:25
  • Move the FormGroup into a service, or create a wrapper component and make the FromGroup an input on A and B. – Mikkel Christensen Aug 23 '22 at 09:21
  • 1
    @AndrewAllen, In my "personal" opinion, a control value accessor should be used only when the component is "complex" (a datepicker, a credit card ask, a circular dial, and drag-drop component...): components that require more that simple group some inputs. – Eliseo Aug 23 '22 at 11:24
  • @MikkelChristensen, the two components are at time in the app, it's unnecesary use a service – Eliseo Aug 23 '22 at 11:25
  • @Eliseo you're probably right, I only use cva as you describe. I've tested using cva for sub formgroup and it went fine but not used in more complex situations – Andrew Allen Aug 23 '22 at 11:35
  • @AndrewAllen, you can use with sub formgroup also. I only tell a "very very personal opinion" that it's not necessary, but of course you can do it. Severals authors do it and there're not problem- – Eliseo Aug 23 '22 at 12:31

1 Answers1

6

It's possible using viewProviders, see, e.g. this SO about FormArray

A more simple

@Component({
  selector: 'hello',
  template: `<h1>Hello </h1>
      <input [formControlName]="name"/>
  `,
  viewProviders:[{ provide: ControlContainer, useExisting: FormGroupDirective }]
})
export class HelloComponent  {
  @Input() name: string;
  
  constructor(){}
}

You can use

<form [formGroup]="form">
  <hello [name]="name" > </hello>
</form>

in .ts

  name = 'name';
  form=new FormGroup({
    name:new FormControl()
  })

See stackblitz

The another way is pass the own FormControl and use

   control:FormControl
   @Input('control') set _control(value){
       this.control=value as FormControl
   }

   <input [formControl]="control">

You use as

   <hello [control]="form.get('name')" > </hello>
Eliseo
  • 50,109
  • 4
  • 29
  • 67