Last active
September 18, 2023 01:19
-
-
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.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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