router icon indicating copy to clipboard operation
router copied to clipboard

Support eagerly configuring child routers

Open bryanrsmith opened this issue 10 years ago • 46 comments

Lazily configuring child routers has a couple downsides:

  1. We can't support hierarchical nav menus because the application's route structure isn't known until all child routes are activated.
  2. More importantly, we can't support generating URLs for routes in "sibling" routers for the same reason.

If we let child routers be eagerly configured we could implement features that require knowledge of the whole apps routing structure. Ideas:

  1. We could let route configs specify child router configs inline, so an App module could configure a larger hierarchy of routes.
  2. We could let route config objects indicate that their modules will configure a child router that should be eager-loaded.

bryanrsmith avatar May 08 '15 04:05 bryanrsmith

+1 this would indeed be a nice enhancement. :)

sorenhoyer avatar Oct 14 '15 20:10 sorenhoyer

I would love this, as well. Until then, is there a workaround one could use?

aozisik avatar Feb 17 '16 19:02 aozisik

+1 for this feature, at least a workaround to avoid first route routing issue.

npelletm avatar Feb 17 '16 20:02 npelletm

+1 - fingers crossed for this!

larsfjerm avatar Feb 17 '16 20:02 larsfjerm

+1 configuring routes in the ViewModel isn't really pretty

Cedware avatar Feb 24 '16 15:02 Cedware

+1

danlourenco avatar Mar 25 '16 20:03 danlourenco

For the next RC could we expected this feature ?

npelletm avatar Mar 25 '16 20:03 npelletm

+1

claylaut avatar Mar 26 '16 10:03 claylaut

Sorry, but I don't know of any plans to work on this before 1.0. I really want it too, but I haven't had much time to spare lately. If anyone wants to work on a PR I'd be more than happy to discuss the necessary changes and answer questions.

bryanrsmith avatar Mar 27 '16 17:03 bryanrsmith

+1

ngelx avatar Apr 03 '16 02:04 ngelx

+1

bhatnagar-ankur avatar Jun 06 '16 09:06 bhatnagar-ankur

+1, any plans on this feature?

ogliznutsa avatar Jul 13 '16 17:07 ogliznutsa

We are working towards v1 release in the next few weeks. After that we'll look at adding some new features to the router. This is high on the list.

(As this is open source, all community members are welcome to implement this and send a PR. That helps to move certain requests ahead faster.)

EisenbergEffect avatar Jul 13 '16 17:07 EisenbergEffect

I think the solution for this and https://github.com/aurelia/router/issues/89 should address a more general scenario. Aurelia is so modular it comes natural to have an app built upon different external modules which may contribute to the route hierarchy. For example:

/       (main-app)
/admin  (admin-app)
/blog   (blog-app)
/wiki   (wiki-app)

Then blog-app and wiki-app may depend both on admin-app, and their view-models might need to generate a route to a view-model in admin-app (for example a user's profile). Problem is, the code of both apps do not know how main-app would configure the base path for admin-app (could be nested too)! The only assumption an app can make about a route of another app it depends on is that it should be mapped somewhere in the hierarchy.

The solution I propose in https://github.com/aurelia/router/issues/89#issuecomment-237277713 could work for this if it's supposed to start from the AppRouter (which AFAIK is the root router of the app) and its generate function which would take a path of route names to let the router navigate through the path building and configuring the needed children and expanding the route templates it encounters with provided parameters. For example, a view-model in blog-app may call router.generate('admin-app/users/profile', { id: user.id }).

I'm willing to work on this, but since it's a bit of a work and I need to study the router internals, I'd like to know if it could be an accepted solution or not 😉

heruan avatar Aug 04 '16 10:08 heruan

@heruan We'd love to have you work on it. It's a very tricky problem, especially since the child apps may not even be loaded and you've got to account for parameters and wild cards at various levels.

EisenbergEffect avatar Aug 04 '16 14:08 EisenbergEffect

I'm just studying the RouteLoader logic and since loading is involved it's clear that generate will never be able to return synchronously. I'm evaluating a more straightforward approach, of a RouteMapper which would be built with all the involved routers configurations and thus have a static hierarchy of url templates. I'll publish ASAP a repo with examples.

heruan avatar Aug 04 '16 14:08 heruan

Yeah, whatever is done here, it has to be considered how it might affect bundling. Lets say we have the root router, and a child router for each area of the site. The app would also be bundled this way; one core bundle, and one bundle for each area.

To make this work, I think we would need to move the configureRouter function to a separate file, such that this file can be included in the core bundle, despite being physically located in the directory of an area, thus keeping the solution nice and organized.

Having the configureRouter function in the view model of a router view is problematic, as the view model may, for whatever other reasons, need to reference other things within the area-specific bundle, thus preventing us from including it in the core app bundle - because if we did, it would effectively end up pulling the entire area bundle into the core bundle.

Maybe this could be as simple as moving the configureRouter function to an index.js file in the area folder (i.e. next to the view model it would currently be defined in), and simply have the router eagerly look for that file by convention? Then we could include those index.ts files in the core bundle.

Of course, this "eagerly look for index.ts" behavior should be explicitly enabled with a per-route option - this way it won't break existing code, and it allows some routers to be eagerly configured and others lazy.

Maybe this could somehow tie in nicely with https://github.com/aurelia/framework/issues/427?

Does that make sense?

thomas-darling avatar Aug 04 '16 14:08 thomas-darling

I think this could be a good approach. One idea I had, just off the top of my head, was very similar. Basically, enable a separate mapper or some additional config at the app level that would provide info for generation. Child routers could maybe reference this information so they didn't need to repeat themselves. It's a difficult problem. We are open to ideas.

EisenbergEffect avatar Aug 04 '16 14:08 EisenbergEffect

I came up with this: https://github.com/heruan/aurelia-route-mapper and this example app: https://github.com/heruan/aurelia-route-mapper-example

The concept is to use a RouteMapper which is an extended RouteRecognizer and has a map(routes: RouteConfig[]) function which adds to its recognized routes the ones passed as the argument, but also looks for a settings.childRoutes and recursively adds them prefixing names and routes accordingly.

Any external application or submodule could just export its routes and the main application will configure the RouteMapper.

heruan avatar Aug 04 '16 16:08 heruan

@heruan Your solution has worked really well for me! Are you planning any more work on it?

Kukks avatar Oct 24 '16 13:10 Kukks

@Kukks Yes, I'm currently working on a JavaScript object-mapper but I'm open to suggestions on how to improve the route-mapper!

heruan avatar Oct 27 '16 13:10 heruan

@thomas-darling I also had the similar idea, how about just making only the routes a separate file like symfony and not the whole function which could be basically models/data holders. So this way maybe it will be cheap on resources eagerly loaded.

deviprsd avatar Nov 10 '16 19:11 deviprsd

@heruan Thanks for the good job. I tried the demo you provided and it worked nicely. @EisenbergEffect Can we go ahead to use this? Any idea if this will be added to one of the releases soon? Thanks

smithaitufe avatar Nov 27 '16 11:11 smithaitufe

@bryanrsmith I'd love to see what you think of the solution that @heruan has come up with. It seems like we could build this into Aurelia without much work if we think it will solve the problem. Let me know what you think.

EisenbergEffect avatar Nov 27 '16 21:11 EisenbergEffect

I found this to be good solution and simple and its working ...

http://www.jeremyg.net/entry/create-a-menu-with-child-routes-using-aurelia

https://github.com/jagonalez/aurelia-menu

activebiz avatar Feb 23 '17 06:02 activebiz

@heruan I've ended up using your route-mapper and its concepts and made a package for my use case where I can generate child router applications registered without loading them. https://github.com/Kukks/aurelia-modules-example The examples themselves may be a little out of date as I'm working on the src in another private project as part of the solution.

Kukks avatar Feb 23 '17 11:02 Kukks

I have a modified version of solution suggested by @activebiz. First we have to gather all the routes from all modules and after that we can use the service to generate the parent/child route combination like this: routeGeneratorService.generate([{ route: 'products', params: { id: 1 } }, { route: 'top', params: { top: 100 } } ])

The code: https://gist.github.com/tdamir/34861b86c015e3fb5c0e25d477b11bbb

tdamir avatar Feb 23 '17 18:02 tdamir

Thanks for the mention @activebiz

Just my two cents but I believe the solution proposed by @heruan is more elegant.

As I mentioned in my blog post using the composition engine loads each module in the route config which could cause performance issues.

I don't believe it'll retrieve any routes added using the router instead of the RouterConfiguration.

jagonalez avatar Feb 23 '17 19:02 jagonalez

I agree that loading modules in advance could cause performance issues and is a very hacky. I also agree that the solution @heruan proposed is more elegant and not that hacky. I might be missing something but I think that the route-mapper cannot handle parent+child navigation properly if the name of route parameters is the same (eg. parentRoute/{id}, childRoute/{id})?

tdamir avatar Feb 24 '17 08:02 tdamir

I've forked a route-mapper and handled the problem I mentioned before. If someone needs it: https://github.com/tdamir/aurelia-route-mapper

tdamir avatar Feb 25 '17 23:02 tdamir