Issue when trying to use Nested routes in Vuejs? - javascript

main.js
import Vue from "vue";
import App from "./App.vue";
import VueRouter from "vue-router";
import HelloWorld from "./components/HelloWorld";
import User from "./components/User";
Vue.use(VueRouter);
const router = new VueRouter({
routes: [
{
path: "/",
name: "HelloWorld",
component: HelloWorld,
children: [{ path: ":id", name: "User", component: User }]
}
]
});
Vue.config.productionTip = false;
new Vue({
router,
render: (h) => h(App)
}).$mount("#app");
HelloWorld.vue
<template>
<div>
<div v-for="item in items" :key="item.id">
<b> id: {{ item.id }}</b>
<router-link :to="`/HelloWorld/${item.id}`">
{{ item.title }}
</router-link>
</div>
<!-- end v-for -->
<router-view></router-view>
</div>
</template>
<script>
import { router } from "./router";
export default {
name: "HelloWorld",
components: {},
data() {
return {
items: [],
};
},
mounted() {
router().then((r) => {
this.items = r.data;
});
},
};
</script>
codesandbox:- https://codesandbox.io/s/combined-logic-api-forked-oq808t?file=/src/main.js
in main.js routing file, if i change from path:'/' to path:'/HelloWorld' then output is not displaying. Not sure why and where it is linked with api call..
The reason why i changed from path:'/' to path:'/HelloWorld' because path:'/' in my project, it will consider as login page. So tried changing but getting blank screen.

You should change
const router = new VueRouter({
routes: [
{
path: "/HelloWorld/",
name: "HelloWorld",
component: HelloWorld,
children: [{ path: ":id", name: "User", component: User }]
}
]
});
to
const router = new VueRouter({
mode: 'history',
routes: [
{
path: "/HelloWorld/",
name: "HelloWorld",
component: HelloWorld,
children: [{ path: ":id", name: "User", component: User }]
}
]
});
(So, add mode: history, to the router.)
More on mode: history in Vue Router v3 here

Related

I cannot have similar router paths in Vue3

I'm just learning Vue3 and trying to do some routing, but I'm getting an error message that makes no sense.
Maybe it's related to some kind of nested routing, but I also tried to do children and it didn't want to work.
This works:
import { createRouter, createWebHistory } from 'vue-router';
import HomePage from '../home/HomePage.vue';
import FetchAccount from '../nonPrimaryADAccounts/FetchAccount.vue';
import CreateADAccount from '../nonPrimaryADAccounts/CreateADAccount.vue';
export default createRouter({
history: createWebHistory(),
routes: [
{
path: '/',
name: 'Home',
component: HomePage,
},
{
path: '/FetchAccount',
name: 'FetchAccount',
component: FetchAccount,
},
{
path: '/CreateADAccount',
name: 'CreateADAccount',
component: CreateADAccount,
},
],
});
And this does not:
import { createRouter, createWebHistory } from 'vue-router';
import HomePage from '../home/HomePage.vue';
import FetchAccount from '../nonPrimaryADAccounts/FetchAccount.vue';
import CreateADAccount from '../nonPrimaryADAccounts/CreateADAccount.vue';
export default createRouter({
history: createWebHistory(),
routes: [
{
path: '/',
name: 'Home',
component: HomePage,
},
{
path: '/NonPrimaryADAccount/FetchAccount',
name: 'FetchAccount',
component: FetchAccount,
},
{
path: '/NonPrimaryADAccount/CreateADAccount',
name: 'CreateADAccount',
component: CreateADAccount,
},
],
});
Error message:
4:29 error Unable to resolve path to module '../nonPrimaryADAccounts/CreateADAccount.vue' import/no-unresolved
If you need nested path the recommended approach is to use a function to generate the routes with the prefix:
const withPrefix = (prefix, routes) =>
routes.map( (route) => {
route.path = prefix + route.path;
return route;
});
export default createRouter({
history: createWebHistory(),
routes: [
{
path: '/',
name: 'Home',
component: HomePage,
},
...withPrefix('/NonPrimaryADAccount',[
{
path: '/FetchData',
name: 'FetchData',
component: FetchData,
},
{
path: '/CreateADAccount',
name: 'CreateADAccount',
component: CreateADAccount,
},
]),
]

Display layout based on boolean from Vuex

I got Vue2 app with vue-router with routings configured like that:
export default {
path: "/",
redirect: "/dashboard",
component: AdminLayout,
meta: {
requiresAuth: true
},
children: [
{
path: "/dashboard",
name: "Dashboard",
component: Dashboard
},
{
path: "/add/user",
name: "InviteUser",
component: InviteUser
},
{
path: "/groups",
name: "Groups",
component: Groups
},
...
In app, we got two different types of users - admin and normal user. Some of those routings should be accessible for both, but the problem is that user should see different layout base on its type (permission) - AdminLayout for admins and UserLayout for normal users.
Is there any way to show app which template should user see based on boolean from vuex with keeping route path?
on /dashboard admin will see dashboard with AdminLayout
on /dashboard normal user will see dashboard with UserLayout
My main routing cofig:
import Vue from "vue";
import VueRouter from "vue-router";
import SessionRoutes from "./session.js";
import AdminRoutes from "./admin.js";
import defaultRoutes from "./default";
Vue.use(VueRouter);
const routes = [AdminRoutes, SessionRoutes, defaultRoutes];
const router = new VueRouter({
mode: "history",
routes
});
export default router;
you can set a condition in the layout part on the current page for example for when you use nuxt:
<script>
export default {
layout: (ctx) => (ctx.isAdmin ? 'adminLayout' : 'userLayout'),
}
</script>
but I opine you don't use Nuxt.js and I think below solution is suitable for your question:
Using the meta-object in our route
set dynamic component on app.vue page
code for about.vue page
import Home from '../views/Home.vue'
import About from '../views/About.vue'
import LayoutA from '../layouts/LayoutA.vue'
import LayoutB from '../layouts/LayoutB.vue'
Vue.use(VueRouter)
const routes = [
{
path: '/',
name: 'Home',
component: Home,
meta: { layout: LayoutA }
},
{
path: '/about',
name: 'About',
component: About,
meta: { layout: LayoutB }
}
]
const router = new VueRouter({
mode: 'history',
base: process.env.BASE_URL,
routes
})
export default router;
<!--app.vue page -->
<template>
<div id="app">
<component :is="this.$route.meta.layout || 'div'">
<router-view />
</component>
</div>
</template>
<script>
export default {
name: "App",
};
</script>
<!--about page-->
<template>
<div class="about">
<h1>This is an about page</h1>
</div>
</template>
<script>
export default {
name: "About"
};
</script>
To get a different layout working for the dashboard and all child routes your layouts have to use the router view component. I use a wrapper component to handle this in one of my projects following this approach.
Excerpt from my router config:
…
{
component: MainFrame,
name: 'main',
path: '/',
redirect: 'dashboard',
children: [
{
alias: 'dashboard',
component: Dashboard,
name: 'dashboard',
path: '', // Default child route → be equivalent to /dashboard
},
{
path: "add/user",
name: "InviteUser",
component: InviteUser
},
{
path: "groups",
name: "Groups",
component: Groups
},
],
},
…
In your MainFrame component you can wrap your layout in a dynamic component. So you can switch your layout easely based on a Vuex getter:
MainFrame.vue
<template>
<component :is="layout">
<!-- you can use slots too if you like -->
</component>
</template>
<script>
import AdminLayout from './AdminLayout'
import UserLayout from './UserLayout'
export default {
computed: {
layout() {
return this.$store.getters['isAdminUser'] ? AdminLayout : UserLayout
}
}
}
</script>
And your layouts have to use <router-view />. It works as a wrapper for all nested routes and therefore you have only one place to handle the layout for the dashboard and child pages:
AdminLayout.vue
<template>
<div class="auth-view">
<header>…</header>
<aside>…</aside>
<main>
<transition name="fade" mode="out-in">
<router-view />
</transition>
</main>
<footer>…</footer>
</div>
</template>
UserLayout.vue
<template>
<div class="guest-view">
<router-view />
</div>
</template>
EDIT:
This approach can be used for deeper nesting too. Assuming your user route should have another child routes you can solve this on the router config using a <router-view /> within a render function:
…
// Let's split down user related routes
{
component: { render: (h) => h('router-view') },
name: 'usersView',
path: 'users',
redirect: 'ListUsers',
children: [
// Show users
{
path: '', // route: /users/
name: 'ListUsers',
component: ListUsers
},
// Show a single user
{
path: ':id', // route: /users/{userId}
name: 'ViewUser',
component: ViewUser
},
// Invite new users
{
path: 'add', // route: /users/add
name: 'InviteUser',
component: InviteUser
},
]
}
…

How do I use the render function correctly in Vue?

I'm just starting to use the render function and came across
with one problem.
When rendering, the Home component does not display app routes
registered in
App.vue
<template>
<div>
<h1>Vue Router Demo App</h1>
<p>
<router-link :to="{ name: 'home' }">Home</router-link> |
<router-link :to="{ name: 'hello' }">Hello World</router-link>
</p>
<div class="container">
<router-view></router-view>
</div>
</div>
</template>
<script>
export default {}
</script>
there are no errors in the browser console.
app.js
import Vue from 'vue'
import VueRouter from 'vue-router'
Vue.use(VueRouter)
import App from './App'
import Hello from './views/Hello'
import Home from './views/Home'
const router = new VueRouter({
mode: 'history',
routes: [
{
path: '/',
name: 'home',
component: Home
},
{
path: '/hello',
name: 'hello',
component: Hello,
},
],
});
const app = new Vue({
el: '#app',
components: { App },
router,
});
Home.vue
with this configuration, the routes are not displayed
<script>
export default {}
import Vue from 'vue'
new Vue({
el: '#app',
render(createElement) {
return createElement("div", { class: "container" }, [
createElement("p", { class: "my-class" }, "Some cool text")
])
}
});
</script>
I just want to use the render function inside my components. Or understand how to use the render function correctly for two or more vue components.
How to configure the app correctly with switching between components
Home and Hello?
The components in Vue should be inherited from vue components and injected in the base component.
Vue.component('home', {
render(createElement) {
return createElement("div", { class: "container" }, [
createElement("p", { class: "my-class" }, "Some cool text")
])
}
})
new Vue({
el: '#app',
components: ['home'],
template: '<home/>'
})
<div id="app"></div>
<script src="https://cdn.jsdelivr.net/npm/vue#2.6.11"></script>

use props with laravel and vuejs2

hi im using laravel with vuejs2
and this is my App.vue code
<template>
<div>
<Navbar></Navbar>
<Applications></Applications>
{{page_title}}
<router-view></router-view>
</div>
</template>
<script>
import Navbar from '../components/Navbar'
import Applications from '../components/Applications'
export default {
name: 'App',
components: {
Navbar, Applications
},
data: function () {
return {
page_title: 'Main',
}
}
}
</script>
every thing working so good so far ..
so in my routes.js i did this code
{ path: '/settings', component: Settings},
and in my Settings.Vue i did this code
<template>
<div>
setting components
{{page_title}}
</div>
</template>
<script>
export default {
props: ['page_title'],
name: 'Settings',
}
</script>
but i cant access page_title from the props what i want i access page_title from App.vue in Settings.vue
thanks a lot
You must pass data to <router-view>:
const Page = {
template: "<div>Title: {{page_title}}</div>",
props: ["page_title"]
};
const router = new VueRouter({
routes: [{
path: "/",
component: Page
}]
});
const app = new Vue({
router,
template: "<router-view :page_title='page_title'></router-view>",
data() {
return {
page_title: "It's magic!"
};
}
}).$mount("#app");
<script src="https://unpkg.com/vue#2.6.11/dist/vue.min.js"></script>
<script src="https://unpkg.com/vue-router#3.1.6/dist/vue-router.min.js"></script>
<div id="app"></div>

VueJS cannot get path after reload or direct link

I have trouble with VueJS(or with my brains). Ok. I have vuejs-webpack project and this router:
import Vue from 'vue'
import Router from 'vue-router'
import Main from '#/components/Main'
import CreateTravel from '#/components/CreateTravel'
import TravelDetail from '#/components/TravelDetail'
import Friends from '#/components/Friends'
import UserTravels from '#/components/UserTravels'
import User from '#/components/User'
import Settings from '#/components/Settings'
import UserActivate from '#/components/UserActivate'
Vue.use(Router);
export default new Router({
mode: 'history',
routes: [
{
path: '/user/activate/:secret',
name: 'UserActivate',
component: UserActivate
},
{
path: '/',
name: 'Main',
component: Main
},
{
path: "/create",
name: "Create",
component: CreateTravel
},
{
path: "/travel/:id",
name: "Travel",
component: TravelDetail
},
{
path: "/friends",
name: "Friends",
component: Friends
},
{
path: '/user/:id',
name: 'User',
component: User,
children: [
{
path: 'travels',
name: 'UserTravels',
component: UserTravels
}
]
},
{
path: '/settings',
name: 'Settings',
component: Settings
}
]
})
And main.js:
// The Vue build version to load with the `import` command
// (runtime-only or standalone) has been set in webpack.base.conf with an alias.
import Vue from 'vue'
import App from './App'
import router from './router'
import VeeValidate from 'vee-validate';
import VueResource from 'vue-resource';
Vue.use(VeeValidate);
Vue.use(VueResource);
Vue.config.productionTip = false;
/* eslint-disable no-new */
new Vue({
el: '#app',
router,
template: '<App/>',
components: {App}
});
And when I redirect to some link I have 404. Example, after redirect on link http://localhost:8080/user/activate/73e7bcfa-a9d2-4d32-8ddc-697a82bf6363 from email I look "Cannot GET /user/activate/73e7bcfa-a9d2-4d32-8ddc-697a82bf6363". In console browser next:
361d711d-05ef-4c5e-944a-7e511ba104ab:1 GET http://localhost:8080/user/activate/361d711d-05ef-4c5e-944a-7e511ba104ab 404 (Not Found). Thanks for your help

Categories