Skip to content

Commit 1d47d57

Browse files
committed
Fix PageRouterOutlet crash with beta 16+
1 parent aa69f5e commit 1d47d57

File tree

2 files changed

+55
-11
lines changed

2 files changed

+55
-11
lines changed
Lines changed: 36 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
import {DynamicComponentLoader, ComponentRef, ViewContainerRef, Component, Type, ViewChild} from '@angular/core';
22

3+
interface PendingLoadEntry {
4+
componentType: Type;
5+
resolveCallback: (ComponentRef) => void;
6+
}
7+
38
/**
49
* Wrapper component used for loading components when navigating
510
* It uses DetachedContainer as selector so that it is containerRef is not attached to the visual tree.
@@ -9,14 +14,42 @@ import {DynamicComponentLoader, ComponentRef, ViewContainerRef, Component, Type,
914
template: `<Placeholder #loader></Placeholder>`
1015
})
1116
export class DetachedLoader {
12-
17+
@ViewChild('loader', { read: ViewContainerRef }) containerRef: ViewContainerRef;
18+
private viewLoaded = false;
19+
20+
private pendingLoads: PendingLoadEntry[] = [];
21+
1322
constructor(
14-
private containerRef: ViewContainerRef,
1523
private loader: DynamicComponentLoader
1624
) {
1725
}
1826

19-
public loadComponent(componentType: Type): Promise<ComponentRef> {
27+
public ngAfterViewInit() {
28+
this.viewLoaded = true;
29+
30+
this.pendingLoads.forEach(loadEntry => {
31+
this.loadInLocation(loadEntry.componentType).then(loadedRef => {
32+
loadEntry.resolveCallback(loadedRef);
33+
});
34+
});
35+
}
36+
37+
private loadInLocation(componentType: Type): Promise<ComponentRef> {
2038
return this.loader.loadNextToLocation(componentType, this.containerRef);
2139
}
40+
41+
public loadComponent(componentType: Type): Promise<ComponentRef> {
42+
// Check if called before placeholder is initialized.
43+
// Delay load if so.
44+
if (this.viewLoaded) {
45+
return this.loadInLocation(componentType);
46+
} else {
47+
return new Promise((resolve, reject) => {
48+
this.pendingLoads.push({
49+
componentType: componentType,
50+
resolveCallback: resolve
51+
});
52+
});
53+
}
54+
}
2255
}

src/nativescript-angular/router/page-router-outlet.ts

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,12 @@ import {PromiseWrapper} from '@angular/core/src/facade/async';
22
import {isBlank, isPresent} from '@angular/core/src/facade/lang';
33
import {StringMapWrapper} from '@angular/core/src/facade/collection';
44

5-
import {Attribute, DynamicComponentLoader, ComponentRef, ViewContainerRef,
6-
ElementRef, ReflectiveInjector, provide, Type, Component} from '@angular/core';
5+
import {
6+
Attribute, DynamicComponentLoader, ComponentRef,
7+
ViewContainerRef, ViewChild, ElementRef,
8+
ReflectiveInjector, provide, Type,
9+
Component, Inject
10+
} from '@angular/core';
711

812
import * as routerHooks from '@angular/router/src/lifecycle/lifecycle_annotations';
913
import {hasLifecycleHook} from '@angular/router/src/lifecycle/route_lifecycle_reflector';
@@ -13,9 +17,12 @@ import {Router, RouterOutlet, RouteData, RouteParams, ComponentInstruction,
1317
import {LocationStrategy} from '@angular/common';
1418
import {topmost} from "ui/frame";
1519
import {Page, NavigatedData} from "ui/page";
20+
import {DEVICE} from "../platform-providers";
21+
import {Device} from "platform";
1622
import {log} from "./common";
1723
import {NSLocationStrategy} from "./ns-location-strategy";
1824
import {DetachedLoader} from "../common/detached-loader";
25+
import {ViewUtil} from "../view-util";
1926

2027
let _resolveToTrue = PromiseWrapper.resolve(true);
2128

@@ -66,13 +73,19 @@ export class PageRouterOutlet extends RouterOutlet {
6673

6774
private componentRef: ComponentRef = null;
6875
private currentInstruction: ComponentInstruction = null;
76+
private viewUtil: ViewUtil;
77+
@ViewChild('loader', { read: ViewContainerRef }) childContainerRef: ViewContainerRef;
6978

70-
constructor(private containerRef: ViewContainerRef,
79+
constructor(
80+
private containerRef: ViewContainerRef,
7181
private loader: DynamicComponentLoader,
7282
private parentRouter: Router,
7383
@Attribute('name') nameAttr: string,
74-
private location: NSLocationStrategy) {
84+
private location: NSLocationStrategy,
85+
@Inject(DEVICE) device: Device
86+
) {
7587
super(containerRef, loader, parentRouter, nameAttr);
88+
this.viewUtil = new ViewUtil(device);
7689
}
7790

7891
/**
@@ -128,7 +141,7 @@ export class PageRouterOutlet extends RouterOutlet {
128141

129142
const page = new Page();
130143
providersArray.push(provide(Page, { useValue: page }));
131-
resultPromise = this.loader.loadNextToLocation(DetachedLoader, this.containerRef, ReflectiveInjector.resolve(providersArray))
144+
resultPromise = this.loader.loadNextToLocation(DetachedLoader, this.childContainerRef, ReflectiveInjector.resolve(providersArray))
132145
.then((pageComponentRef) => {
133146
loaderRef = pageComponentRef;
134147
return (<DetachedLoader>loaderRef.instance).loadComponent(componentType);
@@ -154,9 +167,7 @@ export class PageRouterOutlet extends RouterOutlet {
154167
//Component loaded. Find its root native view.
155168
const componentView = componentRef.location.nativeElement;
156169
//Remove it from original native parent.
157-
if (<any>componentView.parent) {
158-
(<any>componentView.parent).removeChild(componentView);
159-
}
170+
this.viewUtil.removeChild(componentView.parent, componentView);
160171
//Add it to the new page
161172
page.content = componentView;
162173

0 commit comments

Comments
 (0)