5

Note: I am looking the solution for Reactive Forms Approach. Solution for template drive forms is already here

I have a library which is having a reactive form and I am trying to insert form input using ng-template and ng-container (Line A).

LibraryComponent

html

<form [formGroup]="mainForm">
  <input type="text" formControlName="inside">
  <ng-container [ngTemplateOutlet]="template"></ng-container> //line A
</form>

TS:

export class LibraryComponent implements OnInit {

@Input() template;
  mainForm: FormGroup;
  constructor(private formBuilder: FormBuilder) { }

  ngOnInit() {
    this.mainForm = this.formBuilder.group({
      inside: ['inside'],
      outside: ['outside'],
    });

  }

}

AppComponent

<app-library [template]="outer"></app-library>


<ng-template #outer>
      <input type="text" formControlName="outside">
</ng-template>

While doing this I get error:

preview-d2335ca5bdb955611c1cb.js:1 ERROR Error: 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).

      Example:


    <div [formGroup]="myGroup">
      <input formControlName="firstName">
    </div>

    In your class:

    this.myGroup = new FormGroup({
       firstName: new FormControl()
    });
    at Function.ReactiveErrors.controlParentException (reactive_errors.ts:14)
    at FormControlName._checkParentType (form_control_name.ts:272)
    at FormControlName._setUpControl (form_control_name.ts:277)
    at FormControlName.ngOnChanges (form_control_name.ts:207)
    at checkAndUpdateDirectiveInline (provider.ts:208)
    at checkAndUpdateNodeInline (view.ts:429)
    at checkAndUpdateNode (view.ts:389)
    at debugCheckAndUpdateNode (services.ts:431)
    at debugCheckDirectivesFn (services.ts:392)
    at Object.eval [as updateDirectives] (VM1408 AppComponent.ngfactory.js:41)

Any help will be greatly appreaciated.

Stackblitz

dasfdsa
  • 7,102
  • 8
  • 51
  • 93

2 Answers2

5

Really I don't know waht do you want to do, but simple pass as ngTemplateOutletContext the form and get it using let

Your library.component

 <ng-container [ngTemplateOutlet]="template" 
               [ngTemplateOutletContext]="{form:mainForm}">
 </ng-container>

Your template

<ng-template #outer let-form=form>
   <input type="text" [formControl]="form.get('outside')">
</ng-template>

See that we're using [formControl] not formControlName, this is the reason because we need pass the form

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

Pass formControl instance to ng-template using context.Then use formControl instead of formControlName inside ng-template.

App.component.html

<app-library [template]="outer"></app-library>
  <ng-template #outer let-control="control">
      <input type="text" [formControl]="control">     
   </ng-template>

lib.component.html

<form [formGroup]="mainForm">
  <input type="text" formControlName="inside">
  <ng-container *ngTemplateOutlet="template; context:{control: mainForm.get('outside')}"></ng-container>
</form>

Forked Stackblitz

Chellappan வ
  • 23,645
  • 3
  • 29
  • 60