From 4fe0f1fa655717fd49045dedaebc8b1100f11238 Mon Sep 17 00:00:00 2001 From: vsavkin Date: Sun, 1 May 2016 17:07:10 -0700 Subject: [PATCH] feat(router): set router-link-active when RouterLink is active Closes #8376 --- .../src/alt_router/directives/router_link.ts | 4 ++++ modules/angular2/src/alt_router/segments.ts | 11 +++++------ .../test/alt_router/integration_spec.ts | 18 ++++++++++++++++++ modules/angular2/test/alt_router/tree_spec.ts | 6 ++++-- 4 files changed, 31 insertions(+), 8 deletions(-) diff --git a/modules/angular2/src/alt_router/directives/router_link.ts b/modules/angular2/src/alt_router/directives/router_link.ts index 83bfd19b67..c62c9b905c 100644 --- a/modules/angular2/src/alt_router/directives/router_link.ts +++ b/modules/angular2/src/alt_router/directives/router_link.ts @@ -26,6 +26,7 @@ export class RouterLink implements OnDestroy { private _subscription: any; @HostBinding() private href: string; + @HostBinding('class.router-link-active') private isActive: boolean = false; constructor(@Optional() private _routeSegment: RouteSegment, private _router: Router) { this._subscription = @@ -53,6 +54,9 @@ export class RouterLink implements OnDestroy { let tree = this._router.createUrlTree(this._changes, this._routeSegment); if (isPresent(tree)) { this.href = this._router.serializeUrl(tree); + this.isActive = this._router.urlTree.contains(tree); + } else { + this.isActive = false; } } } \ No newline at end of file diff --git a/modules/angular2/src/alt_router/segments.ts b/modules/angular2/src/alt_router/segments.ts index 32b2db95c5..29c9ab2f33 100644 --- a/modules/angular2/src/alt_router/segments.ts +++ b/modules/angular2/src/alt_router/segments.ts @@ -27,9 +27,7 @@ export class Tree { pathFromRoot(t: T): T[] { return _findPath(t, this._root, []).map(s => s.value); } - contains(tree: Tree): boolean { - return _contains(this._root, tree._root); - } + contains(tree: Tree): boolean { return _contains(this._root, tree._root); } } export class UrlTree extends Tree { @@ -59,7 +57,7 @@ function _findPath(expected: T, c: TreeNode, collected: TreeNode[]): Tr collected.push(c); // TODO: vsavkin remove it once recognize is fixed - if(_equalValues(expected, c.value)) return collected; + if (_equalValues(expected, c.value)) return collected; for (let cc of c.children) { let r = _findPath(expected, cc, ListWrapper.clone(collected)); @@ -81,9 +79,9 @@ function _contains(tree: TreeNode, subtree: TreeNode): boolean { return true; } -function _equalValues(a:any, b:any):boolean { +function _equalValues(a: any, b: any): boolean { if (a instanceof RouteSegment) return equalSegments(a, b); - if (a instanceof UrlSegment) return equalUrlSegments(a, b) + if (a instanceof UrlSegment) return equalUrlSegments(a, b); return a === b; } @@ -156,6 +154,7 @@ export function equalSegments(a: RouteSegment, b: RouteSegment): boolean { export function equalUrlSegments(a: UrlSegment, b: UrlSegment): boolean { if (isBlank(a) && !isBlank(b)) return false; if (!isBlank(a) && isBlank(b)) return false; + if (a.segment != b.segment) return false; if (a.outlet != b.outlet) return false; if (isBlank(a.parameters) && !isBlank(b.parameters)) return false; if (!isBlank(a.parameters) && isBlank(b.parameters)) return false; diff --git a/modules/angular2/test/alt_router/integration_spec.ts b/modules/angular2/test/alt_router/integration_spec.ts index ec7fa1181e..ea58b7bb6a 100644 --- a/modules/angular2/test/alt_router/integration_spec.ts +++ b/modules/angular2/test/alt_router/integration_spec.ts @@ -192,6 +192,24 @@ export function main() { .toHaveText('team 22 { relativelink { simple }, aux: }'); }))); + it("should set the router-link-active class", + fakeAsync(inject([Router, TestComponentBuilder], (router, tcb) => { + let fixture = tcb.createFakeAsync(RootCmp); + advance(fixture); + + router.navigateByUrl('/team/22/relativelink'); + advance(fixture); + expect(fixture.debugElement.nativeElement) + .toHaveText('team 22 { relativelink { }, aux: }'); + let link = DOM.querySelector(fixture.debugElement.nativeElement, "a"); + expect(DOM.hasClass(link, "router-link-active")).toEqual(false); + + DOM.dispatchEvent(link, DOM.createMouseEvent('click')); + advance(fixture); + + expect(DOM.hasClass(link, "router-link-active")).toEqual(true); + }))); + it("should update router links when router changes", fakeAsync(inject([Router, TestComponentBuilder], (router, tcb) => { let fixture = tcb.createFakeAsync(RootCmp); diff --git a/modules/angular2/test/alt_router/tree_spec.ts b/modules/angular2/test/alt_router/tree_spec.ts index 4a95e39013..2f96a2b859 100644 --- a/modules/angular2/test/alt_router/tree_spec.ts +++ b/modules/angular2/test/alt_router/tree_spec.ts @@ -49,12 +49,14 @@ export function main() { describe("contains", () => { it("should work", () => { - let tree = new Tree(new TreeNode(1, [new TreeNode(2, []), new TreeNode(3, [])])); + let tree = new Tree( + new TreeNode(1, [new TreeNode(2, []), new TreeNode(3, [])])); let subtree1 = new Tree(new TreeNode(1, [])); let subtree2 = new Tree(new TreeNode(1, [new TreeNode(2, [])])); let subtree3 = new Tree(new TreeNode(1, [new TreeNode(3, [])])); let notSubtree1 = new Tree(new TreeNode(1, [new TreeNode(4, [])])); - let notSubtree2 = new Tree(new TreeNode(1, [new TreeNode(2, [new TreeNode(4, [])])])); + let notSubtree2 = new Tree( + new TreeNode(1, [new TreeNode(2, [new TreeNode(4, [])])])); expect(tree.contains(subtree1)).toEqual(true); expect(tree.contains(subtree2)).toEqual(true);