-
-
Notifications
You must be signed in to change notification settings - Fork 5.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Dynamically add child routes to an existing route #1156
Dynamically add child routes to an existing route #1156
Comments
Since the //MiniApp.js
export const MiniAppRoutes = [
{path: 'a', component: ComponentA, name: 'a'},
{path: 'b', component: ComponentB, name: 'b'},
];
export default Vue.extend({...});
//////////////////////////////////////////////////////////
//The app itself
Vue.use(Router);
import MiniApp, { MiniAppRoutes } from "./MiniApp";
const config = {
routes: [
{path: '/mini', component: MiniApp, name: 'mini', children: MiniAppRoutes }},
]
};
let router = new Router(config); |
@fnlctrl you are right when the app is loaded synchronously, but this is just an example. |
But the routes must be loaded synchronously, otherwise when visiting a url that uses a lazy loaded component, the router won't be able to recognize that route. e.g. const config = {
routes: [
{path: '/mini', component: () => System.import('mini-app'), name: 'mini' }},
]
}; Now, when directly visiting |
Same case in my project. |
@varHarrie For that use case, we already have a better and simpler solution: |
Need this also as my app loads modules, each module has a setup method that registers their properties and I need a way to add a child route dynamically. Tried:
but after digging inside realized that it generates a route map only when addRoutes is called, so it does not find other routes :\ |
Honestly, a |
@posva Is there a plan to implement this? Being able to specify |
Yeah, but I think that taking an optional first parameter for the parent may be better: // parentName is a string and must match a route's name
addRoutes([parentName, ]routes) For the moment, nobody is looking into this. We'll come when we can 🙂 |
I like it @posva, I will take a stab at it as soon as I have some free time and submit a PR. |
Could we go one step further and add support for lazy loaded children. This could be done by allowing children to be of types: We will also need support for deep linking into an async child route. |
@patrickhousley It's unrelated to this issue, but you can already lazy load children components |
@posva I assume you are talking about being able to lazy load components in general. If so, I am already doing that. What I am saying is it would be nice if we could lazy load the children router configuration. Lazy load components: // src/routes.ts
export const routes: VueRouter.RouteConfig[] = [
{
path: '/lazy',
children: [
{
path: '/one',
component: async () => new Promise<Vue>(resolve => {
require.ensure(
[],
async require => {
resolve((require('./one.component.ts') as { OneComponent: Vue }).OneComponent);
},
'lazy'
);
})
},
{
path: '/two',
component: async () => new Promise<Vue>(resolve => {
require.ensure(
[],
async require => {
resolve((require('./two.component.ts') as { TwoComponent: Vue }).TwoComponent);
},
'lazy'
);
})
}
]
}
]; There is nothing wrong with this code. It is just very verbose to read and write. Lazy loaded children configuration: // src/routes.ts
export const routes: VueRouter.RouteConfig[] = [
{
path: '/lazy',
children: async () => new Promise<Vue>(resolve => {
require.ensure(
[],
async require => {
resolve((require('./lazy/routes') as { routes: VueRouter.RouteConfig[] }).Routes);
},
'lazy'
);
})
}
];
// /lazy/routes.ts
export const routes: VueRouter.RouteConfig[] = [
{
{
path: '/one',
component: OneComponent
},
{
path: '/two',
component: TwoComponent
}
}
]; |
Please take a look to vue-tidyroutes it's a simple package to handle routes registration in your project. |
I want the components to be able to add its own routes once they are registered in the app. |
yeah ,maybe need append some childrens. |
👍 Much needed feature in our code, to handle an infinte levels hierarchy. |
Nested dynamic routers would be extremely useful. The composability of vue is its strong point, and that shouldn't stop at the router. Does anyone know of an alternative Vue router that has this functionality? |
Last night I worked on this, maybe this could be a possible solution or maybe keep 2 parameters in the next PR #2064. Greetings. |
@Dri4n could you explain a little bit how the new behavior from your PR works? I read it but not being very familiar with Vue internally, I'm not sure sure. Would that allow me to add routes to a router and Vue instance that has already been initiated? |
@light24bulbs I'm sorry, but this PR is not yet accepted, basically it's about adding routes to a parent route dynamically (once this instanced vue router), this depends on the name or path of the parent route, if they accept it I will add the corresponding documentation, thank you! |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
Any update on adding this much needed feature? |
I have written a simple library for dynamically add routes to an existing route, vue-mfe/src/core/router/index.js. the idea was inspired from @coxy's comment, thanks for that suggestion. this library was not only to enhance hope it can be helpful for someone who needs. |
Still waiting for this feature~🌟 |
vue-router/src/create-route-map.js Lines 24 to 26 in 5118824
function createRouteMap (
routes,
oldPathList,
oldPathMap,
oldNameMap
) {
// the path list is used to control path matching priority
var pathList = oldPathList || [];
// $flow-disable-line
var pathMap = oldPathMap || Object.create(null);
// $flow-disable-line
var nameMap = oldNameMap || Object.create(null);
routes.forEach(function (route) {
/* ---- MODIFICATION:start --------------------------- */
let parent = route.parent && oldNameMap[route.parent.name] ||
route.parent && oldPathMap[route.parent.path] ;
route.parent && route.parent.name && assert(parent , 'Inexistant parent with name :\n\t' + route.parent.name);
route.parent && route.parent.path && assert(parent , 'Inexistant parent with path :\n\t' + route.parent.path);
/*addRouteRecord(pathList, pathMap, nameMap, route);*/
addRouteRecord(pathList, pathMap, nameMap, route, parent);
/* ---- MODIFICATION:end --------------------------- */
});
// ensure wildcard routes are always at the end
for (var i = 0, l = pathList.length; i < l; i++) {
if (pathList[i] === '*') {
pathList.push(pathList.splice(i, 1)[0]);
l--;
i--;
}
}
. . . By adding this modification, i think it will be possible to
let initialConfig = [
{
name : 'app-home',
path : '/' ,
component : lazyLoader('/path/to/app/home.js')
},
{
name : 'app-404' ,
path : '*' ,
component : lazyLoader('/path/to/app/404.js')
} ,
];
// classic and actual way to init routes
const myRouter = new VueRouter({
routes : initialConfig ,
})
/* Later you can do */
let modulesHolder = [
{
name : 'app-modules' ,
path : '/module' ,
component : lazyLoader('/path/to/app/modules.js')
}
];
// classic and actual way to add routes
myRouter.addRoutes( modulesHolder );
/* Later again you can do */
let moduleTest = [
{
name : 'app-module-test' ,
path : 'test' ,
/* - - New Key = parent : define parent by path - - - - - - - - */
parent : { path : '/module' } ,
component : lazyLoader('/path/to/app/modules/test/index.js')
}
];
// matched route = /module/test
myRouter.addRoutes( moduleTest );
/* Later again you can do */
let moduleOther = [
{
name : 'app-module-other' ,
path : 'other' ,
/* - - New Key = parent : define parent by name - - - - - - - - */
parent : { name : 'app-modules' } ,
component : lazyLoader('/path/to/app/modules/other/index.js')
}
];
// matched route = /module/other
myRouter.addRoutes( moduleOther ); |
@donnysim what happens when you're on a child root and refresh the page with that? |
Mmm... Once the modification on main code done, it will open possibility ... myRouter.addAbsentChildRoutes = ( parent, children ) {
let list = children.filter( child =>
let result = myRouter.match({path: child.path , name: child.name});
let haveResult = result.matched && result.matched.length;
if(!haveResult) return true;
return result.matched[0].path === '*' ? true : false;
});
return myRouter.addChildRoutes( parent, list);
}
myRouter.addChildRoutes = ( parent, children ) {
/* check and filter what you want */
return myRouter.addRoutes( children.map( child => {
if( ! child.parent ) child.parent = parent;
return child;
});
}
/* and more and more . . . */ |
@posva what do you think about this addition ? vue-router/src/create-route-map.js Lines 24 to 26 in 5118824
have to become : routes.forEach(function (route) {
let parent = route.parent && oldNameMap[route.parent.name] ||
route.parent && oldPathMap[route.parent.path] ;
route.parent && route.parent.name && assert(parent , 'Inexistant parent with name :\n\t' + route.parent.name);
route.parent && route.parent.path && assert(parent , 'Inexistant parent with path :\n\t' + route.parent.path);
/*addRouteRecord(pathList, pathMap, nameMap, route);*/
addRouteRecord(pathList, pathMap, nameMap, route, parent);
}); And this little modification will permit to dynamically add child routes to an existing route ! |
Has this been implemented yet?? |
Apparently no addChildRoutes, but i am interested by this feature. Currently i use this :
But he generate a warn : Anybody can't push a commit ? |
registering child routes dynamically is a feature that every router (angular/react/...) supports. the priority of this feature should be on highest level IMHO. |
@posva It seems from the comments and upvotes that this is a much needed feature. I too need it. Any news where it stands? |
@JonathanDn This will be added once vuejs/rfcs#122 is merged. That way we can keep the same api surface for |
@posva routes.forEach(function (route) {
let parent = route.parent && oldNameMap[route.parent.name] ||
route.parent && oldPathMap[route.parent.path] ;
route.parent && route.parent.name && assert(parent , 'Inexistant parent with name :\n\t' + route.parent.name);
route.parent && route.parent.path && assert(parent , 'Inexistant parent with path :\n\t' + route.parent.path);
/*addRouteRecord(pathList, pathMap, nameMap, route);*/
addRouteRecord(pathList, pathMap, nameMap, route, parent);
}); It doesn't produce any breaking changes, it just adds such long-awaited functionality. I don't know if Vue-Router 4.x will only be compatible with Vue 3.0, so for now we can have a solution for Vue 2.x and Vue-Router 3.x. It will be available now! Thank you for your work and your time. |
I am building a large scale application with "mini applications" hosted within the application.
Each mini application is being developed by another team.
I would like to dynamically add nested child routes to an existing route to allow dynamic registration of each of the mini apps.
for example:
The text was updated successfully, but these errors were encountered: