Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular 2 use a "template" for ng-content to use inside component loop

Tags:

html

angular

I am trying to create a component that will do some stuff and loop over a result set. I want to be able to provide a "template" for the items in the looped result set.

For instance, this is kind of the idea I am going for:

<search-field>
    <ng-template let-item>
        <span><strong>{{item.foo}}</strong></span>
        <span>{{item.bar}}</span>
    </ng-template>
</search-field>

The content within the search-field component should be used as a template for each iteration of the looped result set within that component.

This is how the search-field component may look:

<div class="search-container">
    <div class="search-input">
        <input type="text" class="form-control" placeholder="Search users..." [(ngModel)]="searchString" (ngModelChange)="searchStringChanged($event)">
        <div class="md-icon">search</div>
    </div>

    <ul class="search-results" *ngIf="searchResults.length > 0">
        <li class="search-results__item" *ngFor="let result of searchResults">
            <ng-content [item]="item"></ng-content> <!-- Template should be used here on each iteration and allow to pass in "item" to use in example up above -->
        </li>
    </ul>
</div>

How can I pass each item of the loop to the ng-content so that I have access to it in the code of the first example?

like image 930
Lansana Camara Avatar asked Oct 18 '17 12:10

Lansana Camara


1 Answers

Solved this with the following:

Component template usage:

<search-field>
    <ng-template let-item>
        <span><strong>{{item.username}}</strong></span>
        <span>{{item.email}}</span>
    </ng-template>
</search-field>

Component template definition:

<div class="search-container">
    <div class="search-input">
        <input type="text" class="form-control" placeholder="Search users..." [(ngModel)]="searchString" (ngModelChange)="searchStringChanged($event)">
        <div class="md-icon">search</div>
    </div>

    <ul class="search-results" *ngIf="searchResults.length > 0">
        <li class="search-results__item" *ngFor="let item of searchResults">
            <ng-template [ngTemplateOutlet]="templateRef" [ngTemplateOutletContext]="{$implicit: item}"></ng-template>
        </li>
    </ul>
</div>

Component class:

@Component({...})
export class SearchFieldComponent {
    @ContentChild(TemplateRef) templateRef: TemplateRef<any>;

    // ...
}

The explanation:

Using ng-template, I can use the let-item syntax, where item is the data that will be passed into the template on each iteration of the loop.

And in order to make the above possible, in the search-field component I use ng-template with ngTemplateOutlet as the template reference, and ngTemplateOutletContext is given the value {$implicit: item}, where item is the data I want to pass into the template.

Lastly, in the component class I need to use ContentChild to get the reference to the template to use in the ngTemplateOutlet.

like image 111
Lansana Camara Avatar answered Nov 16 '22 03:11

Lansana Camara