Skip to content

Commit 21acdca

Browse files
authored
feat(router): add DaffRouterActivatedRoute service (#2949)
1 parent f9bd6b5 commit 21acdca

File tree

4 files changed

+107
-0
lines changed

4 files changed

+107
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export * from './service';
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
import { Component } from '@angular/core';
2+
import { TestBed } from '@angular/core/testing';
3+
import {
4+
provideRouter,
5+
Router,
6+
} from '@angular/router';
7+
8+
import { DaffRouterActivatedRoute } from './service';
9+
10+
@Component({})
11+
class TestComponent {}
12+
13+
describe('@daffodil/router | DaffRouterActivatedRoute', () => {
14+
let service: DaffRouterActivatedRoute;
15+
let router: Router;
16+
17+
beforeEach(() => {
18+
TestBed.configureTestingModule({
19+
providers: [
20+
provideRouter([
21+
{
22+
path: '',
23+
children: [
24+
{
25+
path: '',
26+
data: {
27+
test: 'foo',
28+
},
29+
children: [
30+
{
31+
path: '',
32+
data: {
33+
foo: 'bar',
34+
},
35+
component: TestComponent,
36+
},
37+
],
38+
},
39+
],
40+
},
41+
]),
42+
],
43+
});
44+
45+
service = TestBed.inject(DaffRouterActivatedRoute);
46+
router = TestBed.inject(Router);
47+
});
48+
49+
it('should be created', () => {
50+
expect(service).toBeTruthy();
51+
});
52+
53+
it('should return the activated route for the current tree', (done) => {
54+
service.route$.subscribe((route) => {
55+
expect(route.snapshot.data['foo']).toEqual('bar');
56+
expect(route.snapshot.data['test']).toEqual('foo');
57+
done();
58+
});
59+
router.initialNavigation();
60+
});
61+
});
+44
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
import { Injectable } from '@angular/core';
2+
import {
3+
ActivatedRoute,
4+
NavigationEnd,
5+
Router,
6+
RouterState,
7+
} from '@angular/router';
8+
import {
9+
filter,
10+
map,
11+
Observable,
12+
shareReplay,
13+
} from 'rxjs';
14+
15+
const getActivatedRoute = (routerState: RouterState): ActivatedRoute => {
16+
let route = routerState.root;
17+
while (route.firstChild) {
18+
route = route.firstChild;
19+
}
20+
return route;
21+
};
22+
23+
/**
24+
* Allows accessing the currently activated route from anywhere in the DI hierarchy.
25+
* Contrasted to simply injecting `ActivatedRoute`, this will be accurate even from outside the router outlet.
26+
*
27+
* Note that this service operates by listening to router events. It is therefore recommended to
28+
* inject this service in the root and subscribe to `route$` on app init so that all routing events are captured.
29+
* The consumer can then subscribe at any later time (after all navigations) and the emission stream will be replayed.
30+
*/
31+
@Injectable({
32+
providedIn: 'root',
33+
})
34+
export class DaffRouterActivatedRoute {
35+
route$: Observable<ActivatedRoute> = this.router.events.pipe(
36+
filter((event) => event instanceof NavigationEnd),
37+
map(() => getActivatedRoute(this.router.routerState)),
38+
shareReplay(),
39+
);
40+
41+
constructor(
42+
private router: Router,
43+
) {}
44+
}

libs/router/src/public_api.ts

+1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
export * from './named-view/public_api';
22
export * from './data/public_api';
33
export * from './guards/public_api';
4+
export * from './activated-route/public_api';

0 commit comments

Comments
 (0)