From 6dce4f49c2364d3c7cc8929f0bd39e894dbb2162 Mon Sep 17 00:00:00 2001 From: Brandon Roberts Date: Thu, 18 Feb 2016 09:25:03 -0600 Subject: [PATCH] feat(router): Added method to get current instruction This method delegates to the root router to get the current complete instruction. --- modules/angular1_router/src/ng_route_shim.js | 2 +- .../test/integration/router_spec.js | 40 +++++++++++++++++++ modules/angular2/src/router/router.ts | 33 ++++++++------- modules/angular2/test/router/router_spec.ts | 22 ++++++++++ 4 files changed, 81 insertions(+), 16 deletions(-) diff --git a/modules/angular1_router/src/ng_route_shim.js b/modules/angular1_router/src/ng_route_shim.js index bb17d0816f..6cb817148b 100644 --- a/modules/angular1_router/src/ng_route_shim.js +++ b/modules/angular1_router/src/ng_route_shim.js @@ -246,7 +246,7 @@ var paramsObj = {}; $rootScope.$on('$routeChangeSuccess', function () { - var newParams = $rootRouter._currentInstruction && $rootRouter._currentInstruction.component.params; + var newParams = $rootRouter.currentInstruction && $rootRouter.currentInstruction.component.params; angular.forEach(paramsObj, function (val, name) { delete paramsObj[name]; diff --git a/modules/angular1_router/test/integration/router_spec.js b/modules/angular1_router/test/integration/router_spec.js index 81218edeb4..8365daba64 100644 --- a/modules/angular1_router/test/integration/router_spec.js +++ b/modules/angular1_router/test/integration/router_spec.js @@ -120,6 +120,46 @@ describe('router', function () { expect($routerOnActivate).toHaveBeenCalled(); })); + it('should provide the current instruction', inject(function($location, $q) { + registerComponent('homeCmp', { + template: 'Home ({{homeCmp.isAdmin}})' + }); + + registerComponent('app', { + template: '
', + $routeConfig: [ + { path: '/', component: 'homeCmp', name: 'Home' } + ] + }); + compile(''); + + $location.path('/'); + $rootScope.$digest(); + var instruction = $rootRouter.generate(['/Home']); + expect($rootRouter.currentInstruction).toEqual(instruction); + })); + + it('should provide the root level router', inject(function($location, $q) { + registerComponent('homeCmp', { + template: 'Home ({{homeCmp.isAdmin}})', + bindings: { + $router: '<' + } + }); + + registerComponent('app', { + template: '
', + $routeConfig: [ + { path: '/', component: 'homeCmp', name: 'Home' } + ] + }); + compile(''); + + $location.path('/'); + $rootScope.$digest(); + var homeElement = elt.find('home-cmp'); + expect(homeElement.isolateScope().$ctrl.$router.root).toEqual($rootRouter); + })); function registerDirective(name, options) { function factory() { diff --git a/modules/angular2/src/router/router.ts b/modules/angular2/src/router/router.ts index 1376785a50..4a87b7cd5e 100644 --- a/modules/angular2/src/router/router.ts +++ b/modules/angular2/src/router/router.ts @@ -38,8 +38,10 @@ let _resolveToFalse = PromiseWrapper.resolve(false); export class Router { navigating: boolean = false; lastNavigationAttempt: string; - - private _currentInstruction: Instruction = null; + /** + * The current `Instruction` for the router + */ + public currentInstruction: Instruction = null; private _currentNavigation: Promise = _resolveToTrue; private _outlet: RouterOutlet = null; @@ -50,8 +52,8 @@ export class Router { private _subject: EventEmitter = new EventEmitter(); - constructor(public registry: RouteRegistry, public parent: Router, public hostComponent: any) {} - + constructor(public registry: RouteRegistry, public parent: Router, public hostComponent: any, + public root?: Router) {} /** * Constructs a child router. You probably don't need to use this unless you're writing a reusable @@ -83,8 +85,8 @@ export class Router { } this._outlet = outlet; - if (isPresent(this._currentInstruction)) { - return this.commit(this._currentInstruction, false); + if (isPresent(this.currentInstruction)) { + return this.commit(this.currentInstruction, false); } return _resolveToTrue; } @@ -119,8 +121,8 @@ export class Router { router._outlet = outlet; var auxInstruction; - if (isPresent(this._currentInstruction) && - isPresent(auxInstruction = this._currentInstruction.auxInstruction[outletName])) { + if (isPresent(this.currentInstruction) && + isPresent(auxInstruction = this.currentInstruction.auxInstruction[outletName])) { return router.commit(auxInstruction); } return _resolveToTrue; @@ -137,8 +139,8 @@ export class Router { router = router.parent; instruction = instruction.child; } - return isPresent(this._currentInstruction) && - this._currentInstruction.component == instruction.component; + return isPresent(this.currentInstruction) && + this.currentInstruction.component == instruction.component; } @@ -287,7 +289,7 @@ export class Router { } private _canActivate(nextInstruction: Instruction): Promise { - return canActivateOne(nextInstruction, this._currentInstruction); + return canActivateOne(nextInstruction, this.currentInstruction); } private _routerCanDeactivate(instruction: Instruction): Promise { @@ -324,7 +326,7 @@ export class Router { * Updates this router and all descendant routers according to the given instruction */ commit(instruction: Instruction, _skipLocationChange: boolean = false): Promise { - this._currentInstruction = instruction; + this.currentInstruction = instruction; var next: Promise = _resolveToTrue; if (isPresent(this._outlet) && isPresent(instruction.component)) { @@ -403,10 +405,10 @@ export class Router { } private _getAncestorInstructions(): Instruction[] { - var ancestorInstructions = [this._currentInstruction]; + var ancestorInstructions = [this.currentInstruction]; var ancestorRouter: Router = this; while (isPresent(ancestorRouter = ancestorRouter.parent)) { - ancestorInstructions.unshift(ancestorRouter._currentInstruction); + ancestorInstructions.unshift(ancestorRouter.currentInstruction); } return ancestorInstructions; } @@ -443,6 +445,7 @@ export class RootRouter extends Router { constructor(registry: RouteRegistry, location: Location, @Inject(ROUTER_PRIMARY_COMPONENT) primaryComponent: Type) { super(registry, null, primaryComponent); + this.root = this; this._location = location; this._locationSub = this._location.subscribe((change) => { // we call recognize ourselves @@ -503,7 +506,7 @@ export class RootRouter extends Router { class ChildRouter extends Router { constructor(parent: Router, hostComponent) { - super(parent.registry, parent, hostComponent); + super(parent.registry, parent, hostComponent, parent.root); this.parent = parent; } diff --git a/modules/angular2/test/router/router_spec.ts b/modules/angular2/test/router/router_spec.ts index f8056f32c9..5027eefbca 100644 --- a/modules/angular2/test/router/router_spec.ts +++ b/modules/angular2/test/router/router_spec.ts @@ -218,6 +218,28 @@ export function main() { }); })); + it('should provide the current instruction', inject([AsyncTestCompleter], (async) => { + var outlet = makeDummyOutlet(); + + router.registerPrimaryOutlet(outlet) + .then((_) => router.config([ + new Route({path: '/a', component: DummyComponent, name: 'A'}), + new Route({path: '/b', component: DummyComponent, name: 'B'}) + ])) + .then((_) => router.navigateByUrl('/a')) + .then((_) => { + var instruction = router.generate(['/A']); + + expect(router.currentInstruction).toEqual(instruction); + async.done(); + }); + })); + + it('should provide the root level router from child routers', () => { + let childRouter = router.childRouter(DummyComponent); + expect(childRouter.root).toBe(router); + }); + describe('query string params', () => { it('should use query string params for the root route', () => { router.config(