feat(router): Added method to get current instruction

This method delegates to the root router to get the current complete instruction.
This commit is contained in:
Brandon Roberts 2016-02-18 09:25:03 -06:00 committed by Vikram Subramanian
parent 15e16148f4
commit 6dce4f49c2
4 changed files with 81 additions and 16 deletions

View File

@ -246,7 +246,7 @@
var paramsObj = {}; var paramsObj = {};
$rootScope.$on('$routeChangeSuccess', function () { $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) { angular.forEach(paramsObj, function (val, name) {
delete paramsObj[name]; delete paramsObj[name];

View File

@ -120,6 +120,46 @@ describe('router', function () {
expect($routerOnActivate).toHaveBeenCalled(); expect($routerOnActivate).toHaveBeenCalled();
})); }));
it('should provide the current instruction', inject(function($location, $q) {
registerComponent('homeCmp', {
template: 'Home ({{homeCmp.isAdmin}})'
});
registerComponent('app', {
template: '<div ng-outlet></div>',
$routeConfig: [
{ path: '/', component: 'homeCmp', name: 'Home' }
]
});
compile('<app></app>');
$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: '<div ng-outlet></div>',
$routeConfig: [
{ path: '/', component: 'homeCmp', name: 'Home' }
]
});
compile('<app></app>');
$location.path('/');
$rootScope.$digest();
var homeElement = elt.find('home-cmp');
expect(homeElement.isolateScope().$ctrl.$router.root).toEqual($rootRouter);
}));
function registerDirective(name, options) { function registerDirective(name, options) {
function factory() { function factory() {

View File

@ -38,8 +38,10 @@ let _resolveToFalse = PromiseWrapper.resolve(false);
export class Router { export class Router {
navigating: boolean = false; navigating: boolean = false;
lastNavigationAttempt: string; lastNavigationAttempt: string;
/**
private _currentInstruction: Instruction = null; * The current `Instruction` for the router
*/
public currentInstruction: Instruction = null;
private _currentNavigation: Promise<any> = _resolveToTrue; private _currentNavigation: Promise<any> = _resolveToTrue;
private _outlet: RouterOutlet = null; private _outlet: RouterOutlet = null;
@ -50,8 +52,8 @@ export class Router {
private _subject: EventEmitter<any> = new EventEmitter(); private _subject: EventEmitter<any> = 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 * 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; this._outlet = outlet;
if (isPresent(this._currentInstruction)) { if (isPresent(this.currentInstruction)) {
return this.commit(this._currentInstruction, false); return this.commit(this.currentInstruction, false);
} }
return _resolveToTrue; return _resolveToTrue;
} }
@ -119,8 +121,8 @@ export class Router {
router._outlet = outlet; router._outlet = outlet;
var auxInstruction; var auxInstruction;
if (isPresent(this._currentInstruction) && if (isPresent(this.currentInstruction) &&
isPresent(auxInstruction = this._currentInstruction.auxInstruction[outletName])) { isPresent(auxInstruction = this.currentInstruction.auxInstruction[outletName])) {
return router.commit(auxInstruction); return router.commit(auxInstruction);
} }
return _resolveToTrue; return _resolveToTrue;
@ -137,8 +139,8 @@ export class Router {
router = router.parent; router = router.parent;
instruction = instruction.child; instruction = instruction.child;
} }
return isPresent(this._currentInstruction) && return isPresent(this.currentInstruction) &&
this._currentInstruction.component == instruction.component; this.currentInstruction.component == instruction.component;
} }
@ -287,7 +289,7 @@ export class Router {
} }
private _canActivate(nextInstruction: Instruction): Promise<boolean> { private _canActivate(nextInstruction: Instruction): Promise<boolean> {
return canActivateOne(nextInstruction, this._currentInstruction); return canActivateOne(nextInstruction, this.currentInstruction);
} }
private _routerCanDeactivate(instruction: Instruction): Promise<boolean> { private _routerCanDeactivate(instruction: Instruction): Promise<boolean> {
@ -324,7 +326,7 @@ export class Router {
* Updates this router and all descendant routers according to the given instruction * Updates this router and all descendant routers according to the given instruction
*/ */
commit(instruction: Instruction, _skipLocationChange: boolean = false): Promise<any> { commit(instruction: Instruction, _skipLocationChange: boolean = false): Promise<any> {
this._currentInstruction = instruction; this.currentInstruction = instruction;
var next: Promise<any> = _resolveToTrue; var next: Promise<any> = _resolveToTrue;
if (isPresent(this._outlet) && isPresent(instruction.component)) { if (isPresent(this._outlet) && isPresent(instruction.component)) {
@ -403,10 +405,10 @@ export class Router {
} }
private _getAncestorInstructions(): Instruction[] { private _getAncestorInstructions(): Instruction[] {
var ancestorInstructions = [this._currentInstruction]; var ancestorInstructions = [this.currentInstruction];
var ancestorRouter: Router = this; var ancestorRouter: Router = this;
while (isPresent(ancestorRouter = ancestorRouter.parent)) { while (isPresent(ancestorRouter = ancestorRouter.parent)) {
ancestorInstructions.unshift(ancestorRouter._currentInstruction); ancestorInstructions.unshift(ancestorRouter.currentInstruction);
} }
return ancestorInstructions; return ancestorInstructions;
} }
@ -443,6 +445,7 @@ export class RootRouter extends Router {
constructor(registry: RouteRegistry, location: Location, constructor(registry: RouteRegistry, location: Location,
@Inject(ROUTER_PRIMARY_COMPONENT) primaryComponent: Type) { @Inject(ROUTER_PRIMARY_COMPONENT) primaryComponent: Type) {
super(registry, null, primaryComponent); super(registry, null, primaryComponent);
this.root = this;
this._location = location; this._location = location;
this._locationSub = this._location.subscribe((change) => { this._locationSub = this._location.subscribe((change) => {
// we call recognize ourselves // we call recognize ourselves
@ -503,7 +506,7 @@ export class RootRouter extends Router {
class ChildRouter extends Router { class ChildRouter extends Router {
constructor(parent: Router, hostComponent) { constructor(parent: Router, hostComponent) {
super(parent.registry, parent, hostComponent); super(parent.registry, parent, hostComponent, parent.root);
this.parent = parent; this.parent = parent;
} }

View File

@ -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', () => { describe('query string params', () => {
it('should use query string params for the root route', () => { it('should use query string params for the root route', () => {
router.config( router.config(