Reputation: 1098
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? :D )
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);
}
}
}
Upvotes: 0
Views: 1472
Reputation: 1573
Let's start with defining template.
<chained-item-list [items]="items" (onRemoveItem)="onRemoveItem($event)">
<ng-template #contentAccessTpl="">
<div class="card">
<h4>Header Item</h4>
<small>22/03/2022</small>
<p>Lorem ipsum dolor amet.</p>
</div>
</ng-template>
</chained-item-list>
For safer side add condition. by assigning the Id it will make it easy to use multiple templates.
<ul>
<ng-container *ngFor="let item of items; let indexItem = index">
<li>
<ng-container *ngIf="contentAccessTpl">
<ng-container *ngTemplateOutlet="contentAccessTpl"> </ng-container>
</ng-container>
<button
(click)="removeItem(indexItem)"
title="Remove"
type="button"
class="btn-remove"
>
X
</button>
</li>
</ng-container>
</ul>
Here's forked stackblitz.
Upvotes: 1
Reputation: 171
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!
Upvotes: 3