[SOLVED] How to add custom template to Generic list component

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)

Leave a Reply

Your email address will not be published. Required fields are marked *