Skip to content

Instantly share code, notes, and snippets.

@dongyuwei
Last active September 18, 2023 01:19
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dongyuwei/31ee679a60a7d84925e56153170b48b3 to your computer and use it in GitHub Desktop.
Save dongyuwei/31ee679a60a7d84925e56153170b48b3 to your computer and use it in GitHub Desktop.
cacheable-ng-for.directive. It's buggy now. Don't use it. I'm testing it.
import {
ChangeDetectorRef,
Directive,
DoCheck, Injector,
Input, OnChanges, SimpleChanges,
TemplateRef,
TrackByFunction,
ViewContainerRef
} from "@angular/core";
@Directive({
selector: '[appNgFor]'
})
export class NgForCacheDirective implements DoCheck, OnChanges {
@Input() appNgForOf: any[];
@Input() appNgForTrackBy: TrackByFunction<any>;
loadedViews = new Map();
constructor(private template: TemplateRef<any>,
private viewContainer: ViewContainerRef,
private parentInjector: Injector){
}
ngDoCheck() {
const changes = this.updateViews();
if (changes) {
this.parentInjector.get(ChangeDetectorRef).detectChanges();
}
}
ngOnChanges(changes: SimpleChanges) {
console.warn(111, changes['appNgForOf'])
// if(changes['appNgForOf']) {
// requestAnimationFrame(() => {
// this.updateViews();
// })
// }
}
updateViews() {
let changes = false;
// Insert new views
for(let i = 0; i < this.appNgForOf.length; i++) {
if(!this.loadedViews.has(i)) {
this.loadedViews.set(i, this.viewContainer.createEmbeddedView(this.template));
changes = true;
}
}
// Update context of existing views
this.loadedViews.forEach((view, key) => {
const item = this.appNgForOf[key];
// console.warn(111, item, index)
view.context.$implicit = item;
if (this.appNgForTrackBy) {
view.context.$index =
this.appNgForOf.findIndex(x => this.appNgForTrackBy(key, x) === this.appNgForTrackBy(key, item));
} else {
view.context.$index = key;
}
});
// Remove old views
const removals = [];
this.loadedViews.forEach((view, index) => {
if(index >= this.appNgForOf.length) {
removals.push(index);
changes = true;
}
});
removals.forEach(i => this.loadedViews.delete(i));
return changes;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment