Skip to content

Commit 9842fb7

Browse files
ocombechristopherthielen
authored andcommitted
feat(ng2.urlRouter): HTML5 PushState support
- Wire up HTML5 PushState and HashBang modes using Hash and PathLocationStrategy from angular2 rc.0+ Closes #2688
1 parent 79d4fd7 commit 9842fb7

File tree

5 files changed

+90
-4
lines changed

5 files changed

+90
-4
lines changed

packages/ng2/webpack.config.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ module.exports = {
4343
},
4444

4545
externals: {
46-
"@angular/core": { root: '@angular/core', amd: '@angular/core', commonjs2: '@angular/core', commonjs: '@angular/core' }
46+
"@angular/core": { root: '@angular/core', amd: '@angular/core', commonjs2: '@angular/core', commonjs: '@angular/core' },
47+
"@angular/common": { root: '@angular/common', amd: '@angular/common', commonjs2: '@angular/common', commonjs: '@angular/common' }
4748
}
4849
};

src/common/strings.ts

+7
Original file line numberDiff line numberDiff line change
@@ -89,3 +89,10 @@ export function stringify(o) {
8989
return JSON.stringify(o, (key, val) => format(val)).replace(/\\"/g, '"');
9090
}
9191

92+
/** Returns a function that splits a string on a character or substring */
93+
export const beforeAfterSubstr = char => str => {
94+
if (!str) return ["", ""];
95+
let idx = str.indexOf(char);
96+
if (idx === -1) return [str, ""];
97+
return [str.substr(0, idx), str.substr(idx + 1)];
98+
};

src/ng2.ts

+1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import "./justjs";
99

1010
export * from "./ng2/interface";
1111
export * from "./ng2/providers";
12+
export * from "./ng2/location";
1213
export * from "./ng2/directives";
1314
export * from "./ng2/viewsBuilder";
1415
export * from "./ng2/uiRouterConfig";

src/ng2/location.ts

+74
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
import {HashLocationStrategy, PlatformLocation, LocationStrategy} from "@angular/common";
2+
import {Injectable} from "@angular/core";
3+
4+
import {services} from "../common/coreservices";
5+
import {isDefined} from "../common/predicates";
6+
import {applyPairs} from "../common/common";
7+
import {beforeAfterSubstr} from "../common/strings";
8+
9+
const splitOnHash = beforeAfterSubstr("#");
10+
const splitOnEquals = beforeAfterSubstr("=");
11+
const splitOnQuestionMark = beforeAfterSubstr("?");
12+
13+
@Injectable()
14+
export class UIRouterLocation {
15+
isHashBang: boolean;
16+
hashPrefix: string = "";
17+
18+
constructor(
19+
public locationStrategy: LocationStrategy,
20+
public platformLocation: PlatformLocation
21+
) {
22+
this.isHashBang = locationStrategy instanceof HashLocationStrategy;
23+
}
24+
25+
init() {
26+
let loc = <any> services.location;
27+
let locSt = this.locationStrategy;
28+
29+
if (this.isHashBang) {
30+
loc.hash = () =>
31+
splitOnHash(splitOnHash(this.platformLocation.hash)[1])[1];
32+
} else {
33+
loc.hash = () =>
34+
splitOnHash(this.platformLocation.hash)[1];
35+
}
36+
37+
loc.path = () =>
38+
splitOnHash(splitOnQuestionMark(locSt.path())[0])[0];
39+
40+
loc.search = () => {
41+
let queryString = splitOnHash(splitOnQuestionMark(locSt.path())[1])[0];
42+
return queryString.split("&").map(kv => splitOnEquals(kv)).reduce(applyPairs, {});
43+
};
44+
45+
loc.url = (url) => {
46+
if(isDefined(url)) {
47+
let split = splitOnQuestionMark(url);
48+
locSt.pushState(null, null, split[0], split[1]);
49+
}
50+
return locSt.path()
51+
};
52+
53+
loc.replace = () => {
54+
console.log(new Error('$location.replace() not impl'))
55+
};
56+
57+
loc.onChange = cb => locSt.onPopState(cb);
58+
59+
let locCfg = <any> services.locationConfig;
60+
61+
locCfg.port = () => null;
62+
locCfg.protocol = () => null;
63+
locCfg.host = () => null;
64+
locCfg.baseHref = () => locSt.getBaseHref();
65+
locCfg.html5Mode = () => !this.isHashBang;
66+
locCfg.hashPrefix = (newprefix: string): string => {
67+
if(isDefined(newprefix)) {
68+
this.hashPrefix = newprefix;
69+
}
70+
return this.hashPrefix;
71+
};
72+
}
73+
}
74+

src/ng2/providers.ts

+6-3
Original file line numberDiff line numberDiff line change
@@ -60,10 +60,13 @@ import {ng2ViewsBuilder, Ng2ViewConfig} from "./viewsBuilder";
6060
import {Ng2ViewDeclaration} from "./interface";
6161
import {UIRouterConfig} from "./uiRouterConfig";
6262
import {UIRouterGlobals} from "../globals";
63+
import {UIRouterLocation} from "./location";
6364

64-
let uiRouterFactory = (routerConfig: UIRouterConfig) => {
65+
let uiRouterFactory = (routerConfig: UIRouterConfig, location: UIRouterLocation) => {
6566
let router = new UIRouter();
6667

68+
location.init();
69+
6770
router.viewService.viewConfigFactory("ng2", (node: Node, config: Ng2ViewDeclaration) => new Ng2ViewConfig(node, config));
6871
router.stateRegistry.decorator('views', ng2ViewsBuilder);
6972

@@ -93,8 +96,9 @@ let uiRouterFactory = (routerConfig: UIRouterConfig) => {
9396
* ```
9497
*/
9598
export const UIROUTER_PROVIDERS: Provider[] = [
99+
provide(UIRouter, { useFactory: uiRouterFactory, deps: [UIRouterConfig, UIRouterLocation] }),
96100

97-
provide(UIRouter, { useFactory: uiRouterFactory, deps: [UIRouterConfig] }),
101+
provide(UIRouterLocation, { useClass: UIRouterLocation }),
98102

99103
provide(StateService, { useFactory: (r: UIRouter) => { return r.stateService; }, deps: [UIRouter]}),
100104

@@ -111,6 +115,5 @@ export const UIROUTER_PROVIDERS: Provider[] = [
111115
provide(UIRouterGlobals, { useFactory: (r: UIRouter) => { return r.globals; }, deps: [UIRouter]}),
112116

113117
provide(UiView.PARENT_INJECT, { useFactory: (r: StateRegistry) => { return { fqn: null, context: r.root() } }, deps: [StateRegistry]} )
114-
115118
];
116119

0 commit comments

Comments
 (0)