From 53bddec1d2a803dec2a45de28bee1f4b505e646e Mon Sep 17 00:00:00 2001 From: Brian Ford Date: Fri, 30 Oct 2015 08:48:47 -0700 Subject: [PATCH] fix(router): respond to hashchange events Previously if the URL changed in `HashLocation` mode, the router would not pick up the change. This adds a listener in `HashLocationStrategy` for `hashchange` events to fix the problem. Closes #5013 --- .../src/router/path_location_strategy.ts | 1 + .../hash_routing/hash_location_spec.dart | 3 ++ .../hash_routing/hash_location_spec.ts | 29 +++++++++++ .../playground/src/hash_routing/index.html | 12 +++++ modules/playground/src/hash_routing/index.ts | 49 +++++++++++++++++++ tools/broccoli/trees/browser_tree.ts | 1 + 6 files changed, 95 insertions(+) create mode 100644 modules/playground/e2e_test/hash_routing/hash_location_spec.dart create mode 100644 modules/playground/e2e_test/hash_routing/hash_location_spec.ts create mode 100644 modules/playground/src/hash_routing/index.html create mode 100644 modules/playground/src/hash_routing/index.ts diff --git a/modules/angular2/src/router/path_location_strategy.ts b/modules/angular2/src/router/path_location_strategy.ts index 9ad1799f2d..0e7827fd3a 100644 --- a/modules/angular2/src/router/path_location_strategy.ts +++ b/modules/angular2/src/router/path_location_strategy.ts @@ -63,6 +63,7 @@ export class PathLocationStrategy extends LocationStrategy { onPopState(fn: EventListener): void { DOM.getGlobalEventTarget('window').addEventListener('popstate', fn, false); + DOM.getGlobalEventTarget('window').addEventListener('hashchange', fn, false); } getBaseHref(): string { return this._baseHref; } diff --git a/modules/playground/e2e_test/hash_routing/hash_location_spec.dart b/modules/playground/e2e_test/hash_routing/hash_location_spec.dart new file mode 100644 index 0000000000..fcd80886f2 --- /dev/null +++ b/modules/playground/e2e_test/hash_routing/hash_location_spec.dart @@ -0,0 +1,3 @@ +library playground.e2e_test.hash_location_spec; + +main() {} diff --git a/modules/playground/e2e_test/hash_routing/hash_location_spec.ts b/modules/playground/e2e_test/hash_routing/hash_location_spec.ts new file mode 100644 index 0000000000..e241e34659 --- /dev/null +++ b/modules/playground/e2e_test/hash_routing/hash_location_spec.ts @@ -0,0 +1,29 @@ +import {verifyNoBrowserErrors} from 'angular2/src/testing/e2e_util'; +import {Promise} from 'angular2/src/core/facade/async'; + +function waitForElement(selector) { + var EC = (protractor).ExpectedConditions; + // Waits for the element with id 'abc' to be present on the dom. + browser.wait(EC.presenceOf($(selector)), 20000); +} + +describe('hash routing example app', function() { + afterEach(verifyNoBrowserErrors); + + var URL = 'playground/src/hash_routing/index.html'; + + it('should navigate between routes', function() { + browser.get(URL + '#/bye'); + waitForElement('goodbye-cmp'); + + element(by.css('#hello-link')).click(); + waitForElement('hello-cmp'); + + expect(element(by.css('hello-cmp')).getText()).toContain('hello'); + + browser.navigate().back(); + waitForElement('goodbye-cmp'); + + expect(element(by.css('goodbye-cmp')).getText()).toContain('goodbye'); + }); +}); diff --git a/modules/playground/src/hash_routing/index.html b/modules/playground/src/hash_routing/index.html new file mode 100644 index 0000000000..f3a908da15 --- /dev/null +++ b/modules/playground/src/hash_routing/index.html @@ -0,0 +1,12 @@ + + +Routing Example + + + + Loading... + + + $SCRIPTS$ + + diff --git a/modules/playground/src/hash_routing/index.ts b/modules/playground/src/hash_routing/index.ts new file mode 100644 index 0000000000..d82bfbd977 --- /dev/null +++ b/modules/playground/src/hash_routing/index.ts @@ -0,0 +1,49 @@ +import {Component, provide} from 'angular2/angular2'; +import {bootstrap} from 'angular2/bootstrap'; +import { + RouteConfig, + Route, + ROUTER_PROVIDERS, + ROUTER_DIRECTIVES, + HashLocationStrategy, + LocationStrategy +} from 'angular2/router'; + +import {reflector} from 'angular2/src/core/reflection/reflection'; +import {ReflectionCapabilities} from 'angular2/src/core/reflection/reflection_capabilities'; + +@Component({selector: 'hello-cmp', template: `hello`}) +class HelloCmp { +} + + +@Component({selector: 'goodbye-cmp', template: `goodbye`}) +class GoodByeCmp { +} + + +@Component({ + selector: 'example-app', + template: ` +

My App

+ + + `, + directives: [ROUTER_DIRECTIVES] +}) +@RouteConfig([ + new Route({path: '/', component: HelloCmp, name: 'HelloCmp'}), + new Route({path: '/bye', component: GoodByeCmp, name: 'GoodbyeCmp'}) +]) +class AppCmp { +} + + +export function main() { + reflector.reflectionCapabilities = new ReflectionCapabilities(); + bootstrap(AppCmp, + [ROUTER_PROVIDERS, provide(LocationStrategy, {useClass: HashLocationStrategy})]); +} diff --git a/tools/broccoli/trees/browser_tree.ts b/tools/broccoli/trees/browser_tree.ts index d107c0c64d..76c3f19c3d 100644 --- a/tools/broccoli/trees/browser_tree.ts +++ b/tools/broccoli/trees/browser_tree.ts @@ -43,6 +43,7 @@ const kServedPaths = [ 'playground/src/person_management', 'playground/src/order_management', 'playground/src/gestures', + 'playground/src/hash_routing', 'playground/src/hello_world', 'playground/src/http', 'playground/src/jsonp',