概要
以前の記事で ngFor
の trackBy
についての記事を記述しました。
TrackByFunction内の this
は DefaultIterableDiffer
になります。
定義元のコンポーネントを this
としたい場合は TrackByFunction
を返すメソッドを作成して、そのメソッドを テンプレートの trackBy
内で呼び出す用にします。
使用ケースとしては一意キーを外部から指定する場合などに使用します。
実行環境
- Node.js 10.9.x
使用ライブラリ
- Angular 7.1.x
サンプルソース
list.component.ts
import { Component, Input, OnInit, OnDestroy } from '@angular/core'; @Component({ selector: 'custom-list', template: `<li>{{num}}</li>` }) export class ListComponent implements OnInit, OnDestroy { @Input() num = 0; @Input() title = 'list'; ngOnInit(): void { console.log(`${this.title}: init - ${this.num}`); } ngOnDestroy(): void { console.log(`${this.title}: destroy - ${this.num}`); } }
app.component.html
<div style="margin-top: 10px;"> <div> <h4> Non trackBy </h4> <div> <button (click)="setItem1()">Apply</button> </div> <div> <ul> <ng-container *ngFor="let item of item1"> <custom-list [num]="item.id" title="non-trackBy"></custom-list> </ng-container> </ul> </div> </div> <div style="margin-top: 10px;"> <h4> trackBy </h4> <div> <button (click)="setItem2()">Apply</button> </div> <div> <ul> <ng-container *ngFor="let item of item2; trackBy: trackByItemFunc()"> <custom-list [num]="item.id" title="trackBy"></custom-list> </ng-container> </ul> </div> </div> </div>
app.component.ts
import { Component, TrackByFunction } from "@angular/core"; interface ListData { id: number; } @Component({ selector: 'app-root', templateUrl: './app.component.html' }) export class AppComponent { item1: ListData[] = []; item2: ListData[] = []; key = 'id'; setItem1(): void { this.item1 = this.createList(); } setItem2(): void { this.item2 = this.createList(); } /** * ngFor trackBy setting. */ trackByItemFunc(): TrackByFunction<ListData> { return (index, value) => { return value ? value[this.key] : null; }; } private createList(): ListData[] { const items = new Array<ListData>(); const length = Math.floor(Math.random() * 7) + 3; for (let i = 0; i < length; i++) { while (true) { const value = Math.floor(Math.random() * 10) + 1; if (items.findIndex(item => item.id === value) < 0) { items.push({ id: value }); break; } } } return items; } }