Dynamic nested routes in Nuxt - vue.js

I've got to grips with static routes and dynamic routes in Nuxt.
However, I'm trying to work out if it's possible to have effectively unlimited nested pages.
For example, in a standard CMS such as Wordpress I can define a deep nest of pages such as:
*hostname.com/page/other-page/another/yet-another/one-more/final-page*
I suppose I could define an unnecessarily deep page structure, such as:
- /_level1
- index.vue
/_level2
- index.vue
/ _level3
- index.vue
/level4
-index.vue
...and so on. But this doesn't feel particularly efficient or scalable, and introduces lots of duplicate code and maintenance problems.
Is there a better way to achieve this?

You can use nested routes with the "children" option.
https://router.vuejs.org/guide/essentials/nested-routes.html
const router = new VueRouter({
routes: [
{ path: '/user/:id', component: User,
children: [
{
// UserProfile will be rendered inside User's <router-view>
// when /user/:id/profile is matched
path: 'profile',
component: UserProfile
},
{
// UserPosts will be rendered inside User's <router-view>
// when /user/:id/posts is matched
path: 'posts',
component: UserPosts
}
]
}
]
})
You can also import child routes from a separate file.
import UserRoutes from "./users/router.js"
const router = new VueRouter({
routes: [
{ path: '/user/:id', component: User,
children: UserRoutes
}
]
})
Then in your users/router.js:
export default [
{
// UserProfile will be rendered inside User's <router-view>
// when /user/:id/profile is matched
path: 'profile',
component: UserProfile
},
{
// UserPosts will be rendered inside User's <router-view>
// when /user/:id/posts is matched
path: 'posts',
component: UserPosts
}
]

Related

Vue router redirecting to home page on reload

I have an vue app with many routes. Whenever I try to reload a page it is always redirecting me to the home page instead of refreshing the current page.
Below is my router setting:
export default new Router({
mode: 'history',
base: process.env.BASE_URL,
routes: [
{
path: '/',
name: 'home',
component: Home,
children: [
{
path: "/dashboard",
name: 'dashboard',
component: DashboardView
},
{
path: "/About",
name:'about',
component: About
},
{
path: "/comments",
name:'comments',
component: Comments
},
]
}
How to refresh the current page instead of redirection to home page.
Well, assuming your process.env.BASE_URL exists and it is correct, the home component is your entry point.
From your routes list you placed About as a child of home, probably you meant that to be outside.
Anyway, try to make all of them non-children, once you are sure they all work as expected, try the nested children approach again but please note from the Docs:
Note that nested paths that start with / will be treated as a root path. This allows you to leverage the component nesting without having to use a nested URL.
Reference:
https://router.vuejs.org/guide/essentials/nested-routes.html

How to achieve n levels of nested dynamic routes in Vue.js?

I want to achieve n levels of dynamic nested routes in Vue.js, where n is unknown to me.
for eg -
abc.com/ctx-path/component/1/2/...../n
where 1,2,...n are the levels
How can I achieve this with Vue-router?
Behind the scenes vue-router path matching uses path-to-regexp.
So it should be possible to write something like this
{ path: '/ctx-path/component/:id+', component: Component }
or
{ path: '/ctx-path/component/:id*', component: Component }
You could also add path dynamically at run time, but you'll need to have a trigger to add it.
One last option is to have a catch all route and add your own logic.
This is from docs:
const router = new VueRouter({
routes: [
{ path: '/user/:id', component: User,
children: [
{
// UserProfile will be rendered inside User's <router-view>
// when /user/:id/profile is matched
path: 'profile',
component: UserProfile
},
{
// UserPosts will be rendered inside User's <router-view>
// when /user/:id/posts is matched
path: 'posts',
component: UserPosts
}
]
}
]
})
see link https://router.vuejs.org/guide/essentials/nested-routes.html
Double dynamic nested routes to filter a single view by the nested URL params
const routes = [
{
path: '/category/:categoryId',
name: 'category',
component: () =>
import(/* webpackChunkName: "product" */ '../views/Categories.vue'),
props: (route: Route) => ({
categoryId: route.params.categoryId,
}),
},
{
path: '/category/:categoryId/:attributeIdsJsonString',
name: 'attributeFilter',
component: () =>
import(/* webpackChunkName: "product" */ '../views/Categories.vue'),
props: (route: Route) => ({
categoryId: route.params.categoryId,
attributeIdsJsonString: route.params.attributeIdsJsonString,
}),
},
];
const router = new VueRouter({
routes,
});
Using different route names like this will mean that beforeRouteUpdate won't fire in some instances, so use beforeRouteEnter as well

Vuejs Display a router name in Component

How can I display a router name in a component ?
Example:
const routes = [
{ path: '/documents', component: Documents, name:"Documents" ,props:true},
{ path: '/queries', component: Queries, name:"Queries", props:true}
]
I want to display the name property as a title in the component. Is this possible? how?
props:true will convert path parameters to properties:
{ path: '/documents/:name', component: Documents, name:"Documents", props:true},
You can use an object instead of true and then send in a string.
{ path: '/documents', component: Documents, name:"Documents", props:{ name:'Documents'}},
In your component, register the property
props: { name:String }
And then use it in a template like this:
<div>{{name}}</div>
You can also refer to the route name using the components $route object
<div>{{$route.name}}</div>
To specify title to a component you can use router's meta property, Link
const routes = [
{
path: '/documents',
component: Documents,
name:"Documents" ,
props:true,
meta: {
title: 'Documents'
}
},
{
path: '/queries',
component: Queries,
name:"Queries",
props:true,
meta: {
title: 'Queries'
}
}
]
In main.js,
import router from '#/routes'
router.beforeEach((to, from, next) => {
document.title = `Currently at - ${to.meta.title}`
next()
})

VueRouter omitting the forward slash before the # in non-history mode

i'm trying to use VueRouter 2.2.1 in my Laravel application and for some reason my URL's (although working) show the # symbol in a weird way
http://myapp.dev/admin#/
Instead of
http://myapp.dev/admin/#/
As i would normally expect...
This is my VueRouter configuration
const Router = new VueRouter({
routes: [
{
path: '/',
component: App,
children: [
{
path: 'dashboard',
name: 'dashboard',
component: Dashboard
}
]
}
]
});
And on the PHP side of things i'm just defining a catch all route for the /admin section of the Application
// Catch-all Route, sends GET requests to VueRouter //
Route::get('{all?}', function() {
return view('index');
})->where(['all' => '(.*)'])->name('catchall');
Like this, is there anything i'm doing wrong? It is working but it just kinda bugs me that the # just floats there.
You have to enable history mode, as stated here, I dont see that in your vue-router config.
const Router = new VueRouter({
mode: 'history',
routes: [
{
path: '/',
component: App,
children: [
{
path: 'dashboard',
name: 'dashboard',
component: Dashboard
}
]
}
]
});
You have to do it on server side, just redirect the route to one ended with '/'
As in laravel:
Route::get('{all?}', function() {
return view('index');
})->where(['all' => '^/admin\/$'])->name('catchall');
now just visit /admin/#/

How to Generate Routes for Subcomponents Based on a Base Path

How to get the next route in vue-router
I have the following route: /principal
{path: '/principal', component: Principal}
Now, I need to drive other components that have the same url base,
the new url would be as follows:
/principal/compa
Is it possible to have a single base route be able to display the other components?
Something like this (I know that vue-router does not work like this), but how do you get this behavior?
{
path: '/principal',
component: Principal,
subpath: {
path: 'compa',
component: 'CompA'
}
}
Thanks
There is a children option in VueRouter constructor config to render Vue components with nested routes.
In that particular case, it would be:
{
path: '/principal',
component: Principal,
children: [{
path: 'compa', // it would match /principal/compa
component: CompA
}]
}
From the vue-router doc:
const router = new VueRouter({
routes: [
{
path: '/user/:id',
component: User,
children: [ // <-- notice the children property
{
// UserProfile will be rendered inside User's <router-view>
// when /user/:id/profile is matched
path: 'profile',
component: UserProfile
},
{
// UserPosts will be rendered inside User's <router-view>
// when /user/:id/posts is matched
path: 'posts',
component: UserPosts
}
]
}
]
});
Have a look at nested routes for more details.