Issue
I have this application where several lists on diferent components are being made.
The pattern for the component is always the same.
Master list items with ADD button and a REMOVE button for each item.
But the item itself vary alot, and some have its own list items.
I was trying to create a shareable component (cause DRY huh? 😀 )
But I cant’ get to my ngFor to repeat the items inside the component.
I made this
Stackblitz
with the work.
Here’s my code:
Component being used:
<chained-item-list [items]="items" (onRemoveItem)="onRemoveItem($event)">
<div class="card">
<h4>Header Item</h4>
<small>22/03/2022</small>
<p>Lorem ipsum dolor amet.</p>
</div>
</chained-item-list>
Component .HTML file
<div class="list-header">
<h3>CHAINED LIST</h3>
<button (click)="addNewItem()" title="Add Item" type="button" class="btn-add">
Add New
</button>
</div>
<br />
<ul>
<ng-container *ngFor="let item of items; let indexItem = index">
<li>
<ng-content></ng-content>
<button
(click)="removeItem(indexItem)"
title="Remove"
type="button"
class="btn-remove"
>
X
</button>
</li>
</ng-container>
</ul>
Component .TS file
export class ChainedItemListComponent {
@Input() items: any[];
@Output() onRemoveItem: EventEmitter<any> = new EventEmitter();
constructor() {}
addNewItem() {
this.items.push(Math.floor(Math.floor(Math.random() * 100)));
}
removeItem(indexItem: number) {
try {
this.onRemoveItem.emit(this.items.splice(indexItem, 1)[0]);
} catch (e) {
this.onRemoveItem.emit(e);
console.log(e);
}
}
}
Solution
It’s very simple. You need to update you component.
Change the way of passing a template, use ng-template
.
<chained-item-list [items]="items" (onRemoveItem)="onRemoveItem($event)">
<!-- pass template using ng-template tag -->
<ng-template>
<div class="card">
<h4>Header Item</h4>
<small>22/03/2022</small>
<p>Lorem ipsum dolor amet.</p>
</div>
</ng-template>
</chained-item-list>
Add this line to your component ts file.
@ContentChild(TemplateRef) customTemplateRef: TemplateRef<any>;
Now pass this customTemplateRef
to the ng-content
tag.
<ul>
<ng-container *ngFor="let item of items; let indexItem = index">
<li>
<!-- update this line -->
<ng-content *ngTemplateOutlet="customTemplateRef"></ng-content>
<button
(click)="removeItem(indexItem)"
title="Remove"
type="button"
class="btn-remove"
>
X
</button>
</li>
</ng-container>
</ul>
You’re done. Enjoy!
Answered By – Justwell Solets
Answer Checked By – Willingham (BugsFixing Volunteer)