Last active
November 29, 2018 15:55
-
-
Save tdamir/34861b86c015e3fb5c0e25d477b11bbb to your computer and use it in GitHub Desktop.
Aurelia parent+child route generation
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 { autoinject } from 'aurelia-dependency-injection'; | |
import { Router, RouterConfiguration } from 'aurelia-router'; | |
import { CompositionEngine } from 'aurelia-templating'; | |
import { relativeToFile } from 'aurelia-path'; | |
import { Origin } from 'aurelia-metadata'; | |
/** | |
* Usage: | |
* app.ts | |
* async attached(params, routeConfig, navigationInstruction) { | |
* await this.routeGenerator.configure(this.router); | |
* } | |
* | |
* page.ts | |
* | |
* let url = routeGeneratorService.generate([{ route: 'products', params: { id: 1 } }, { route: 'top', params: { top: 100 } } ]) | |
* // url should be 'products/1/top/100' | |
* | |
*/ | |
@autoinject() | |
export class RouteGeneratorService { | |
private _isConfigured: boolean = false; | |
private _routers: Router[] = []; | |
constructor(private compositionEngine: CompositionEngine) { | |
} | |
public async configure(router: Router) { | |
this._routers.push(router); | |
let childRouters = await this.getChildRouters(router); | |
this._routers.push(...childRouters); | |
this._isConfigured = true; | |
} | |
private async getChildRouters(router: Router): Promise<Array<Router>> { | |
let routers: Array<Router> = []; | |
for (let i = 0; i < router.navigation.length; i++) { | |
let navModel = router.navigation[i]; | |
if (navModel.config.moduleId) { | |
const childContainer = router.container.createChild(); | |
let context: any = { | |
viewModel: relativeToFile(navModel.config.moduleId, Origin.get((<any>router.container).viewModel.constructor).moduleId), | |
container: router.container, | |
childContainer: childContainer, | |
view: (<any>navModel.config).view || (<any>navModel.config).viewStrategy | |
}; | |
context = await this.compositionEngine.ensureViewModel(context); | |
if ('configureRouter' in context.viewModel) { | |
const childRouter = new Router(childContainer, router.history) | |
const childConfig = new RouterConfiguration() | |
context.viewModel.configureRouter(childConfig, childRouter); | |
childConfig.exportToRouter(childRouter); | |
routers.push(childRouter); | |
let childRouters = await this.getChildRouters(childRouter); | |
routers.push(...childRouters); | |
} | |
} | |
} | |
return routers; | |
} | |
public generate(routes: [{ routeName: string, params?: any, options?: any }]): string { | |
if (!this._isConfigured) | |
return ''; | |
return routes.map(route => { | |
return this._generate(route.routeName, route.params, route.options).replace('#', ''); | |
}).join(''); | |
} | |
private _generate(routeName: string, params?: any, options?: any): string { | |
if (!this._isConfigured) | |
return ''; | |
let url: string = ''; | |
for (let i = 0; i < this._routers.length; i++) { | |
let router = this._routers[i]; | |
if (router.hasRoute(routeName)) { | |
url = router.generate(routeName, params, options); | |
break; | |
} | |
} | |
return url; | |
} | |
} |
@tdamir The jsdoc should be:
/**
* Usage:
* app.ts
* async activate() {
* await this.routeGenerator.configure(this.router);
* }
*
* page.ts
*
* let url = routeGeneratorService.generate([{ routeName: 'products', params: { id: 1 } }, { routeName: 'top', params: { top: 100 } } ])
* // url should be 'products/1/top/100'
*
*/
@marekpw Better late than never... attached()
is not async but activate()
is. You can simply put the routeGenerator.configure()
inside activate
, like mentioned above, and it should work.
WARNING: This breaks route lazy loading.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Any ideas why the routes aren't generated before calling the generate method in a child module?
app.ts:
showcase.ts:
route-generator.ts:
output: