Created
December 13, 2016 13:43
-
-
Save klinki/8bb6b1f80585cebdaa66552301356d4c to your computer and use it in GitHub Desktop.
RouteLinkProviderService - service which maps component into its route
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 {Routes, Route} from "@angular/router"; | |
import {Injectable} from "@angular/core"; | |
@Injectable() | |
export class RouteLinkProviderService { | |
protected routes: Routes; | |
protected routesByComponents = new Map<any, any>(); | |
constructor(routes: Routes) { | |
this.routes = routes; | |
let componentRoutes = this.getComponentRoutes(routes); | |
console.log(componentRoutes); | |
this.routesByComponents = this.getComponentRouteMap(componentRoutes); | |
} | |
protected getComponentRoutes(routes: Routes, predecessors: any[] = []): Route[] { | |
let finalRoutes = []; | |
routes.forEach((route: Route) => { | |
if (route.component && (!route.children || route.children.length === 0)) { | |
finalRoutes.push(this.createRoutingEntry(route, predecessors)); | |
} else if (route.children) { | |
let currentPredecessors = predecessors.slice().concat([route]); | |
let nestedRoutes = this.getComponentRoutes(route.children, currentPredecessors); | |
nestedRoutes.forEach(item => finalRoutes.push(item)); | |
} | |
}); | |
return finalRoutes; | |
} | |
protected getComponentRouteMap(routingEntries: any[]) { | |
let routesByComponents = new Map<any, any>(); | |
routingEntries.forEach((entry) => { | |
routesByComponents.set(entry.route.component, entry); | |
}); | |
return routesByComponents; | |
} | |
protected createRoutingEntry(route: Route, predecessors: Routes) { | |
let result = { | |
url: '', | |
route: route, | |
parameters: [] | |
}; | |
let fullRouteHierarchy = predecessors.concat([route]); | |
fullRouteHierarchy.forEach((part: Route) => { | |
if (part.path !== '' && part.path !== '/') { | |
result.url += '/' + part.path; | |
} | |
}); | |
let parameters = result.url.match(/:(\w+)/g); | |
if (parameters) { | |
result.parameters = parameters.map(param => param.substring(1));; | |
} | |
return result; | |
} | |
public getRouteForComponent(component: any, parameters?: any|any[]|Object) { | |
if (!this.routesByComponents.has(component)) { | |
throw new Error("Route for component not found!") | |
} | |
let routingEntry = this.routesByComponents.get(component); | |
let url = routingEntry.url; | |
let routingParameters = {}; | |
if (routingEntry.parameters) { | |
if (!parameters) { | |
throw new Error("Route has parameters, but none were provided"); | |
} else if (Array.isArray(parameters)) { | |
routingParameters = this.getParametersFromArray(routingEntry.parameters, <any[]>parameters); | |
} else if (typeof parameters === 'object') { | |
routingParameters = this.getParametersFromObject(routingEntry.parameters, <Object>parameters); | |
} else if (this.isScalar(parameters)) { | |
if (routingEntry.parameters.length > 1) { | |
throw new Error("Route has multiple parameters, need to provide array or object with parameters"); | |
} | |
routingParameters = {}; | |
routingParameters[routingEntry.parameters[0]] = parameters; | |
} | |
Object.keys(routingParameters).forEach((parameter) => { | |
url = url.replace(':' + parameter, routingParameters[parameter]); | |
}); | |
} | |
return url; | |
} | |
protected isScalar(obj: any): boolean { | |
return (/string|number|boolean/).test(typeof obj); | |
} | |
protected getParametersFromArray(expectedParameters: string[], givenParameters: any[]) { | |
if (expectedParameters.length !== givenParameters.length) { | |
throw new Error(`Expecting ${expectedParameters.length} parameters, but ${givenParameters.length} given`); | |
} | |
let routeParameters = {}; | |
expectedParameters.forEach((name, index) => { | |
routeParameters[name] = givenParameters[index]; | |
}); | |
return routeParameters; | |
} | |
protected getParametersFromObject(expectedParameters: string[], givenParameters: {[key: string]: any}) { | |
let routeParameters = {}; | |
expectedParameters.forEach((name) => { | |
if (!givenParameters.hasOwnProperty(name)) { | |
throw new Error(`Parameter ${name} not found in provided parameters object`); | |
} | |
routeParameters[name] = givenParameters[name]; | |
}); | |
return routeParameters; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment