forked from ngrx/router
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcomponent-renderer.ts
98 lines (85 loc) · 2.66 KB
/
component-renderer.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
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
import 'rxjs/add/observable/of';
import 'rxjs/add/operator/let';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/mergeMap';
import {
DynamicComponentLoader,
ElementRef,
Injector,
Injectable,
Inject,
Type,
Provider,
ResolvedProvider,
OpaqueToken,
ComponentRef
} from 'angular2/core';
import { Observable } from 'rxjs/Observable';
import { Async, ResourceLoader } from './resource-loader';
import { compose } from './util';
import { Route, SimpleRoute } from './route';
import { Middleware, identity, provideMiddlewareForToken } from './middleware';
export const PRE_RENDER_MIDDLEWARE = new OpaqueToken(
'@ngrx/router Pre Render Middleware'
);
export const POST_RENDER_MIDDLEWARE = new OpaqueToken(
'@ngrx/router Post Render Middleware'
);
export const usePreRenderMiddleware = provideMiddlewareForToken(
PRE_RENDER_MIDDLEWARE
);
export const usePostRenderMiddleware = provideMiddlewareForToken(
POST_RENDER_MIDDLEWARE
);
export interface RenderInstruction {
component: Type;
injector: Injector;
providers: Provider[];
}
export interface ResolvedInstruction {
component: Type;
providers: ResolvedProvider[];
ref: ElementRef;
dcl: DynamicComponentLoader;
}
@Injectable()
export class ComponentRenderer {
constructor(
private _loader: ResourceLoader,
@Inject(PRE_RENDER_MIDDLEWARE) private _preMiddleware: Middleware[],
@Inject(POST_RENDER_MIDDLEWARE) private _postMiddleware: Middleware[]
) { }
render(
route: Route,
components: SimpleRoute,
injector: Injector,
ref: ElementRef,
dcl: DynamicComponentLoader,
providers: Provider[]
) {
return Observable.of(route)
.mergeMap(route => this._loadComponent(components))
.map<RenderInstruction>(component => {
return { component, injector, providers };
})
.let<RenderInstruction>(compose(...this._preMiddleware))
.map<ResolvedInstruction>(instruction => {
const providers = Injector.resolve(instruction.providers);
const component = instruction.component;
return { providers, component, ref, dcl };
})
.mergeMap(instruction => this.renderComponent(instruction))
.let<ComponentRef>(compose(...this._postMiddleware));
}
renderComponent({ component, providers, ref, dcl }: ResolvedInstruction) {
return dcl.loadNextToLocation(component, ref, providers);
}
private _loadComponent(route: SimpleRoute): Promise<Type> {
return this._loader.load(route.component, route.loadComponent);
}
}
export const COMPONENT_RENDERER_PROVIDERS = [
usePreRenderMiddleware(identity),
usePostRenderMiddleware(identity),
new Provider(ComponentRenderer, { useClass: ComponentRenderer })
];