diff --git a/npm/ng-packs/packages/core/src/lib/services/track-by.service.ts b/npm/ng-packs/packages/core/src/lib/services/track-by.service.ts new file mode 100644 index 0000000000..ca2b92db5f --- /dev/null +++ b/npm/ng-packs/packages/core/src/lib/services/track-by.service.ts @@ -0,0 +1,18 @@ +import { Injectable, TrackByFunction } from '@angular/core'; + +@Injectable({ + providedIn: 'root', +}) +export class TrackByService { + by(key: keyof T): TrackByFunction { + return ({}, item) => item[key]; + } + + byDeep(...keys: (string | number)[]): TrackByFunction { + return ({}, item) => keys.reduce((acc, key) => acc[key], item); + } + + bySelf(): TrackByFunction { + return ({}, item) => item; + } +} diff --git a/npm/ng-packs/packages/core/src/lib/tests/track-by.service.spec.ts b/npm/ng-packs/packages/core/src/lib/tests/track-by.service.spec.ts new file mode 100644 index 0000000000..19868e8ad5 --- /dev/null +++ b/npm/ng-packs/packages/core/src/lib/tests/track-by.service.spec.ts @@ -0,0 +1,33 @@ +import { TrackByService } from '../services/track-by.service'; + +describe('TrackByService', () => { + const service = new TrackByService(); + + describe('#by', () => { + it('should return a function which tracks a property', () => { + expect(service.by('x')(284, { x: 1036 })).toBe(1036); + }); + }); + + describe('#byDeep', () => { + it('should return a function which tracks a deeply-nested property', () => { + expect( + service.byDeep( + 'a', + 'b', + 'c', + 1, + 'x', + )(284, { + a: { b: { c: [{ x: 1035 }, { x: 1036 }, { x: 1037 }] } }, + }), + ).toBe(1036); + }); + }); + + describe('#bySelf', () => { + it('should return a function which tracks the item', () => { + expect(service.bySelf()(284, 'X')).toBe('X'); + }); + }); +});