Created
March 22, 2017 10:00
-
-
Save klinki/7fd7cc3eadb1c120c4f007154fb7e6c0 to your computer and use it in GitHub Desktop.
Angular Route Flattener
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import {ActivatedRouteSnapshot, UrlSegment, Params, Data, Route} from "@angular/router"; | |
import {Type, Injectable} from "@angular/core"; | |
import {Subject, ReplaySubject} from "rxjs"; | |
@Injectable() | |
export class RouteFlattenerService { | |
public getFlattenedRouteData(route: ActivatedRouteSnapshot): FlattenedRouteData { | |
let downLevel = this.getActivatedRouteSnapshotWithChildren(route); | |
downLevel.splice(0, 1); | |
let upLevel = this.getActivatedRouteSnapshotWithParents(route); | |
upLevel.pop(); | |
let result: FlattenedRouteData = this.mergeAllRoutes( | |
...upLevel, | |
this.getRoute(route), | |
...downLevel | |
); | |
return result; | |
} | |
public getActivatedRouteSnapshotWithParents(route: ActivatedRouteSnapshot): ActivatedRouteSnapshot[] { | |
let result = [ route ]; | |
if (route.parent) { | |
let parents = this.getActivatedRouteSnapshotWithParents(route.parent); | |
result = parents.concat(result); | |
} | |
return result; | |
} | |
public getActivatedRouteSnapshotWithChildren(route: ActivatedRouteSnapshot): ActivatedRouteSnapshot[] { | |
let result = [ route ]; | |
if (route.firstChild) { | |
let children = this.getActivatedRouteSnapshotWithChildren(route.firstChild); | |
result = result.concat(children); | |
} | |
return result; | |
} | |
public getFlattenedRouteBottomUp(route: ActivatedRouteSnapshot, includeSelf: boolean = true): FlattenedRouteData { | |
let result = { params: {}, data: {} }; | |
if (includeSelf) { | |
result = this.getRoute(route); | |
} | |
if (route.parent) { | |
let parent = this.getFlattenedRouteBottomUp(route.parent); | |
result = this.mergeRoutes(parent, result); | |
} | |
return result; | |
} | |
public getFlattenedRouteTopDown(route: ActivatedRouteSnapshot, includeSelf: boolean = true): FlattenedRouteData { | |
let result = { params: {}, data: {} }; | |
if (includeSelf) { | |
result = this.getRoute(route); | |
} | |
if (route.firstChild) { | |
let child = this.getFlattenedRouteTopDown(route.firstChild); | |
result = this.mergeRoutes(result, child); | |
} | |
return result; | |
} | |
protected getRoute(route: ActivatedRouteSnapshot): FlattenedRouteData { | |
let result: FlattenedRouteData = Object.assign({ | |
snapshotsHierarchy: [ route ], | |
routeConfig: route.routeConfig | |
}, route); | |
return result; | |
} | |
protected getRouteConfigHierarchy(route: FlattenedRouteData): Route[] { | |
let routeConfig = []; | |
if (route.routeConfigHierarchy) { | |
routeConfig = [].concat(route.routeConfigHierarchy); | |
} else if (route.routeConfig) { | |
routeConfig = [].concat([ route.routeConfig ]); | |
} | |
return routeConfig; | |
} | |
protected mergeAllRoutes(...routes: FlattenedRouteData[]): FlattenedRouteData | |
{ | |
let result = { | |
data: {}, | |
params: {}, | |
url: [], | |
routeConfigHierarchy: [], | |
snapshotsHierarchy: [] | |
}; | |
Object.assign(result.data, ...(routes.map(route => route.data))); | |
Object.assign(result.params, ...(routes.map(route => route.params))); | |
result.routeConfigHierarchy = [].concat( | |
...routes.map(route => this.getRouteConfigHierarchy(route)) | |
); | |
result.snapshotsHierarchy = routes; | |
result.url = routes.map(route => route.url).filter(array => array.length > 0); | |
return result; | |
} | |
protected mergeRoutes(parent: FlattenedRouteData, child: FlattenedRouteData): FlattenedRouteData { | |
let result = { | |
data: {}, | |
params: {}, | |
url: [], | |
routeConfigHierarchy: [], | |
snapshotsHierarchy: [] | |
}; | |
Object.assign(result.data, parent.data, child.data); | |
Object.assign(result.params, parent.params, child.params); | |
result.routeConfigHierarchy = [].concat( | |
this.getRouteConfigHierarchy(parent), | |
this.getRouteConfigHierarchy(child) | |
); | |
result.snapshotsHierarchy = [].concat(parent.snapshotsHierarchy, child.snapshotsHierarchy); | |
result.url = parent.url.concat(child.url); | |
return result; | |
} | |
} | |
export interface FlattenedRouteData { | |
params: Params; | |
data: Data; | |
url?: UrlSegment[]; | |
routeConfig?: Route; | |
routeConfigHierarchy?: Route[]; | |
snapshotsHierarchy?: ActivatedRouteSnapshot[]; | |
} | |
export interface FullFlattenedRoute { | |
/** | |
* The URL segments matched by this route. | |
*/ | |
url: UrlSegment[]; | |
/** | |
* The matrix parameters scoped to this route. | |
*/ | |
params: Params; | |
/** | |
* The query parameters shared by all the routes. | |
*/ | |
queryParams: Params; | |
/** | |
* The URL fragment shared by all the routes. | |
*/ | |
fragment: string; | |
/** | |
* The static and resolved data of this route. | |
*/ | |
data: Data; | |
/** | |
* The outlet name of the route. | |
*/ | |
outlet: string; | |
/** | |
* The component of the route. | |
*/ | |
component: Type<any> | string; | |
/** | |
* The configuration used to match this route. | |
*/ | |
routeConfig: Route; | |
/** | |
* The root of the router state. | |
*/ | |
root: ActivatedRouteSnapshot; | |
/** | |
* The parent of this route in the router state tree. | |
*/ | |
parent: ActivatedRouteSnapshot; | |
/** | |
* The first child of this route in the router state tree. | |
*/ | |
firstChild: ActivatedRouteSnapshot; | |
/** | |
* The children of this route in the router state tree. | |
*/ | |
children: ActivatedRouteSnapshot[]; | |
/** | |
* The path from the root of the router state tree to this route. | |
*/ | |
pathFromRoot: ActivatedRouteSnapshot[]; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import {Component, OnInit} from "@angular/core"; | |
import {Router, ActivatedRoute} from "@angular/router"; | |
import {RouteFlattenerService} from "../../core/routing/route-flattener.service"; | |
@Component({ | |
templateUrl: './some.component.html', | |
}) | |
export class SomeComponent implements OnInit { | |
public constructor( | |
protected _router: Router, | |
protected _activatedRoute: ActivatedRoute, | |
protected _routeFlattener: RouteFlattenerService | |
) { | |
} | |
ngOnInit(): void { | |
this.router.events | |
.filter(event => event instanceof NavigationEnd) | |
.subscribe((event: NavigationEnd) => { | |
let flattenedRouteData = this._routeFlattener.getFlattenedRouteData(this._activatedRoute.snapshot); | |
}); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment