Skip to content

Commit 5129eed

Browse files
committed
fix(core): fixes clear view after value changes
1 parent 773a4cc commit 5129eed

2 files changed

Lines changed: 53 additions & 19 deletions

File tree

Lines changed: 20 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,33 @@
11
import { NgForOf } from '@angular/common';
2-
import { Directive, Host, Input, Optional } from '@angular/core';
2+
import { Directive, Host, Input, OnChanges, Optional, SimpleChanges, ViewContainerRef } from '@angular/core';
33

44
@Directive({
55
selector: '[ngForTrackByKey]'
66
})
7-
export class NgForTrackByKeyDirective<T> {
7+
export class NgForTrackByKeyDirective<T> implements OnChanges {
88

9-
@Input()
10-
set ngForTrackByKey(key: keyof T) {
11-
if (key) {
12-
this.ngFor.ngForTrackBy = (index: number, item: T): T[keyof T] => item[key];
13-
} else {
14-
this.ngFor.ngForTrackBy = undefined;
15-
}
16-
17-
this.ngFor['_differ'] = null;
18-
this.ngFor['_ngForOfDirty'] = true;
19-
this.ngFor.ngDoCheck();
20-
}
9+
@Input() ngForTrackByKey: keyof T;
2110

22-
constructor(@Host() @Optional() private ngFor: NgForOf<T>) {
11+
constructor(@Host() @Optional() private ngFor: NgForOf<T>, private viewContainerRef: ViewContainerRef) {
2312
if (!ngFor) {
2413
throw new Error('TrackByKey should use with *ngFor!');
2514
}
2615
}
2716

17+
ngOnChanges(changes: SimpleChanges): void {
18+
if ('ngForTrackByKey' in changes) {
19+
const key = this.ngForTrackByKey;
20+
if (key) {
21+
this.ngFor.ngForTrackBy = (index: number, item: T): T[keyof T] => item[ key ];
22+
} else {
23+
this.ngFor.ngForTrackBy = undefined;
24+
}
25+
26+
this.ngFor[ '_differ' ] = null;
27+
this.ngFor[ '_ngForOfDirty' ] = true;
28+
this.viewContainerRef.clear();
29+
this.ngFor.ngDoCheck();
30+
}
31+
}
32+
2833
}

β€Žprojects/platform/src/test/directives/track-by-key.directive.spec.tsβ€Ž

Lines changed: 33 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,21 @@
1-
import { CommonModule } from '@angular/common';
1+
import { Component } from '@angular/core';
22
import { createHostComponentFactory, SpectatorWithHost } from '@netbasal/spectator';
33
import { NgForTrackByKeyDirective } from '../../lib/directives/track-by-key.directive';
44

5+
@Component({
6+
selector: 'lib-animals',
7+
template: ''
8+
})
9+
class AnimalsComponent {
10+
animals: any[];
11+
}
12+
513
describe('NgForTrackByKeyDirective', () => {
6-
let host: SpectatorWithHost<NgForTrackByKeyDirective<any>>;
14+
let host: SpectatorWithHost<NgForTrackByKeyDirective<any>, AnimalsComponent>;
715
const create = createHostComponentFactory({
816
component: NgForTrackByKeyDirective,
917
declarations: [ NgForTrackByKeyDirective ],
10-
imports: [ CommonModule ]
18+
host: AnimalsComponent
1119
});
1220

1321
it('should add generate trackBy fn by key', () => {
@@ -21,7 +29,28 @@ describe('NgForTrackByKeyDirective', () => {
2129
</ng-container>
2230
`);
2331

24-
expect(host.element).toHaveText('🦊 πŸ¦„');
32+
expect(host.hostElement).toHaveText('🦊 πŸ¦„');
33+
});
34+
35+
it('should correct recreate differs when array are changed', () => {
36+
host = create(`
37+
<ng-container *ngFor="let item of animals trackByKey 'animal'">
38+
{{ item.animal }}
39+
</ng-container>
40+
`);
41+
42+
host.setHostInput('animals', [
43+
{ animal: '🦊' },
44+
{ animal: 'πŸ¦„' }
45+
]);
46+
expect(host.hostElement.textContent).toEqual(' 🦊 πŸ¦„ ');
47+
48+
host.setHostInput('animals', [
49+
{ animal: '🦊' },
50+
{ animal: 'πŸ™€' },
51+
{ animal: 'πŸ¦„' }
52+
]);
53+
expect(host.hostElement.textContent).toEqual(' 🦊 πŸ™€ πŸ¦„ ');
2554
});
2655

2756
it('should throw exception', () => {

0 commit comments

Comments
Β (0)