Uğur Dinç
Uğur Dinç

Reputation: 2455

How to pass values and methods to ng-template?

Consider the following situation inside the same template:

<!-- createFoo -->
<form [formGroup]="fooForm1" (ngSubmit)="createFoo(fooForm1)">
  <input formControlName="bar">
</form>

<!-- updateFoo -->
<form [formGroup]="fooForm2" (ngSubmit)="updateFoo(fooForm2, index)">
  <input formControlName="bar">
</form>

How would I re-write this without defining the same set of forms / formControls twice in the same template?

I believe it needs to look something like this? >>>

<!-- createFoo -->
<ng-template [ngTemplateOutlet]="fooForm" [ngTemplateOutletContext]="..."></ng-template>

<!-- updateFoo -->
<ng-template [ngTemplateOutlet]="fooForm" [ngTemplateOutletContext]="..."></ng-template>

<ng-template #fooForm>
  <form [formGroup]="...." (ngSubmit)="....">
    <input formControlName="bar">
  </form>
</ng-template>

Upvotes: 3

Views: 9335

Answers (2)

user2216584
user2216584

Reputation: 5602

In Angular 6 this is how I propose -

<ng-container *ngTemplateOutlet="fooForm; context: {$implicit: yourObjectWhichHasPropsAndMethods}">
</ng-container>

<ng-template #fooForm let-yourObjectWhichHasPropsAndMethods>
  <form [formGroup]="...." (ngSubmit)="yourObjectWhichHasPropsAndMethods.methodToCallOnSubmit">
    <input formControlName="bar">
  </form>
</ng-template>

interface YourContractToReuseTemplate {
  prop1;
  prop2;
  //this should return a function which will be called on submit
  methodToCallOnSubmit;
}

yourObjectWhichHasPropsAndMethods object will be of type YourContractToReuseTemplate.

Hope it will give you an idea.

EDIT - As requested by the user

To get the index you can do the following:

<ng-container *ngFor="let d of data; let i = index">
    <ng-container *ngTemplateOutlet="fooForm; context: {$implicit: {data: d, index: i}}">
    </ng-container>
</ng-container>

<ng-template #fooForm let-d>
    <h1>{{d.data.prop1}}</h1>
    <button (click)="d.data.methodToCallOnSubmit(d, d.index)">Button From Template Ref</button>  
</ng-template>

See the working example [NOTE I am not using the form but it will give you a direction] - https://stackblitz.com/edit/angular-8npc19?file=app%2Fbutton-overview-example.html

Hope it helps.

Upvotes: 4

PeS
PeS

Reputation: 4039

You are close however you can't use template outlet at ng-template as that defines the template. I usually use the template with ng-container:

<!-- createFoo -->
<ng-container *ngTemplateOutlet="fooForm; context:{$implicit: 'CREATE', fg: createFG}"</ng-container>

<!-- updateFoo -->
<ng-container *ngTemplateOutlet="fooForm; context:{$implicit: 'UPDATE', fg: updateFG}"</ng-container>

<ng-template #fooForm let-action let-formgroup="fg">
  <h1>{{action}}</h1>
  <form [formGroup]="formgroup" (ngSubmit)="....">
    <input formControlName="bar">
  </form>
</ng-template>

So, the let-something assigns values passed in context to variables local to the template. Note that let-action receives $implicit value from the values passed.

Otherwise you just (re)assign values from the context object as is the case of let-formgroup="fg". formgroup variable in the template holds the value passed in as fg property.

Upvotes: 4

Related Questions