refactor(router): improve control flow of descendant route activation
This commit is contained in:
parent
6b02cb9b44
commit
c29ab86d85
48
modules/angular2/src/router/instruction.js
vendored
48
modules/angular2/src/router/instruction.js
vendored
@ -16,26 +16,32 @@ export class RouteParams {
|
|||||||
|
|
||||||
export class Instruction {
|
export class Instruction {
|
||||||
component:any;
|
component:any;
|
||||||
_children:StringMap<string, Instruction>;
|
_children:Map<string, Instruction>;
|
||||||
router:any;
|
|
||||||
matchedUrl:string;
|
// the part of the URL captured by this instruction
|
||||||
params:StringMap<string, string>;
|
capturedUrl:string;
|
||||||
|
|
||||||
|
// the part of the URL captured by this instruction and all children
|
||||||
|
accumulatedUrl:string;
|
||||||
|
|
||||||
|
params:Map<string, string>;
|
||||||
reuse:boolean;
|
reuse:boolean;
|
||||||
cost:number;
|
cost:number;
|
||||||
|
|
||||||
constructor({params, component, children, matchedUrl, parentCost}:{params:StringMap, component:any, children:StringMap, matchedUrl:string, cost:number} = {}) {
|
constructor({params, component, children, matchedUrl, parentCost}:{params:StringMap, component:any, children:StringMap, matchedUrl:string, cost:number} = {}) {
|
||||||
this.reuse = false;
|
this.reuse = false;
|
||||||
this.matchedUrl = matchedUrl;
|
this.capturedUrl = matchedUrl;
|
||||||
|
this.accumulatedUrl = matchedUrl;
|
||||||
this.cost = parentCost;
|
this.cost = parentCost;
|
||||||
if (isPresent(children)) {
|
if (isPresent(children)) {
|
||||||
this._children = children;
|
this._children = children;
|
||||||
var childUrl;
|
var childUrl;
|
||||||
StringMapWrapper.forEach(this._children, (child, _) => {
|
StringMapWrapper.forEach(this._children, (child, _) => {
|
||||||
childUrl = child.matchedUrl;
|
childUrl = child.accumulatedUrl;
|
||||||
this.cost += child.cost;
|
this.cost += child.cost;
|
||||||
});
|
});
|
||||||
if (isPresent(childUrl)) {
|
if (isPresent(childUrl)) {
|
||||||
this.matchedUrl += childUrl;
|
this.accumulatedUrl += childUrl;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
this._children = StringMapWrapper.create();
|
this._children = StringMapWrapper.create();
|
||||||
@ -44,7 +50,11 @@ export class Instruction {
|
|||||||
this.params = params;
|
this.params = params;
|
||||||
}
|
}
|
||||||
|
|
||||||
getChildInstruction(outletName:string): Instruction {
|
hasChild(outletName:string):Instruction {
|
||||||
|
return StringMapWrapper.contains(this._children, outletName);
|
||||||
|
}
|
||||||
|
|
||||||
|
getChild(outletName:string):Instruction {
|
||||||
return StringMapWrapper.get(this._children, outletName);
|
return StringMapWrapper.get(this._children, outletName);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -52,37 +62,23 @@ export class Instruction {
|
|||||||
StringMapWrapper.forEach(this._children, fn);
|
StringMapWrapper.forEach(this._children, fn);
|
||||||
}
|
}
|
||||||
|
|
||||||
mapChildrenAsync(fn):Promise {
|
|
||||||
return mapObjAsync(this._children, fn);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Does a synchronous, breadth-first traversal of the graph of instructions.
|
* Does a synchronous, breadth-first traversal of the graph of instructions.
|
||||||
* Takes a function with signature:
|
* Takes a function with signature:
|
||||||
* (parent:Instruction, child:Instruction) => {}
|
* (parent:Instruction, child:Instruction) => {}
|
||||||
*/
|
*/
|
||||||
traverseSync(fn:Function): void {
|
traverseSync(fn:Function): void {
|
||||||
this.forEachChild((childInstruction, _) => fn(this, childInstruction));
|
this.forEachChild(fn);
|
||||||
this.forEachChild((childInstruction, _) => childInstruction.traverseSync(fn));
|
this.forEachChild((childInstruction, _) => childInstruction.traverseSync(fn));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Does an asynchronous, breadth-first traversal of the graph of instructions.
|
|
||||||
* Takes a function with signature:
|
|
||||||
* (child:Instruction, parentOutletName:string) => {}
|
|
||||||
*/
|
|
||||||
traverseAsync(fn:Function):Promise {
|
|
||||||
return this.mapChildrenAsync(fn)
|
|
||||||
.then((_) => this.mapChildrenAsync((childInstruction, _) => childInstruction.traverseAsync(fn)));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Takes a currently active instruction and sets a reuse flag on this instruction
|
* Takes a currently active instruction and sets a reuse flag on this instruction
|
||||||
*/
|
*/
|
||||||
reuseComponentsFrom(oldInstruction:Instruction): void {
|
reuseComponentsFrom(oldInstruction:Instruction): void {
|
||||||
this.forEachChild((childInstruction, outletName) => {
|
this.traverseSync((childInstruction, outletName) => {
|
||||||
var oldInstructionChild = oldInstruction.getChildInstruction(outletName);
|
var oldInstructionChild = oldInstruction.getChild(outletName);
|
||||||
if (shouldReuseComponent(childInstruction, oldInstructionChild)) {
|
if (shouldReuseComponent(childInstruction, oldInstructionChild)) {
|
||||||
childInstruction.reuse = true;
|
childInstruction.reuse = true;
|
||||||
}
|
}
|
||||||
@ -104,5 +100,3 @@ function mapObj(obj:StringMap, fn: Function):List {
|
|||||||
StringMapWrapper.forEach(obj, (value, key) => ListWrapper.push(result, fn(value, key)));
|
StringMapWrapper.forEach(obj, (value, key) => ListWrapper.push(result, fn(value, key)));
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
export var noopInstruction = new Instruction();
|
|
||||||
|
9
modules/angular2/src/router/pipeline.js
vendored
9
modules/angular2/src/router/pipeline.js
vendored
@ -11,15 +11,6 @@ export class Pipeline {
|
|||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
this.steps = [
|
this.steps = [
|
||||||
instruction => instruction.traverseSync((parentInstruction, childInstruction) => {
|
|
||||||
childInstruction.router = parentInstruction.router.childRouter(childInstruction.component);
|
|
||||||
}),
|
|
||||||
instruction => instruction.router.traverseOutlets((outlet, name) => {
|
|
||||||
return outlet.canDeactivate(instruction.getChildInstruction(name));
|
|
||||||
}),
|
|
||||||
instruction => instruction.router.traverseOutlets((outlet, name) => {
|
|
||||||
return outlet.canActivate(instruction.getChildInstruction(name));
|
|
||||||
}),
|
|
||||||
instruction => instruction.router.activateOutlets(instruction)
|
instruction => instruction.router.activateOutlets(instruction)
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
111
modules/angular2/src/router/router.js
vendored
111
modules/angular2/src/router/router.js
vendored
@ -15,6 +15,15 @@ import {Location} from './location';
|
|||||||
* You can see the state of the router by inspecting the read-only field `router.navigating`.
|
* You can see the state of the router by inspecting the read-only field `router.navigating`.
|
||||||
* This may be useful for showing a spinner, for instance.
|
* This may be useful for showing a spinner, for instance.
|
||||||
*
|
*
|
||||||
|
* ## Concepts
|
||||||
|
* Routers and component instances have a 1:1 correspondence.
|
||||||
|
*
|
||||||
|
* The router holds reference to a number of "outlets." An outlet is a placeholder that the
|
||||||
|
* router dynamically fills in depending on the current URL.
|
||||||
|
*
|
||||||
|
* When the router navigates from a URL, it must first recognizes it and serialize it into an `Instruction`.
|
||||||
|
* The router uses the `RouteRegistry` to get an `Instruction`.
|
||||||
|
*
|
||||||
* @exportedAs angular2/router
|
* @exportedAs angular2/router
|
||||||
*/
|
*/
|
||||||
export class Router {
|
export class Router {
|
||||||
@ -28,19 +37,16 @@ export class Router {
|
|||||||
|
|
||||||
_pipeline:Pipeline;
|
_pipeline:Pipeline;
|
||||||
_registry:RouteRegistry;
|
_registry:RouteRegistry;
|
||||||
_outlets:Map<any, RouterOutlet>;
|
_outlets:Map<any, Outlet>;
|
||||||
_children:Map<any, Router>;
|
|
||||||
_subject:EventEmitter;
|
_subject:EventEmitter;
|
||||||
_location:Location;
|
|
||||||
|
|
||||||
constructor(registry:RouteRegistry, pipeline:Pipeline, location:Location, parent:Router, hostComponent) {
|
|
||||||
|
constructor(registry:RouteRegistry, pipeline:Pipeline, parent:Router, hostComponent:any) {
|
||||||
this.hostComponent = hostComponent;
|
this.hostComponent = hostComponent;
|
||||||
this.navigating = false;
|
this.navigating = false;
|
||||||
this.parent = parent;
|
this.parent = parent;
|
||||||
this.previousUrl = null;
|
this.previousUrl = null;
|
||||||
this._outlets = MapWrapper.create();
|
this._outlets = MapWrapper.create();
|
||||||
this._children = MapWrapper.create();
|
|
||||||
this._location = location;
|
|
||||||
this._registry = registry;
|
this._registry = registry;
|
||||||
this._pipeline = pipeline;
|
this._pipeline = pipeline;
|
||||||
this._subject = new EventEmitter();
|
this._subject = new EventEmitter();
|
||||||
@ -51,25 +57,18 @@ export class Router {
|
|||||||
/**
|
/**
|
||||||
* Constructs a child router. You probably don't need to use this unless you're writing a reusable component.
|
* Constructs a child router. You probably don't need to use this unless you're writing a reusable component.
|
||||||
*/
|
*/
|
||||||
childRouter(outletName = 'default'): Router {
|
childRouter(hostComponent:any): Router {
|
||||||
var router = MapWrapper.get(this._children, outletName);
|
return new ChildRouter(this, hostComponent);
|
||||||
|
|
||||||
if (isBlank(router)) {
|
|
||||||
router = new ChildRouter(this, outletName);
|
|
||||||
MapWrapper.set(this._children, outletName, router);
|
|
||||||
}
|
|
||||||
|
|
||||||
return router;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Register an object to notify of route changes. You probably don't need to use this unless you're writing a reusable component.
|
* Register an object to notify of route changes. You probably don't need to use this unless you're writing a reusable component.
|
||||||
*/
|
*/
|
||||||
registerOutlet(outlet:RouterOutlet, name: string = 'default'):Promise {
|
registerOutlet(outlet:RouterOutlet, name: string = 'default'): Promise {
|
||||||
MapWrapper.set(this._outlets, name, outlet);
|
MapWrapper.set(this._outlets, name, outlet);
|
||||||
if (isPresent(this._currentInstruction)) {
|
if (isPresent(this._currentInstruction)) {
|
||||||
var childInstruction = this._currentInstruction.getChildInstruction(name);
|
var childInstruction = this._currentInstruction.getChild(name);
|
||||||
return outlet.activate(childInstruction);
|
return outlet.activate(childInstruction);
|
||||||
}
|
}
|
||||||
return PromiseWrapper.resolve(true);
|
return PromiseWrapper.resolve(true);
|
||||||
@ -77,7 +76,7 @@ export class Router {
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update the routing configuration and trigger a navigation.
|
* Dynamically update the routing configuration and trigger a navigation.
|
||||||
*
|
*
|
||||||
* # Usage
|
* # Usage
|
||||||
*
|
*
|
||||||
@ -98,7 +97,6 @@ export class Router {
|
|||||||
config(config:any): Promise {
|
config(config:any): Promise {
|
||||||
if (config instanceof List) {
|
if (config instanceof List) {
|
||||||
config.forEach((configObject) => {
|
config.forEach((configObject) => {
|
||||||
// TODO: this is a hack
|
|
||||||
this._registry.config(this.hostComponent, configObject);
|
this._registry.config(this.hostComponent, configObject);
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
@ -110,6 +108,9 @@ export class Router {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Navigate to a URL. Returns a promise that resolves to the canonical URL for the route.
|
* Navigate to a URL. Returns a promise that resolves to the canonical URL for the route.
|
||||||
|
*
|
||||||
|
* If the given URL begins with a `/`, router will navigate absolutely.
|
||||||
|
* If the given URL does not begin with `/`, the router will navigate relative to this component.
|
||||||
*/
|
*/
|
||||||
navigate(url:string):Promise {
|
navigate(url:string):Promise {
|
||||||
if (this.navigating) {
|
if (this.navigating) {
|
||||||
@ -124,19 +125,16 @@ export class Router {
|
|||||||
return PromiseWrapper.resolve(false);
|
return PromiseWrapper.resolve(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(isPresent(this._currentInstruction)) {
|
if (isPresent(this._currentInstruction)) {
|
||||||
matchedInstruction.reuseComponentsFrom(this._currentInstruction);
|
matchedInstruction.reuseComponentsFrom(this._currentInstruction);
|
||||||
}
|
}
|
||||||
|
|
||||||
matchedInstruction.router = this;
|
|
||||||
this._startNavigating();
|
this._startNavigating();
|
||||||
|
|
||||||
var result = this._pipeline.process(matchedInstruction)
|
var result = this.commit(matchedInstruction)
|
||||||
.then((_) => {
|
.then((_) => {
|
||||||
this._location.go(matchedInstruction.matchedUrl);
|
ObservableWrapper.callNext(this._subject, matchedInstruction.accumulatedUrl);
|
||||||
ObservableWrapper.callNext(this._subject, matchedInstruction.matchedUrl);
|
|
||||||
this._finishNavigating();
|
this._finishNavigating();
|
||||||
this._currentInstruction = matchedInstruction;
|
|
||||||
});
|
});
|
||||||
|
|
||||||
PromiseWrapper.catchError(result, (_) => this._finishNavigating());
|
PromiseWrapper.catchError(result, (_) => this._finishNavigating());
|
||||||
@ -152,6 +150,7 @@ export class Router {
|
|||||||
this.navigating = false;
|
this.navigating = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Subscribe to URL updates from the router
|
* Subscribe to URL updates from the router
|
||||||
*/
|
*/
|
||||||
@ -160,25 +159,46 @@ export class Router {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
activateOutlets(instruction:Instruction):Promise {
|
/**
|
||||||
return this._queryOutlets((outlet, name) => {
|
*
|
||||||
var childInstruction = instruction.getChildInstruction(name);
|
*/
|
||||||
if (childInstruction.reuse) {
|
commit(instruction:Instruction):Promise {
|
||||||
return PromiseWrapper.resolve(true);
|
this._currentInstruction = instruction;
|
||||||
|
|
||||||
|
// collect all outlets that do not have a corresponding child instruction
|
||||||
|
// and remove them from the internal map of child outlets
|
||||||
|
var toDeactivate = ListWrapper.create();
|
||||||
|
MapWrapper.forEach(this._outlets, (outlet, outletName) => {
|
||||||
|
if (!instruction.hasChild(outletName)) {
|
||||||
|
MapWrapper.delete(this._outlets, outletName);
|
||||||
|
ListWrapper.push(toDeactivate, outlet);
|
||||||
}
|
}
|
||||||
return outlet.activate(childInstruction);
|
});
|
||||||
})
|
|
||||||
.then((_) => instruction.mapChildrenAsync((instruction, _) => {
|
return PromiseWrapper.all(ListWrapper.map(toDeactivate, (outlet) => outlet.deactivate()))
|
||||||
return instruction.router.activateOutlets(instruction);
|
.then((_) => this.activate(instruction));
|
||||||
}));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
traverseOutlets(fn):Promise {
|
|
||||||
return this._queryOutlets(fn)
|
/**
|
||||||
.then((_) => mapObjAsync(this._children, (child, _) => child.traverseOutlets(fn)));
|
* Recursively remove all components contained by this router's outlets.
|
||||||
|
* Calls deactivate hooks on all descendant components
|
||||||
|
*/
|
||||||
|
deactivate():Promise {
|
||||||
|
return this._eachOutletAsync((outlet) => outlet.deactivate);
|
||||||
}
|
}
|
||||||
|
|
||||||
_queryOutlets(fn):Promise {
|
|
||||||
|
/**
|
||||||
|
* Recursively activate.
|
||||||
|
* Calls the "activate" hook on descendant components.
|
||||||
|
*/
|
||||||
|
activate(instruction:Instruction):Promise {
|
||||||
|
return this._eachOutletAsync((outlet, name) => outlet.activate(instruction.getChild(name)));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
_eachOutletAsync(fn):Promise {
|
||||||
return mapObjAsync(this._outlets, fn);
|
return mapObjAsync(this._outlets, fn);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -212,17 +232,26 @@ export class Router {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export class RootRouter extends Router {
|
export class RootRouter extends Router {
|
||||||
|
_location:Location;
|
||||||
|
|
||||||
constructor(registry:RouteRegistry, pipeline:Pipeline, location:Location, hostComponent:Type) {
|
constructor(registry:RouteRegistry, pipeline:Pipeline, location:Location, hostComponent:Type) {
|
||||||
super(registry, pipeline, location, null, hostComponent);
|
super(registry, pipeline, null, hostComponent);
|
||||||
|
this._location = location;
|
||||||
this._location.subscribe((change) => this.navigate(change['url']));
|
this._location.subscribe((change) => this.navigate(change['url']));
|
||||||
this._registry.configFromComponent(hostComponent);
|
this._registry.configFromComponent(hostComponent);
|
||||||
this.navigate(location.path());
|
this.navigate(location.path());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
commit(instruction):Promise {
|
||||||
|
return super.commit(instruction).then((_) => {
|
||||||
|
this._location.go(instruction.accumulatedUrl);
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class ChildRouter extends Router {
|
class ChildRouter extends Router {
|
||||||
constructor(parent:Router, hostComponent) {
|
constructor(parent:Router, hostComponent) {
|
||||||
super(parent._registry, parent._pipeline, parent._location, parent, hostComponent);
|
super(parent._registry, parent._pipeline, parent, hostComponent);
|
||||||
this.parent = parent;
|
this.parent = parent;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
45
modules/angular2/src/router/router_outlet.js
vendored
45
modules/angular2/src/router/router_outlet.js
vendored
@ -1,5 +1,5 @@
|
|||||||
import {Promise, PromiseWrapper} from 'angular2/src/facade/async';
|
import {Promise, PromiseWrapper} from 'angular2/src/facade/async';
|
||||||
import {isBlank} from 'angular2/src/facade/lang';
|
import {isBlank, isPresent} from 'angular2/src/facade/lang';
|
||||||
|
|
||||||
import {Directive} from 'angular2/src/core/annotations_impl/annotations';
|
import {Directive} from 'angular2/src/core/annotations_impl/annotations';
|
||||||
import {Attribute} from 'angular2/src/core/annotations_impl/di';
|
import {Attribute} from 'angular2/src/core/annotations_impl/di';
|
||||||
@ -9,43 +9,74 @@ import {Injector, bind} from 'angular2/di';
|
|||||||
import * as routerMod from './router';
|
import * as routerMod from './router';
|
||||||
import {Instruction, RouteParams} from './instruction'
|
import {Instruction, RouteParams} from './instruction'
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A router outlet is a placeholder that Angular dynamically fills based on the application's route.
|
||||||
|
*
|
||||||
|
* ## Use
|
||||||
|
*
|
||||||
|
* ```
|
||||||
|
* <router-outlet></router-outlet>
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* Route outlets can also optionally have a name:
|
||||||
|
*
|
||||||
|
* ```
|
||||||
|
* <router-outlet name="side"></router-outlet>
|
||||||
|
* <router-outlet name="main"></router-outlet>
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
*/
|
||||||
@Directive({
|
@Directive({
|
||||||
selector: 'router-outlet'
|
selector: 'router-outlet'
|
||||||
})
|
})
|
||||||
export class RouterOutlet {
|
export class RouterOutlet {
|
||||||
_compiler:Compiler;
|
_compiler:Compiler;
|
||||||
_injector:Injector;
|
_injector:Injector;
|
||||||
_router:routerMod.Router;
|
_parentRouter:routerMod.Router;
|
||||||
|
_childRouter:routerMod.Router;
|
||||||
_viewContainer:ViewContainerRef;
|
_viewContainer:ViewContainerRef;
|
||||||
|
|
||||||
constructor(viewContainer:ViewContainerRef, compiler:Compiler, router:routerMod.Router, injector:Injector, @Attribute('name') nameAttr:String) {
|
constructor(viewContainer:ViewContainerRef, compiler:Compiler, router:routerMod.Router, injector:Injector, @Attribute('name') nameAttr:String) {
|
||||||
if (isBlank(nameAttr)) {
|
if (isBlank(nameAttr)) {
|
||||||
nameAttr = 'default';
|
nameAttr = 'default';
|
||||||
}
|
}
|
||||||
this._router = router;
|
this._parentRouter = router;
|
||||||
|
this._childRouter = null;
|
||||||
this._viewContainer = viewContainer;
|
this._viewContainer = viewContainer;
|
||||||
this._compiler = compiler;
|
this._compiler = compiler;
|
||||||
this._injector = injector;
|
this._injector = injector;
|
||||||
this._router.registerOutlet(this, nameAttr);
|
this._parentRouter.registerOutlet(this, nameAttr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Given an instruction, update the contents of this viewport.
|
||||||
|
*/
|
||||||
activate(instruction:Instruction): Promise {
|
activate(instruction:Instruction): Promise {
|
||||||
|
// if we're able to reuse the component, we just have to pass along the
|
||||||
|
if (instruction.reuse && isPresent(this._childRouter)) {
|
||||||
|
return this._childRouter.commit(instruction);
|
||||||
|
}
|
||||||
return this._compiler.compileInHost(instruction.component).then((pv) => {
|
return this._compiler.compileInHost(instruction.component).then((pv) => {
|
||||||
|
this._childRouter = this._parentRouter.childRouter(instruction.component);
|
||||||
var outletInjector = this._injector.resolveAndCreateChild([
|
var outletInjector = this._injector.resolveAndCreateChild([
|
||||||
bind(RouteParams).toValue(new RouteParams(instruction.params)),
|
bind(RouteParams).toValue(new RouteParams(instruction.params)),
|
||||||
bind(routerMod.Router).toValue(instruction.router)
|
bind(routerMod.Router).toValue(this._childRouter)
|
||||||
]);
|
]);
|
||||||
|
|
||||||
this._viewContainer.clear();
|
this._viewContainer.clear();
|
||||||
this._viewContainer.create(pv, 0, null, outletInjector);
|
this._viewContainer.create(pv, 0, null, outletInjector);
|
||||||
|
return this._childRouter.commit(instruction);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
canActivate(instruction:Instruction): Promise<boolean> {
|
deactivate():Promise {
|
||||||
return PromiseWrapper.resolve(true);
|
return (isPresent(this._childRouter) ? this._childRouter.deactivate() : PromiseWrapper.resolve(true))
|
||||||
|
.then((_) => this._viewContainer.clear());
|
||||||
}
|
}
|
||||||
|
|
||||||
canDeactivate(instruction:Instruction): Promise<boolean> {
|
canDeactivate(instruction:Instruction): Promise<boolean> {
|
||||||
|
// TODO: how to get ahold of the component instance here?
|
||||||
return PromiseWrapper.resolve(true);
|
return PromiseWrapper.resolve(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -24,7 +24,7 @@ export function main() {
|
|||||||
|
|
||||||
var instruction = registry.recognize('/test', rootHostComponent);
|
var instruction = registry.recognize('/test', rootHostComponent);
|
||||||
|
|
||||||
expect(instruction.getChildInstruction('default').component).toBe(DummyCompB);
|
expect(instruction.getChild('default').component).toBe(DummyCompB);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should prefer static segments to dynamic', () => {
|
it('should prefer static segments to dynamic', () => {
|
||||||
@ -33,7 +33,7 @@ export function main() {
|
|||||||
|
|
||||||
var instruction = registry.recognize('/home', rootHostComponent);
|
var instruction = registry.recognize('/home', rootHostComponent);
|
||||||
|
|
||||||
expect(instruction.getChildInstruction('default').component).toBe(DummyCompA);
|
expect(instruction.getChild('default').component).toBe(DummyCompA);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should prefer dynamic segments to star', () => {
|
it('should prefer dynamic segments to star', () => {
|
||||||
@ -42,7 +42,7 @@ export function main() {
|
|||||||
|
|
||||||
var instruction = registry.recognize('/home', rootHostComponent);
|
var instruction = registry.recognize('/home', rootHostComponent);
|
||||||
|
|
||||||
expect(instruction.getChildInstruction('default').component).toBe(DummyCompA);
|
expect(instruction.getChild('default').component).toBe(DummyCompA);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should match the full URL recursively', () => {
|
it('should match the full URL recursively', () => {
|
||||||
@ -50,8 +50,8 @@ export function main() {
|
|||||||
|
|
||||||
var instruction = registry.recognize('/first/second', rootHostComponent);
|
var instruction = registry.recognize('/first/second', rootHostComponent);
|
||||||
|
|
||||||
var parentInstruction = instruction.getChildInstruction('default');
|
var parentInstruction = instruction.getChild('default');
|
||||||
var childInstruction = parentInstruction.getChildInstruction('default');
|
var childInstruction = parentInstruction.getChild('default');
|
||||||
|
|
||||||
expect(parentInstruction.component).toBe(DummyParentComp);
|
expect(parentInstruction.component).toBe(DummyParentComp);
|
||||||
expect(childInstruction.component).toBe(DummyCompB);
|
expect(childInstruction.component).toBe(DummyCompB);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user