Skip to content

Commit

Permalink
feat(core): added directive NgForTrackByKey
Browse files Browse the repository at this point in the history
Example:
*ngFor="let item of items trackByKey 'key'"
  • Loading branch information
thekiba committed Mar 15, 2019
1 parent 03f54e1 commit dc64928
Show file tree
Hide file tree
Showing 3 changed files with 71 additions and 0 deletions.
28 changes: 28 additions & 0 deletions projects/platform/src/lib/directives/track-by-key.directive.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { NgForOf } from '@angular/common';
import { Directive, Host, Input, Optional } from '@angular/core';

@Directive({
selector: '[ngForTrackByKey]'
})
export class NgForTrackByKeyDirective<T> {

@Input()
set ngForTrackByKey(key: keyof T) {
if (key) {
this.ngFor.ngForTrackBy = (index: number, item: T): T[keyof T] => item[key];
} else {
this.ngFor.ngForTrackBy = undefined;
}

this.ngFor['_differ'] = null;
this.ngFor['_ngForOfDirty'] = true;
this.ngFor.ngDoCheck();
}

constructor(@Host() @Optional() private ngFor: NgForOf<T>) {
if (!ngFor) {
throw new Error('TrackByKey should use with *ngFor!');
}
}

}
2 changes: 2 additions & 0 deletions projects/platform/src/lib/platform.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { ReturnDirective } from './directives/return.directive';
import { RouteDirective } from './directives/route.directive';
import { SetPropsDirective } from './directives/set-props.directive';
import { TimeoutDirective } from './directives/timeout.directive';
import { NgForTrackByKeyDirective } from './directives/track-by-key.directive';
import { UseEffectDirective } from './directives/use-effect.directive';
import { UseReducerDirective } from './directives/use-reducer.directive';
import { UseStateDirective } from './directives/use-state.directive';
Expand All @@ -32,6 +33,7 @@ const DIRECTIVES = [
RouteDirective,
SetPropsDirective,
TimeoutDirective,
NgForTrackByKeyDirective,
UseReducerDirective,
UseStateDirective,
UseEffectDirective,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { CommonModule } from '@angular/common';
import { createHostComponentFactory, SpectatorWithHost } from '@netbasal/spectator';
import { NgForTrackByKeyDirective } from '../../lib/directives/track-by-key.directive';

describe('NgForTrackByKeyDirective', () => {
let host: SpectatorWithHost<NgForTrackByKeyDirective<any>>;
const create = createHostComponentFactory({
component: NgForTrackByKeyDirective,
declarations: [ NgForTrackByKeyDirective ],
imports: [ CommonModule ]
});

it('should add generate trackBy fn by key', () => {
host = create(`
<ng-container *ngFor="
let item of [
{ animal: '🦊' },
{ animal: '🦄' }
] trackByKey 'animal'">
{{ item.animal }}
</ng-container>
`);

expect(host.element).toHaveText('🦊 🦄');
});

it('should throw exception', () => {
expect(() => {
host = create(`
<ng-container *ngFor="
let item of [
{ animal: '🦊' },
null
] trackByKey 'animal'">
{{ item?.animal }}
</ng-container>
`);
}).toThrow(`Cannot read property 'animal' of null`);
});

});

0 comments on commit dc64928

Please # to comment.