Skip to content

Commit b8c6146

Browse files
feat(ng2.UrlRouter): Implement { location: replace }
refactor(core.$location): BC-BREAK remove $location.replace() and $location.url(url) in favor of `$location.setUrl(url, replace)` Closes #2850
1 parent 7bca101 commit b8c6146

File tree

9 files changed

+44
-48
lines changed

9 files changed

+44
-48
lines changed

src/common/coreservices.ts

+2-3
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ let services: CoreServices = {
1919
template: <any> {}
2020
};
2121

22-
["replace", "url", "path", "search", "hash", "onChange"]
22+
["setUrl", "path", "search", "hash", "onChange"]
2323
.forEach(key => services.location[key] = notImplemented(key));
2424

2525
["port", "protocol", "host", "baseHref", "html5Mode", "hashPrefix" ]
@@ -58,8 +58,7 @@ export interface CoreServices {
5858
}
5959

6060
export interface LocationServices {
61-
replace(): void;
62-
url(newurl: string): string;
61+
setUrl(newurl: string, replace?: boolean): void;
6362
url(): string;
6463
path(): string;
6564
search(): string;

src/justjs.ts

+3-2
Original file line numberDiff line numberDiff line change
@@ -86,8 +86,9 @@ let loc = <any> services.location;
8686
loc.hash = () => "";
8787
loc.path = () => location.hash.replace(/^#/, "");
8888
loc.search = () => location.search;
89-
loc.url = (url: string) => { if (url) location.hash = url; return loc.path(); };
90-
loc.replace = () => { console.log(new Error("not impl")); };
89+
loc.setUrl = (url: string, replace: boolean = true) => {
90+
if (url) location.hash = url;
91+
};
9192
loc.onChange = (cb: (ev?: HashChangeEvent) => any) => {
9293
window.addEventListener("hashchange", cb, false);
9394
};

src/ng1/services.ts

+5
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,11 @@ function $uiRouter($locationProvider: ILocationProvider) {
197197
html5Mode = isObject(html5Mode) ? html5Mode.enabled : html5Mode;
198198
return html5Mode && $sniffer.history;
199199
};
200+
201+
services.location.setUrl = (newUrl: string, replace = false) => {
202+
$location.url(newUrl)
203+
if (replace) $location.replace();
204+
};
200205

201206
services.template.get = (url: string) =>
202207
$http.get(url, { cache: $templateCache, headers: { Accept: 'text/html' }}).then(prop("data"));

src/ng2/location.ts

+10-11
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ export class UIRouterLocation {
2424
}
2525

2626
init() {
27-
let loc = <any> services.location;
27+
let loc = services.location;
2828
let locSt = this.locationStrategy;
2929

3030
if (this.isHashBang) {
@@ -43,24 +43,23 @@ export class UIRouterLocation {
4343
}
4444

4545

46-
loc.search = () => {
46+
loc.search = <any> (() => {
4747
let queryString = splitOnHash(splitOnQuestionMark(locSt.path())[1])[0];
4848
return queryString.split("&").map(kv => splitOnEquals(kv)).reduce(applyPairs, {});
49-
};
49+
});
5050

51-
loc.url = (url: string) => {
51+
loc.setUrl = (url: string, replace: boolean = false) => {
5252
if(isDefined(url)) {
5353
let split = splitOnQuestionMark(url);
54-
locSt.pushState(null, null, split[0], split[1]);
54+
if (replace) {
55+
locSt.replaceState(null, null, split[0], split[1]);
56+
} else {
57+
locSt.pushState(null, null, split[0], split[1]);
58+
}
5559
}
56-
return locSt.path()
57-
};
58-
59-
loc.replace = () => {
60-
console.log(new Error('$location.replace() not impl'))
6160
};
6261

63-
loc.onChange = (cb: LocationChangeListener) => locSt.onPopState(cb);
62+
loc.onChange = (cb: LocationChangeListener) => locSt.onPopState(cb) as any;
6463

6564
let locCfg = <any> services.locationConfig;
6665

src/url/urlRouter.ts

+6-8
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,7 @@ function update(rules: Function[], otherwiseFn: Function, evt?: any) {
4949

5050
if (!handled) return false;
5151
if (isString(handled)) {
52-
$location.replace();
53-
$location.url(handled);
52+
$location.setUrl(handled, true);
5453
}
5554
return true;
5655
}
@@ -355,13 +354,12 @@ export class UrlRouter {
355354
*/
356355
update(read?: boolean) {
357356
if (read) {
358-
this.location = $location.url();
357+
this.location = $location.path();
359358
return;
360359
}
361-
if ($location.url() === this.location) return;
360+
if ($location.path() === this.location) return;
362361

363-
$location.url(this.location);
364-
$location.replace();
362+
$location.setUrl(this.location, true);
365363
}
366364

367365
/**
@@ -374,8 +372,8 @@ export class UrlRouter {
374372
* @param options
375373
*/
376374
push(urlMatcher: UrlMatcher, params: StateParams, options: { replace?: (string|boolean) }) {
377-
$location.url(urlMatcher.format(params || {}));
378-
if (options && options.replace) $location.replace();
375+
let replace = options && !!options.replace;
376+
$location.setUrl(urlMatcher.format(params || {}), replace);
379377
}
380378

381379
/**

test/core/stateRegistrySpec.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ describe("StateRegistry", () => {
6464
registry.register(state);
6565

6666
spyOn($state, "transitionTo");
67-
services.location.url("/foo");
67+
services.location.setUrl("/foo");
6868
router.urlRouter.sync();
6969
expect($state.transitionTo['calls'].mostRecent().args[0]).toBe(state.$$state());
7070

test/core/stateServiceSpec.ts

+6-6
Original file line numberDiff line numberDiff line change
@@ -63,13 +63,13 @@ describe('stateService', function () {
6363
}));
6464

6565
it("should not update the URL in response to synchronizing URL", ((done) => {
66-
$loc.url('/a/b/c');
67-
spyOn($loc, 'url').and.callThrough();
66+
$loc.setUrl('/a/b/c');
67+
spyOn($loc, 'setUrl').and.callThrough();
6868
router.urlRouter.sync();
6969

7070
wait().then(() => {
7171
expect($state.current.name).toBe('C');
72-
let pushedUrls = $loc.url.calls.all().map(x => x.args[0]).filter(x => x !== undefined);
72+
let pushedUrls = $loc.setUrl.calls.all().map(x => x.args[0]).filter(x => x !== undefined);
7373
expect(pushedUrls).toEqual([]);
7474
expect($loc.path()).toBe('/a/b/c');
7575
done();
@@ -79,13 +79,13 @@ describe('stateService', function () {
7979
it("should update the URL in response to synchronizing URL then redirecting", ((done) => {
8080
$transitions.onStart({ to: 'C' }, () => $state.target('D'));
8181

82-
$loc.url('/a/b/c');
83-
spyOn($loc, 'url').and.callThrough();
82+
$loc.setUrl('/a/b/c');
83+
spyOn($loc, 'setUrl').and.callThrough();
8484
router.urlRouter.sync();
8585

8686
wait().then(() => {
8787
expect($state.current.name).toBe('D');
88-
let pushedUrls = $loc.url.calls.all().map(x => x.args[0]).filter(x => x !== undefined);
88+
let pushedUrls = $loc.setUrl.calls.all().map(x => x.args[0]).filter(x => x !== undefined);
8989
expect(pushedUrls).toEqual(['/a/b/c/d']);
9090
expect($loc.path()).toBe('/a/b/c/d');
9191
done();

test/ng1/stateSpec.js

+3-2
Original file line numberDiff line numberDiff line change
@@ -1456,12 +1456,13 @@ describe('state', function () {
14561456

14571457
it('should replace browser history when "replace" enabled', inject(function ($state, $rootScope, $location, $q) {
14581458

1459-
spyOn(services.location, 'replace');
1459+
spyOn(services.location, 'setUrl');
14601460

14611461
$state.transitionTo('about', {}, { location: 'replace' });
14621462
$q.flush();
14631463

1464-
expect(services.location.replace).toHaveBeenCalled();
1464+
expect(services.location.setUrl).toHaveBeenCalled();
1465+
expect(services.location.setUrl.calls.argsFor(0)[1]).toBe(true);
14651466
}));
14661467

14671468
it('should not replace history normally', inject(function ($state, $rootScope, $location, $q) {

test/ng1/urlRouterSpec.ts

+8-15
Original file line numberDiff line numberDiff line change
@@ -194,28 +194,21 @@ describe("UrlRouter", function () {
194194

195195
describe("location updates", function() {
196196
it('can push location changes', inject(function($urlRouter) {
197-
spyOn(services.location, "url");
198-
spyOn(services.location, "replace");
197+
spyOn(services.location, "setUrl");
199198
$urlRouter.push(makeMatcher("/hello/:name"), { name: "world" });
200-
201-
expect(services.location.url).toHaveBeenCalledWith("/hello/world");
202-
expect(services.location.replace).not.toHaveBeenCalled();
199+
expect(services.location.setUrl).toHaveBeenCalledWith("/hello/world", undefined);
203200
}));
204201

205202
it('can push a replacement location', inject(function($urlRouter, $location) {
206-
spyOn(services.location, "url");
207-
spyOn(services.location, "replace");
203+
spyOn(services.location, "setUrl");
208204
$urlRouter.push(makeMatcher("/hello/:name"), { name: "world" }, { replace: true });
209-
210-
expect(services.location.url).toHaveBeenCalledWith("/hello/world");
211-
expect(services.location.replace).toHaveBeenCalled();
205+
expect(services.location.setUrl).toHaveBeenCalledWith("/hello/world", true);
212206
}));
213207

214208
it('can push location changes with no parameters', inject(function($urlRouter, $location) {
215-
spyOn(services.location, "url");
209+
spyOn(services.location, "setUrl");
216210
$urlRouter.push(makeMatcher("/hello/:name", {params:{name: ""}}));
217-
218-
expect(services.location.url).toHaveBeenCalledWith("/hello/");
211+
expect(services.location.setUrl).toHaveBeenCalledWith("/hello/", undefined);
219212
}));
220213

221214
it('can push location changes that include a #fragment', inject(function($urlRouter, $location) {
@@ -237,9 +230,9 @@ describe("UrlRouter", function () {
237230
it('can read and sync a copy of location URL', inject(function($urlRouter, $location) {
238231
$location.url('/old');
239232

240-
spyOn(services.location, 'url').and.callThrough();
233+
spyOn(services.location, 'path').and.callThrough();
241234
$urlRouter.update(true);
242-
expect(services.location.url).toHaveBeenCalled();
235+
expect(services.location.path).toHaveBeenCalled();
243236

244237
$location.url('/new');
245238
$urlRouter.update();

0 commit comments

Comments
 (0)