@@ -0,0 +1,34 @@
|
||||
import {
|
||||
ResolvedReflectiveProvider,
|
||||
Directive,
|
||||
DynamicComponentLoader,
|
||||
ViewContainerRef,
|
||||
Input,
|
||||
ComponentRef,
|
||||
ComponentFactory,
|
||||
ReflectiveInjector
|
||||
} from 'angular2/core';
|
||||
import {RouterOutletMap} from '../router';
|
||||
import {isPresent} from 'angular2/src/facade/lang';
|
||||
|
||||
@Directive({selector: 'router-outlet'})
|
||||
export class RouterOutlet {
|
||||
private _loaded: ComponentRef;
|
||||
public outletMap: RouterOutletMap;
|
||||
@Input() name: string = "";
|
||||
|
||||
constructor(parentOutletMap: RouterOutletMap, private _location: ViewContainerRef) {
|
||||
parentOutletMap.registerOutlet("", this);
|
||||
}
|
||||
|
||||
load(factory: ComponentFactory, providers: ResolvedReflectiveProvider[],
|
||||
outletMap: RouterOutletMap): ComponentRef {
|
||||
if (isPresent(this._loaded)) {
|
||||
this._loaded.destroy();
|
||||
}
|
||||
this.outletMap = outletMap;
|
||||
let inj = ReflectiveInjector.fromResolvedProviders(providers, this._location.parentInjector);
|
||||
this._loaded = this._location.createComponent(factory, this._location.length, inj, []);
|
||||
return this._loaded;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
import {RouteSegment, Tree} from './segments';
|
||||
|
||||
export interface OnActivate {
|
||||
routerOnActivate(curr: RouteSegment, prev?: RouteSegment, currTree?: Tree<RouteSegment>,
|
||||
prevTree?: Tree<RouteSegment>): void;
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
import './interfaces.dart';
|
||||
bool hasLifecycleHook(String name, Object obj) {
|
||||
if (name == "routerOnActivate") return obj is OnActivate;
|
||||
return false;
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
import {Type} from 'angular2/src/facade/lang';
|
||||
|
||||
export function hasLifecycleHook(name: string, obj: Object): boolean {
|
||||
let type = obj.constructor;
|
||||
if (!(type instanceof Type)) return false;
|
||||
return name in(<any>type).prototype;
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
import {provide, ReflectiveInjector, ComponentResolver} from 'angular2/core';
|
||||
import {RouterOutlet} from './directives/router_outlet';
|
||||
import {Type, isBlank, isPresent} from 'angular2/src/facade/lang';
|
||||
import {RouterUrlParser} from './router_url_parser';
|
||||
import {recognize} from './recognize';
|
||||
import {equalSegments, routeSegmentComponentFactory, RouteSegment, Tree} from './segments';
|
||||
import {hasLifecycleHook} from './lifecycle_reflector';
|
||||
|
||||
export class RouterOutletMap {
|
||||
/** @internal */
|
||||
_outlets: {[name: string]: RouterOutlet} = {};
|
||||
registerOutlet(name: string, outlet: RouterOutlet): void { this._outlets[name] = outlet; }
|
||||
}
|
||||
|
||||
export class Router {
|
||||
private prevTree: Tree<RouteSegment>;
|
||||
constructor(private _componentType: Type, private _componentResolver: ComponentResolver,
|
||||
private _urlParser: RouterUrlParser, private _routerOutletMap: RouterOutletMap) {}
|
||||
|
||||
navigateByUrl(url: string): Promise<void> {
|
||||
let urlSegmentTree = this._urlParser.parse(url.substring(1));
|
||||
return recognize(this._componentResolver, this._componentType, urlSegmentTree)
|
||||
.then(currTree => {
|
||||
let prevRoot = isPresent(this.prevTree) ? this.prevTree.root : null;
|
||||
_loadSegments(currTree, currTree.root, this.prevTree, prevRoot, this,
|
||||
this._routerOutletMap);
|
||||
this.prevTree = currTree;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function _loadSegments(currTree: Tree<RouteSegment>, curr: RouteSegment,
|
||||
prevTree: Tree<RouteSegment>, prev: RouteSegment, router: Router,
|
||||
parentOutletMap: RouterOutletMap): void {
|
||||
let outlet = parentOutletMap._outlets[curr.outlet];
|
||||
|
||||
let outletMap;
|
||||
if (equalSegments(curr, prev)) {
|
||||
outletMap = outlet.outletMap;
|
||||
} else {
|
||||
outletMap = new RouterOutletMap();
|
||||
let resolved = ReflectiveInjector.resolve(
|
||||
[provide(RouterOutletMap, {useValue: outletMap}), provide(RouteSegment, {useValue: curr})]);
|
||||
let ref = outlet.load(routeSegmentComponentFactory(curr), resolved, outletMap);
|
||||
if (hasLifecycleHook("routerOnActivate", ref.instance)) {
|
||||
ref.instance.routerOnActivate(curr, prev, currTree, prevTree);
|
||||
}
|
||||
}
|
||||
|
||||
if (isPresent(currTree.firstChild(curr))) {
|
||||
let cc = currTree.firstChild(curr);
|
||||
let pc = isBlank(prevTree) ? null : prevTree.firstChild(prev);
|
||||
_loadSegments(currTree, cc, prevTree, pc, router, outletMap);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user