I have a simple data list component which as inputs one can pass the data to be shown, set a header for the list as well as a custom template for the list items.
All this works fine, however when I use an *ngIf
inside the header for some reason the template of the list items is not the same as the one I'm passing. I think it might be an issue with the @ContentChild
but I'm not sure what the issue is.
Data List Component
@Component({
selector: 'data-list',
template: `
<ng-content select="[data-list-header]"></ng-content>
<div>
<ng-template *ngFor="let item of itemsData" let-item [ngForOf]="[item]" [ngForTemplate]="itemTemplate">
</ng-template>
</div>
`
})
export class DataListComponent {
@Input() itemsData: any[];
@ContentChild(TemplateRef) itemTemplate: TemplateRef<ElementRef>;
}
Template
<data-list [itemsData]="items">
<div data-list-header style="border-bottom: 2px solid grey;">
<h1>Persons List</h1>
<h2>Count: {{ items.length }}</h2>
</div>
<ng-template let-item>
<div>
<h4>{{ item.name }} {{ item.surname }}</h4>
</div>
</ng-template>
</data-list>
Results In
The above templates works fine, a list of persons is shown. However once I add an *ngIf
to hide the Count as an example a list of counts is displayed instead.
Template not working properly
<data-list [itemsData]="items">
<div data-list-header style="border-bottom: 2px solid grey;">
<h1>Persons List</h1>
<h2 *ngIf="showCount">Count: {{ items.length }}</h2>
</div>
<ng-template let-item>
<div>
<h4>{{ item.name }} {{ item.surname }}</h4>
</div>
</ng-template>
</data-list>
Results In
This is a stackblitz of the above: https://stackblitz.com/edit/ng-template-loop-issue
The issue happens because when using structural directives (such *ngIf
) ng-template
is always created.
Now having @ContentChild(TemplateRef)
means that a query to find the first template (ng-template
) is done. Therefore in this case having *ngIf
on the header meant that an ng-template
was automatically created which was then picked up by the query.
To fix this issue a template reference was used so that the @ContentChild()
query would be done searching for the template reference. Example: @ContentChild('itemTemplate')
.
Updated code: https://stackblitz.com/edit/ng-template-loop-issue
More Info: