I am using vue3 and I am a newcomer to this. With the use of vue-router I created the routes. But I want to get the this.$route.name inside the app.vue. Therefore tried to get the value inside the created method. But at the beginning that value is undefined.
You get null because $route.name is not intialized yet in the created method.
You can instead use a computed variable, so this way $route.name will be initialized.
<template>
<div class="main-view">
<Navigation v-if="enableNavigation" />
<router-view />
<Footer />
</template>
export default {
name: 'App',
computed: {
enableNavigation() {
const disabledNavRoutes = ['login', 'register', 'resetPassword'];
return disabledNavRoutes.indexOf(this.$route.name) === -1;
}
}
}
In your case you want to display the Navigation component but only in some routes (the route when the user is not authenticated i assume). Here some alternatives:
Method 1: nested routes
router.js
const router = new Router({
mode: 'history',
base: process.env.BASE_URL,
routes: [
{
path: '/login',
name: 'login',
component: LoginView,
},
{
path: '/home',
name: 'home-shell',
component: HomeShell,
children: [
{
path: 'home',
name: 'home',
component: HomeView
},
]
},
],
});
Remove the Navigation from App.js to remove it from login / register component
App.js
<template>
<div class="main-view">
<router-view></router-view>
</div>
</template>
Put the navigation and footer component in the HomeShell
HomeShell.js
<template>
<Navigation />
<--! Nested router. In our case HomeView !-->
<router-view />
<Footer />
</template>
And the HomeView component will be injected in the router-view of the HomeShell
Method 2: v-if
An other way would be to have a variable isAuthenticated in the store and conditionally show the Navigation component in the App component
App.js
<template>
<Navigation v-if="isAuthenticated" />
<router-view />
<Footer v-if="isAuthenticated" />
</template>
...
computed: {
isAuthenticated() {
return this.$store.getters.isAuthenticated
}
The limitation here is that if later you want to disable the navigation for routes where the user can authenticated (i.e. error 404 route). This won't work anymore.
I recommend you to check out this SO question for more info
Related
I am trying to access root path of app '/' or named component 'Home' from nested view with nested children.
const routes = [
{
path: "/",
name: "Home",
component: Home,
},
...
{
path: "/account",
name: "Account",
component: AccountHome,
children: [
{
name: "AccountAvatars",
path: "avatars",
component: AccountAvatar,
},
...
],
},
];
const router = new VueRouter({
mode: "history",
base: '/',
routes,
scrollBehavior(to, from, savedPosition) {
return { x: 0, y: 0 };
},
});
Vue.use(VueRouter);
export default router;
....
When i want to use router-link or manually this.$router.push({name: 'Home'}) or this.$router.push({name: '/'}) from /account/avatars for example click on router-link or $router.push not working at all.
App.vue
<template>
<div id="app">
<global-header />
<router-view />
<global-footer />
</div>
</template>
Home.vue
<template>
<div class="home">
<offer />
<home-menu />
<game-catalog/>
<benefits />
<news />
</div>
</template>
AccountHome.vue
<template>
<div class="container">
<div
class="account"
>
<account-left-sidebar />
<router-view />
<account-right-sidebar />
</div>
</div>
</template>
Router instance
const router = new VueRouter({
mode: 'history',
base: process.env.BASE_URL,
routes,
scrollBehavior(to, from, savedPosition) {
return { x: 0, y: 0 }
}
})
check what's inside BASE_URL. the .base argument of VueRouter constructor is not your app's baseUrl. it's just default path. official Vue Router doc. it should be base:'/'.
check this working code:
https://codesandbox.io/s/holy-bush-jsi79?file=/src/routes.js
Edit: I've added programmatically routing example as well.(to match your edit)
Edit 2: I've also added another running example that's exactly same to your edit. it still works. I think one of your components are fiddling with routers.
https://codepen.io/rabelais88/pen/NWjJEMe
In Vue 3 i have a problem calling a computed property. I need to show a component if a user sign in correctly.
In my App.vue i have:
<template>
<div class="wrapper">
<Sidebar v-if="authorized"/>
</div>
<main class="content">
<router-view />
</main>
</template>
<script>
import Sidebar from "#/components/Sidebar.vue";
export default {
name: "App",
components: {
Sidebar
},
computed: {
authorized: () => {
//some code
}
},
};
For example, when i go to /login path, the authorized computed property is called.
Then, in my Login.vue component, i have a method with:
this.$router.push({ name: 'Dashboard' })
The problem is that after the router.push, the computed property in App vue parent isn't called.
Why?
Before using routing, I had the following Dashboard component:
<template>
<div>
<RegistrationForm v-on:add-employee="addEmployee" />
<EmployeeTable
v-bind:employees="employees"
v-on:delete-employee="deleteEmployee"
/>
</div>
</template>
<script>
...
export default {
components: {
EmployeeTable,
RegistrationForm
},
data() {
return {
employees: []
};
},
methods:{
deleteEmployee() {...}
addEmployee() {...}
}
}
</script>
I want to have to separate routes one for registering a new employee and one for listing all employees, so what I did first is updating the above template:
<template>
<div>
<router-view/>
</div>
</template>
Then I defined a router object:
export default new Router({
mode: 'history',
routes: [
{
path: "/dashboard",
name: "dashboard",
component: Dashboard,
children: [
{
path: 'add-employee',
component: RegistrationForm,
},
{
path: 'list-employees',
component: EmployeeTable,
}
]
}
]
});
My question is how to pass the employees state variable and deleteEmployee, addEmployee methods from the Dashboard component to its children components?
Update:
I do not know why I did not receive any response on this question, although this is a common and trivial task to do in other frameworks, for instance in React:
...
export default function BasicExample() {
const [x, setX] = useState("World");
return (
<Router>
<div>
<ul>
<li>
<Link to="/">Home</Link>
</li>
</ul>
<Switch>
<Route exact path="/">
<Home x={x}/>
</Route>
</Switch>
</div>
</Router>
);
}
function Home({x}) {
return (
<div>
<h2>Hello {x}</h2>
</div>
);
}
After using Vue-router for a short period of time, I concluded that this is not a limitation, but more like a design decision:
React-router: is more like a condional renderer, e.i from within the parent component and based on the current path, render the apporopriate child.
Vue-router: is more like a wiring solution.
Also I have to say: a similar behavior to React-router can be achieved using Vue-router. This by combining the router's currentRoute property with the v-if directive, which truly insert/remove a component from the DOM (not hiding it using css as v-show do).
Finally: seprating routes configuration is advantegeous, as it yield more modular project and better SPA. Of-course this separation can be done in both Vue-router and React-router (look here for React-router).
I am creating a SPA which have a login screen and other views. But the problem I am facing is, the login screen view also includes in the Navigation bar but It should not be there. Then I used Router navigation which displays a navigation bar alone without any views I think it also guards the Login view also.
App.vue
<template>
<section id="app" class="hero">
<section class="main-content columns is-fullheight has-background-white-bis">
<Navigation />
<div class="hero-body">
<router-view />
</div>
</section>
</section>
</template>
<style>
.menu {
margin: 25px;
}
</style>
<script>
import Navigation from "#/components/Navigation.vue";
export default {
name: "app",
components: {
Navigation
}
};
</script>
router/index.js
import Vue from 'vue'
import VueRouter from 'vue-router'
Vue.use(VueRouter)
const routes = [{
path: '/LoginUser',
name: 'login',
component: LoginUser,
},
{
path: '/',
name: 'dashboard',
component: Dashboard,
},
}]
const router = new VueRouter({
mode: 'history',
base: process.env.BASE_URL,
routes
})
var isAuthenticated = false;
router.beforeEach((to, from, next) => {
if (!isAuthenticated) next('/LoginUser')
else next()
})
export default router
To remove the navigation when specifically on the Login route, you can add a v-if to your <Navigation /> component, which checks if the route is not on the login page:
<Navigation v-if="this.$router.currentRoute.name !== 'login'" />
We can conditionally render components by checking the name of the current route using v-if directive. I used this in a recent project.
My route index.js file
import Vue from 'vue'
import VueRouter from 'vue-router'
import Home from '../views/Home.vue'
import Login from '../views/Login.vue'
Vue.use(VueRouter)
const routes = [
{
path: '/',
name: 'home',
component: Home
},
{
path: '/login',
name: 'login',
component: Login
},
{
path: '/register',
name: 'register',
component: Register
}
]
const router = new VueRouter({
mode: 'history',
base: process.env.BASE_URL,
routes
})
export default router
My App.vue file
<template>
<div id="app">
/* Note that this takes an array of route names, so you can simple pass in
the name of the route you dont want this component to be displayed on */
<navbar v-if="!['login', 'register', 'help'].includes($route.name)" />
<main>
<router-view />
</main>
<appfooter v-if="!['login', 'register'].includes($route.name)"/>
</div>
</template>
The router does not load the components inside my view...
this is the structure:
the view: (test works, finMain does not)
<template>
<div>
<finMain></finMain>
<p>test</p>
</div>
</template>
<script>
export default {
name: 'FinView',
component: {
finMain: () => import("../components/finance/finMain"),
}
};
</script>
the router:
export default new Router({
routes: [
{
path: "/financial",
name: "financial",
component: () => import("#/views/finView")
}
],
});
if i put component: () => import("../components/finance/finMain") in my router it works... but not if I wrap the component inside the View..
This is the error i get:
Unknown custom element: <finMain> - did you register the component correctly?
For recursive components, make sure to provide the "name" option.
found in
---> <FinView>
<VApp>
<App> at src/App.vue
<Root>
I think that it's just misspelling, change component: { to components: {.