forked from NativeScript/nativescript-angular
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdetached-loader.ts
61 lines (51 loc) · 2.31 KB
/
detached-loader.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
import { ComponentRef, ComponentFactory, ViewContainerRef, Component, Type, ComponentFactoryResolver, ChangeDetectorRef, ApplicationRef, OnDestroy } from '@angular/core';
import { Trace } from '@nativescript/core';
/**
* Wrapper component used for loading components when navigating
* It uses DetachedContainer as selector so that it is containerRef is not attached to
* the visual tree.
*/
@Component({
selector: 'DetachedContainer',
template: `<Placeholder #loader></Placeholder>`,
})
export class DetachedLoader implements OnDestroy {
private disposeFunctions: Array<() => void> = [];
// tslint:disable-line:component-class-suffix
constructor(private resolver: ComponentFactoryResolver, private changeDetector: ChangeDetectorRef, private containerRef: ViewContainerRef, private appRef: ApplicationRef) {}
private loadInLocation(componentType: Type<any>): Promise<ComponentRef<any>> {
const factory = this.resolver.resolveComponentFactory(componentType);
const componentRef = factory.create(this.containerRef.injector);
this.appRef.attachView(componentRef.hostView);
this.disposeFunctions.push(() => {
this.appRef.detachView(componentRef.hostView);
componentRef.destroy();
});
// Component is created, built may not be checked if we are loading
// inside component with OnPush CD strategy. Mark us for check to be sure CD will reach us.
// We are inside a promise here so no need for setTimeout - CD should trigger
// after the promise.
Trace.write('DetachedLoader.loadInLocation component loaded -> markForCheck', 'detached-loader');
return Promise.resolve(componentRef);
}
public ngOnDestroy() {
this.disposeFunctions.forEach((fn) => fn());
}
public detectChanges() {
this.changeDetector.markForCheck();
}
// TODO: change this API -- async promises not needed here anymore.
public loadComponent(componentType: Type<any>): Promise<ComponentRef<any>> {
Trace.write('DetachedLoader.loadComponent', 'detached-loader');
return this.loadInLocation(componentType);
}
public loadWithFactory<T>(factory: ComponentFactory<T>): ComponentRef<T> {
const componentRef = factory.create(this.containerRef.injector);
this.appRef.attachView(componentRef.hostView);
this.disposeFunctions.push(() => {
this.appRef.detachView(componentRef.hostView);
componentRef.destroy();
});
return componentRef;
}
}