Vue3 Router duplicated component - vue.js

I'm creating an app using Vue3js and vue-router.
When the app is created, I get my first component duplicated.
My App.vue component is this:
<template>
<div class="container-fluid">
<nav class="navbar navbar-expand-md fixed-top">
<div class="menu-izq">
<router-link id="logo" class="menu-item" to="/">COVELESS</router-link>
<router-link class="menu-item" v-if="!this.userLogged" to="/login">Login</router-link>
<router-link class="menu-item" v-if="this.userLogged" to="/canvas">Canvas</router-link>
<router-link class="menu-item" v-if="this.userLogged" to="/dashboard">Dashboard</router-link>
</div>
<div class="menu-dcha">
<router-link class="menu-item" v-if="this.userLogged" v-on:click="vaciarStorage()" to="/login">Logout
</router-link>
</div>
</nav>
<router-view></router-view>
</div>
My router.js file is this
import { createRouter, createWebHistory } from
'vue-router'
import LoginMenu from './components/LoginMenu.vue'
import AllElement from './components/AllElement.vue'
import Dashboard from './components/Dashboard.vue'
import App from './App.vue'
const routes = [
{
path: '/',
name: 'Home',
component: App
},
{
path: '/login',
name: 'Login',
component: LoginMenu
},
{
path: '/canvas',
name: 'Canvas',
component: AllElement
},
{
path: '/dashboard',
name: 'Dashboard',
component: Dashboard
}
]
const history = createWebHistory();
const router = createRouter({
history,
routes,
});
export default router
And my app.js file is this
import './bootstrap';
import { createApp } from 'vue/dist/vue.esm-bundler'
import App from './App.vue'
import router from './router'
createApp(App).use(router).mount('#app');
So when the App component is mounted on #app, the navbar gets duplicated because it is mounting another App component at "/" path (I guess because it is defined at router.js like that). But if I remove the
{
path: '/',
name: 'Home',
component: App
}
route, then I'm never navigating to the index.
Here you can see both the App components.

Related

How can I change the view for one part of the page in VueJs 3

I have three main sections inside my page, and I want to switch the view for one section only:
<template>
<div id="main">
<div id="scene">
<scene/>
</div>
<div id="plan">
<Plan/>
</div>
<div id="titleControl">
<router-link to="/controls"> Controls </router-link>
<router-link to="/logs"> Logs </router-link>
</div>
<div id="controlPannel">
<div id="controls">
<Controls/>
</div>
<router-view/>
</div>
</div>
</template>
router
import { createWebHistory, createRouter } from "vue-router";
import MainInterface from '../views/MainInterface.vue'
import Logs from '../views/Logs.vue'
import Scene from '../views/Scene.vue'
import Plan from '../views/Plan.vue'
import Controls from '../views/Controls.vue'
import PageNotFound from '../views/PageNotFound.vue'
const routes = [
{
path: '/',
name: 'main',
component: MainInterface
},
{
path: '/scene',
name: 'scene',
component: Scene
},
{
path: '/plan',
name: 'plan',
component: Plan
},
{
path: '/logs',
name: 'logs',
component: Logs
},
{
path: '/controls',
name: 'controls',
component: Controls
},
{
path: '/:catchAll(.*)*',
name: "PageNotFound",
component: PageNotFound,
},
]
const router = createRouter({
history: createWebHistory(),
routes
})
export default router
I want to parse the controls as a default, and I want the user to navigate between the Logs and the Controls only, but when I click on any of the routing links it takes me to another page completely!
Can you please tell me how can I solve that? thanks in advance.
Instead of having all routes at one level, you can use Nested Routes
Change your App.vue to
<template>
<div id="main">
<div id="scene">
<ScenePage />
</div>
<div id="plan">
<PlanPage />
</div>
<div id="titleControl">
<router-link to="/controls"> Controls </router-link>
<router-link to="/logs"> Logs </router-link>
</div>
<router-view />
</div>
</template>
<script>
import PlanPage from "./Views/Plan.vue";
import ScenePage from "./Views/Scene.vue";
export default {
name: "App",
components: {
PlanPage,
ScenePage,
},
};
</script>
Add another file in view to handle nested routing such as Sub.vue with the following content
<template>
<router-view />
</template>
<script>
export default {
name: "SubPageForRouting",
};
</script>
and finally, update your router.js file as
import { createWebHistory, createRouter } from "vue-router";
import SubPageForRouting from "../Views/Sub.vue";
import LogPage from "../Views/Log.vue";
import ControlPage from "../Views/Controls.vue";
const routes = [
{
path: "/",
component: SubPageForRouting,
children: [
{
path: "",
alias: "controls",
component: ControlPage
},
{
path: "logs",
component: LogPage
}
]
}
];
const router = createRouter({
history: createWebHistory(),
routes
});
export default router;
You can find a working code sandbox Here

Problem with router-view duplicating the components

Recently changed from laravel routing to Vue Router. Whenever I'd insert the <router-view></router-view> in any part of the file below, it'll duplicate the component which the router routes to (i.e. it will duplicate the div part of the component and insert it in the sidebar.vue file) .
For demonstration of the problem: vs
SideBar.vue file is
<template>
<aside class="container_sidebar">
<nav id="sidebar">
<ul class="list-unstyled components">
<li class="active">
<router-link to="/nghome">Home</router-link>
</li>
<li>
<router-link to="/ngsongs">All Songs</router-link>
</li>
<li>
<router-link to="/ngalbums">Albums</router-link>
</li>
<li>
<router-link to="/ngartists">Artists</router-link>
</li>
</ul>
</nav>
</aside>
</template>
My Router.js file is
import NightingaleHome from "./components/NightingaleHome";
import NightingaleSongs from "./components/NightingaleSongs";
import NightingaleArtists from "./components/NightingaleArtists";
import NightingaleAlbum from "./components/NightingaleAlbum";
import MusicUpload from "./components/MusicUpload";
export const routes = [{
path: "/home",
component: NightingaleHome,
name: "home",
},
{
path: "/ngsongs",
component: NightingaleSongs,
name: "All Songs",
},
{
path: "/ngartists",
component: NightingaleArtists,
name: "All Artists",
},
{
path: "/ngalbums",
component: NightingaleAlbum,
name: "All Album",
},
{
path: "/fileupload",
component: MusicUpload,
name: "Music File Upload",
},
];
And my App.js file is
require('./bootstrap');
import { routes } from "./router";
import VueRouter from "vue-router";
import Vue from "vue";
import Vuesax from 'vuesax';
import { BootstrapVue, IconsPlugin } from 'bootstrap-vue';
// Import Bootstrap an BootstrapVue CSS files (order is important)
import 'bootstrap/dist/css/bootstrap.css'
import 'bootstrap-vue/dist/bootstrap-vue.css'
// Make BootstrapVue available throughout your project
Vue.use(BootstrapVue)
// Optionally install the BootstrapVue icon components plugin
Vue.use(IconsPlugin)
import 'vuesax/dist/vuesax.css' //Vuesax styles
Vue.use(Vuesax, {
// options here
})
window.Vue = require('vue').default;
Vue.component('music-player', require('./components/MusicPlayer.vue').default);
Vue.component('music-upload', require('./components/MusicUpload.vue').default);
Vue.component('upload-progress', require('./components/UploadProgress.vue').default);
Vue.component('nightingale-songs', require('./components/NightingaleSongs.vue').default);
Vue.component('nightingale-album', require('./components/NightingaleAlbum.vue').default);
Vue.component('nightingale-artist', require('./components/NightingaleArtists.vue').default);
Vue.component('side-bar', require('./components/SideBar.vue').default);
Vue.component('edit-songs', require('./components/EditSongs.vue').default);
Vue.component('nightingale-home', require('./components/NightingaleHome.vue').default);
Vue.use(VueRouter);
let router = new VueRouter({
mode: 'history',
routes
});
const app = new Vue({
el: '#app',
router,
});
I don't have App.vue file because currently I don't need it. Any solutions?
I don't know if there help you but for similar issue, I delete the root path in my router file ( path : "/" component: App).
I think the nativ root is already charged so you don't have to built-it.

the switching of the Vue Router is not working

I have a menu with 2 buttons. But the switching is not working. Moreover, the main page is invisible.
My sandbox https://codesandbox.io/s/serene-neumann-mpqs0?file=/src/App.vue
This is router.js
const routes = [
{
path: "/",
component: Main
},
{
path: "/history",
component: History
},
{
path: "/favorites",
component: Favorites
}
];
const router = new VueRouter({
routes
});
export default router;
This is Header
<template>
<header class="sticky top-0 z-40 w-full flex bg-yellow-500 md:h-16 shadow-md">
<div class="w-1/4 flex justify-end">
<router-link to="/favorites">
<button title="Favorites" class="p-2 hover:text-red has-tooltip">
Favorites
</button>
</router-link>
<button class="p-2 hover:text-red" title="History">
<router-link to="/history"> History </router-link>
</button>
</div>
</header>
</template>
App.vue
<template>
<Header/>
<router-view></router-view>
</template>
<script>
import Header from './components/Header.vue'
export default {
name: "App",
components: {
Header
},
};
</script>
and main.ts
import { createApp } from "vue";
import App from "./App.vue";
import "./assets/index.css";
import router from "./router";
const app = createApp(App);
app.use(router);
app.mount("#app");
You have kind of a mix between vue-router v3/v4.
Update everything to the latest versions and adapt the Router, so it works according to the latest docs should work:
https://codesandbox.io/s/keen-morning-rufbo?file=/src/router.js

Why does Vue router-link not Work on Click

I have the following nav bar component which should link to my about page view. When I mouse over a router-link element I can see Chrome telling me it should go there:
But when I click a link it does not go there.
NavBar.vue component template:
<template>
<nav>
<input class="search-bar" type="text" placeholder="Search Creators..." />
<ul class="menu-div">
<router-link to="/about">Pricing</router-link>
<router-link to="/about">Hello</router-link>
<router-link to="/about">Goodbye</router-link>
<router-link to="/about">Onetwo</router-link>
<button class="sign-up">Sign Up</button>
</ul>
</nav>
</template>
Here is my app.vue template
<template>
<div id="app">
<nav-bar />
<router-view></router-view>
</div>
</template>
<script>
import NavBar from "#/components/NavBar.vue";
export default {
components: {
"nav-bar": NavBar
}
};
</script>
And my routes in my index.js
import Home from "#/views/Home.vue";
import Vue from "vue";
import VueRouter from "vue-router";
Vue.use(VueRouter);
const routes = [
{
path: "/",
name: "Home",
component: Home
},
{
path: "/about",
name: "About",
component () { import("#/views/About.vue") }
}
];
const router = new VueRouter({
mode: "history",
base: process.env.BASE_URL,
routes
});
export default router;
Why is my about view not showing up when I click the router-link tags in my nav bar?
You are just importing the component. You must return it.
Change
component () { import("#/views/About.vue") }
to
component () { return import("#/views/About.vue") }
Or you could import the component outside of the definition and use it
import Home from "#/views/Home.vue";
import Vue from "vue";
import VueRouter from "vue-router";
import About from "#/views/About.vue"
Vue.use(VueRouter);
const routes = [
{
path: "/",
name: "Home",
component: Home
},
{
path: "/about",
name: "About",
component: About
}
];
const router = new VueRouter({
mode: "history",
base: process.env.BASE_URL,
routes
});
export default router;
....

How to proper use vue-router?

I want to exclude the h1 tag every time I go to different route in my Vue application.
Here's my app.vue:
<template>
<div id="app">
<img alt="Vue logo" src="./assets/logo.png">
<h1>LANDING PAGE</h1>
<router-view></router-view>
<!--Path for login.vue-->
<button #click="$router.push('/login')">LOGIN</button>
</div>
</template>
<script>
export default {
name: 'app',
}
</script>
And here's my login page, where I want only to display my design for login page only:
<template>
<div>
<h1>Login Page</h1>
</div>
</template>
<script>
export default {
name: "Login"
}
</script>
My route.js:
import Login from './components/LandingPage/Login';
import Register from './components/LandingPage/Register';
export default [
{
path: '/login', component: Login
},
{
path: '/register', component: Register
}
]
and lastly my main.js:
import Vue from 'vue'
import App from './App.vue'
import VueRouter from 'vue-router'
import Routes from './routes';
import VueResource from 'vue-resource'
Vue.config.productionTip = false;
Vue.use(VueRouter);
Vue.use(VueResource);
const router = new VueRouter({
routes: Routes,
/* To remove # in the URL */
mode: 'history'
});
new Vue({
render: h => h(App),
router: router
}).$mount('#app');
I didn't include the register.vue because it's just the same with login.vue.
Conditional rendering based on the landing page url:
<h1 v-if="$route.path === '/landing-page-url'">LANDING PAGE</h1>
Actually, there are three approaches to solve your problem:
Just drop your <h1></h1> into your landing page component.
You can use conditional rendering, like Psidom answered (just changed path to name):
<h1 v-if="$route.name === 'Landing'">Landing page</h1>
You can have only one <h1></h1> in your main layout, and render current page title dynamically. Route Meta Fields come in rescue.
import Login from './components/LandingPage/Login'
import Register from './components/LandingPage/Register'
export default [
{
path: '/login',
component: Login,
meta: {
title: 'Login',
},
},
{
path: '/register',
component: Register,
meta: {
title: 'Register',
},
},
]
And then in your template:
<h1>{{ $route.meta.title }}</h1>
P.S. To navigate to another route in your template use <router-link></router-link> instead of button with click event.