Skip to content

Commit 6ed812f

Browse files
petebacondarwinmhevery
authored andcommitted
feat(aio): add LocationService.path() method (angular#16139)
This enables things like embedded components easy access to a clean version of the current location path.
1 parent 5461182 commit 6ed812f

File tree

3 files changed

+43
-0
lines changed

3 files changed

+43
-0
lines changed

aio/src/app/shared/location.service.spec.ts

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,37 @@ describe('LocationService', () => {
124124
});
125125
});
126126

127+
describe('path', () => {
128+
it('should ask Location for the current path without the hash', () => {
129+
const location: MockLocationStrategy = injector.get(LocationStrategy);
130+
const service: LocationService = injector.get(LocationService);
131+
132+
// We cannot test this directly in the following test because the `MockLocationStrategy`
133+
// does not remove the hash from the path, even if we do pass `false`.
134+
135+
spyOn(location, 'path').and.callThrough();
136+
service.path();
137+
expect(location.path).toHaveBeenCalledWith(false);
138+
});
139+
140+
it('should return the current location.path, with the query and trailing slash stripped off', () => {
141+
const location: MockLocationStrategy = injector.get(LocationStrategy);
142+
const service: LocationService = injector.get(LocationService);
143+
144+
location.simulatePopState('a/b/c?foo=bar&moo=car');
145+
expect(service.path()).toEqual('a/b/c');
146+
147+
location.simulatePopState('c/d/e');
148+
expect(service.path()).toEqual('c/d/e');
149+
150+
location.simulatePopState('a/b/c/?foo=bar&moo=car');
151+
expect(service.path()).toEqual('a/b/c');
152+
153+
location.simulatePopState('c/d/e/');
154+
expect(service.path()).toEqual('c/d/e');
155+
});
156+
});
157+
127158
describe('search', () => {
128159
it('should read the query from the current location.path', () => {
129160
const location: MockLocationStrategy = injector.get(LocationStrategy);

aio/src/app/shared/location.service.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,16 @@ export class LocationService {
4242
return url.replace(/^\/+/, '');
4343
}
4444

45+
/**
46+
* Get the current path, without trailing slash, hash fragment or query params
47+
*/
48+
path(): string {
49+
let path = this.location.path(false);
50+
path = path.match(/[^?]*/)[0]; // strip off query
51+
path = path.replace(/\/$/, ''); // strip off trailing slash
52+
return path;
53+
}
54+
4555
search(): { [index: string]: string; } {
4656
const search = {};
4757
const path = this.location.path();

aio/src/testing/location.service.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ export class MockLocationService {
77
setSearch = jasmine.createSpy('setSearch');
88
go = jasmine.createSpy('Location.go').and
99
.callFake((url: string) => this.urlSubject.next(url));
10+
path = jasmine.createSpy('Location.path').and
11+
.callFake(() => this.urlSubject.getValue().split('?')[0]);
1012
handleAnchorClick = jasmine.createSpy('Location.handleAnchorClick')
1113
.and.returnValue(false); // prevent click from causing a browser navigation
1214

0 commit comments

Comments
 (0)