Skip to content
Permalink
Browse files

feat(router): add hash-based navigation option to setUpLocationSync (#…

…28609)

The `setUpLocationSync` function in @angular/router/upgrade didn't previously let you sync hash-based navigations. With this change, you can now pass an option to `setUpLocationSync` that will make sure location changes run in Angular in hash-based apps.

Fixes #24429 #21995

PR Close #28609
  • Loading branch information...
jasonaden authored and IgorMinar committed Feb 8, 2019
1 parent 295a143 commit 71d0eeb966843d372068bf69489da278ff7969fb
@@ -58,7 +58,7 @@ export function locationSyncBootstrapListener(ngUpgrade: UpgradeModule) {
*
* @publicApi
*/
export function setUpLocationSync(ngUpgrade: UpgradeModule) {
export function setUpLocationSync(ngUpgrade: UpgradeModule, urlType: 'path' | 'hash' = 'path') {
if (!ngUpgrade.$injector) {
throw new Error(`
RouterUpgradeInitializer can be used only after UpgradeModule.bootstrap has been called.
@@ -71,7 +71,16 @@ export function setUpLocationSync(ngUpgrade: UpgradeModule) {

ngUpgrade.$injector.get('$rootScope')
.$on('$locationChangeStart', (_: any, next: string, __: string) => {
const url = resolveUrl(next);
let url;
if (urlType === 'path') {
url = resolveUrl(next);
} else if (urlType === 'hash') {
// Remove the first hash from the URL
const hashIdx = next.indexOf('#');
url = resolveUrl(next.substring(0, hashIdx) + next.substring(hashIdx + 1));
} else {
throw 'Invalid URLType passed to setUpLocationSync: ' + urlType;
}
const path = location.normalize(url.pathname);
router.navigateByUrl(path + url.search + url.hash);
});
@@ -79,6 +79,30 @@ describe('setUpLocationSync', () => {
expect(RouterMock.navigateByUrl).toHaveBeenCalledWith(normalizedPathname + query + hash);
});

it('should allow configuration to work with hash-based routing', () => {
const url = 'https://google.com';
const pathname = '/custom/route';
const normalizedPathname = 'foo';
const query = '?query=1&query2=3';
const hash = '#new/hash';
const combinedUrl = url + '#' + pathname + query + hash;
const $rootScope = jasmine.createSpyObj('$rootScope', ['$on']);

upgradeModule.$injector.get.and.returnValue($rootScope);
LocationMock.normalize.and.returnValue(normalizedPathname);

setUpLocationSync(upgradeModule, 'hash');

const callback = $rootScope.$on.calls.argsFor(0)[1];
callback({}, combinedUrl, '');

expect(LocationMock.normalize).toHaveBeenCalledTimes(1);
expect(LocationMock.normalize).toHaveBeenCalledWith(pathname);

expect(RouterMock.navigateByUrl).toHaveBeenCalledTimes(1);
expect(RouterMock.navigateByUrl).toHaveBeenCalledWith(normalizedPathname + query + hash);
});

it('should work correctly on browsers that do not start pathname with `/`', () => {
const anchorProto = HTMLAnchorElement.prototype;
const originalDescriptor = Object.getOwnPropertyDescriptor(anchorProto, 'pathname');
@@ -98,4 +122,5 @@ describe('setUpLocationSync', () => {
Object.defineProperty(anchorProto, 'pathname', originalDescriptor !);
}
});

});
@@ -5,4 +5,4 @@ export declare const RouterUpgradeInitializer: {
deps: (typeof UpgradeModule)[];
};

export declare function setUpLocationSync(ngUpgrade: UpgradeModule): void;
export declare function setUpLocationSync(ngUpgrade: UpgradeModule, urlType?: 'path' | 'hash'): void;

0 comments on commit 71d0eeb

Please sign in to comment.
You can’t perform that action at this time.
You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session.