NavBar in Vue using v-for and router - vue.js

I have this default vue navbar which I want to make it more dynamic by using v-for.
Before changes, this is the code:
<template>
<div>
<router-link to="/">Home</router-link> |
<router-link to="/about">About</router-link>
</div>
</template>
After changes, this is the code:
<template>
<div>
<div v-for="navbar in navbars" :key="navbar.id">
<router-link :to="navbar.router">{{ navbar.names }}</router-link>
</div>
</div>
</template>
<script>
export default {
name: "Header",
navbars: [
{ names: "Home", router: "/" },
{ names: "About", router: "/About" }
]
};
</script>
But after converted it, the navbar doesn't show up. Anything I miss out?

You need to define navbars as a data of the component using data
<template>
<div>
<div v-for="navbar in navbars" :key="navbar.id">
<router-link :to="navbar.router">{{ navbar.names }}</router-link>
</div>
</div>
</template>
<script>
export default {
name: "Header",
data: function () {
return {
navbars: [
{ names: "Home", router: "/" },
{ names: "About", router: "/About" }
]
}
}
};
</script>

Related

Clicking routes in Header refreshes page in vuejs with prerender-spa plugin after serving dist

The connection in between components gets disrupted. Which shouldnt happen since I am using bootstrap-vue inbuilt router link (using to=" " instead of href="").
The app works perfectly fine when running without dist.
App.vue
<template>
<div class="container">
<app-header></app-header>
<div class="row">
<div class="col-xs-12">
<transition name="slide" mode="out-in">
<router-view></router-view>
</transition>
</div>
</div>
</div>
</template>
<script>
import Header from "./components/Header.vue";
export default {
components: {
appHeader: Header
},
created() {
this.$store.dispatch("initStocks");
}
};
</script>
Header.vue
<template>
<div>
<b-navbar toggleable="lg" type="dark" variant="info">
<b-navbar-brand to="/">Stock Broker</b-navbar-brand>
<b-navbar-toggle target="nav-collapse"></b-navbar-toggle>
<b-collapse id="nav-collapse" is-nav>
<b-navbar-nav>
<b-nav-item to="/portfolio">Portfolio</b-nav-item>
<b-nav-item to="/stocks">Stocks</b-nav-item>
<b-nav-item #click="endDay">End Day</b-nav-item>
<b-navbar-nav right>
<b-nav-item right>Funds: {{ funds }}</b-nav-item>
</b-navbar-nav>
</b-navbar-nav>
</b-collapse>
</b-navbar>
</div>
</template>
<script>
import { mapActions } from "vuex";
export default {
data() {
return {
isDropdownOpen: false
};
},
computed: {
funds() {
return this.$store.getters.funds;
}
},
methods: {
...mapActions({
randomizeStocks: "randomizeStocks",
fetchData: "loadData"
}),
endDay() {
this.randomizeStocks();
},
saveData() {
const data = {
funds: this.$store.getters.funds,
stockPortfolio: this.$store.getters.stockPortfolio,
stocks: this.$store.getters.stocks
};
this.$http.put("data.json", data);
},
loadData() {
this.fetchData();
}
}
};
</script>
vue.config.js
module.exports = {
pluginOptions: {
prerenderSpa: {
registry: undefined,
renderRoutes: ["/", "/portfolio", "/stocks"],
useRenderEvent: true,
headless: true,
onlyProduction: true
}
}
};
router/index.js
import Vue from 'vue'
import VueRouter from 'vue-router'
import Home from '../views/Home.vue'
Vue.use(VueRouter)
const routes = [
{
path: '/',
name: 'Home',
component: Home
},
{
path: '/stocks',
name: 'Stocks',
component: () => import(/ '../views/Stocks.vue')
},
{
path: '/portfolio',
name: 'Portfolio',
component: () => import('../views/Portfolio.vue')
}
]
const router = new VueRouter({
mode: 'history',
base: process.env.BASE_URL,
routes
})
export default router
I figured it a minute after making this post haha.
The issue was that in App.vue I had my main div with a class of "container" instead of id of "app".
Corrected below:
<template>
<div id="app"> //correction here
<app-header></app-header>
<div class="row">
<div class="col-xs-12">
<transition name="slide" mode="out-in">
<router-view></router-view>
</transition>
</div>
</div>
</div>
</template>

Vue js single page and siderbar with header issue

I am creating vue js application. I have login screen and after login, left sidebar for options like dashboard, users, settings.. and header for signout and notification feature.
My architecture is : I have 1 common file(main layout) in which header and sidebar are added. Now on 1st time open after login, dashboard is called in which main layout is imported.
I want to call this sidebar and header only once.. but the problem is whenever I click on sidebar, it opens respective screen in right side in container but sidebar and header also calls as I have imported main file to each component.
Due to this my firebase listener attached in header calls multiple times. I want to load header only once after login so that I can use firebase listener correctly.
My architecture is below:
main layout file:
<template>
<div id="appOne">
<div class="col-sm-3 col-lg-2 hamburger" style="padding-left: 0;">
<Sidebar></Sidebar>
</div>
<div class="col-sm-9 col-lg-10 fixed">
<Header class="header"></Header>
<div class="dynTemplate" id="dynTemplate"></div>
</div>
</div>
</template>
Dashboard vue file:
<template>
<div>
<Mainlayout></Mainlayout>
<div>
<span><h1 align="center"> Welcome </h1> </span>
</div>
</div>
</template>
<script>
import Mainlayout from './shared/Mainlayout.vue';
export default {
el: '#appOne',
components: {
Mainlayout,
}
}
</script>
What is correct way to use header, sidebar and other component which will call on click on sidebar options.
Try this snippet. The mounted() and created() in header will be called only once.
Or if you need more dynamic view components, try named view
const Login = {
template: `
<div>
<div>Login Page</div>
<router-link to="/foo">click here</router-link>
</div>
`
}
const Sider = {
template: '<div>This is sider</div>'
}
const Header = {
template: '<div>This is header</div>',
mounted() {
console.log("header mounted")
},
created() {
console.log("header created")
},
}
const MainLayout = {
template: `
<div>
<mysider></mysider>
<div>
<myheader></myheader>
<router-view></router-view>
</div>
</div>
`,
components: {
mysider: Sider,
myheader: Header
}
}
const Foo = {
template: `
<div>
<div>This is Foo</div>
<router-link to="/bar">go to Bar</router-link>
</div>`
}
const Bar = {
template: `
<div>
<div>This is Bar</div>
<router-link to="/foo">go to Foo</router-link>
</div>`
}
const router = new VueRouter({
routes: [{
path: '/',
component: Login
},
{
path: '/main',
component: MainLayout,
children: [
{
path: '/foo',
component: Foo
},
{
path: '/bar',
component: Bar
},
]
}
]
})
const app = new Vue({
router
}).$mount('#app')
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>
<div id="app">
<router-view></router-view>
</div>

Passing route params in vue router v-link

I have this anchor in Parent.vue:
<a v-link="{ path: '/somepath/somesubpath', query: { messageId: 999}}"> Here </a>
or also this
<a v-link="{ path: '/somepath/somesubpath', params: { messageId: 999}}"> Here </a>
My Child.vue is like this:
<template>
{{messageId}}
// other html..
</template>
<script>
export default {
props: ['messageId']
}
</script>
In Child.vue I can not see the value of {{messageId}} being rendered. This means that the value is not getting passed.
I am using vue router 0.7.5 and the docs here do not specify how to specify params in v-link (without named routes).
So whats the proper way to pass in params using vue router with v-link?
Route params are available in the this.$route.params property. They do not need to be passed as a component property.
In your case you can access the messageId param in your template like so:
{{ $route.params.messageId }}
However, you also need to make sure that the template for your Child.vue component has a single root element and not just text. Otherwise, the component will not render.
So, you'd at least need something like this:
<template>
<div>
{{ $route.params.messageId }}
</div>
</template>
Here's a simple example:
Vue.component('child', {
template: `
<div>
message id: {{ $route.params.messageID }}
</div>
`
});
const Home = {
template: '<div>Home</div>'
};
const Message = {
template: `
<div>
<span>Message View</span>
<child></child>
</div>
`
};
const router = new VueRouter({
routes: [
{ path: '/', component: Home, name: 'home' },
{ path: '/message', component: Message, name: 'message' }
]
})
new Vue({
router,
el: '#app'
})
<script src="https://npmcdn.com/vue/dist/vue.js"></script>
<script src="https://npmcdn.com/vue-router/dist/vue-router.js"></script>
<div id="app">
<router-link :to="{ name: 'home' }">home</router-link>
<router-link :to="{ name: 'message', params: { messageID: 123 } }">message view</router-link>
<router-view></router-view>
</div>

Add event listener to <router-link> component using "v-on:" directive - VueJS

I'm attempting to add a custom handler InlineButtonClickHandler to a <router-link> component's click event, so that I can emit a custom appSidebarInlineButtonClick event.
But, my code isn't working. What am I doing wrong?
<template>
<router-link :to="to" #click="InlineButtonClickHandler">
{{ name }}
</router-link>
</template>
<script type="text/babel">
export default {
props: {
to: { type: Object, required: true },
name: { type: String, required: true }
},
methods: {
InlineButtonClickHandler(event) {
this.$emit('appSidebarInlineButtonClick');
}
}
}
</script>
You need to add the .native modifier:
<router-link
:to="to"
#click.native="InlineButtonClickHandler"
>
{{name}}
</router-link>
This will listen to the native click event of the root element of the router-link component.
<router-link:to="to">
<span #click="InlineButtonClickHandler">{{name}}</span>
</router-link>
Maybe you can try this.
With vue 3 and vue router 4 the #event and tag prop are removed according to this and instead of that you could use v-slot:
const Home = {
template: '<div>Home</div>'
}
const About = {
template: '<div>About</div>'
}
let routes = [{
path: '/',
component: Home
}, {
path: '/about',
component: About
}, ]
const router = VueRouter.createRouter({
history: VueRouter.createWebHashHistory(),
routes,
})
const app = Vue.createApp({
methods: {
test() {
console.log("test")
}
}
})
app.use(router)
app.mount('#app')
<script src="https://unpkg.com/vue#3"></script>
<script src="https://unpkg.com/vue-router#4"></script>
<div id="app">
<h1>Hello App!</h1>
<p>
<router-link to="/" v-slot="{navigate}">
<span #click="test" role="link">Go to Home</span>
</router-link>
<br/>
<router-link to="/about">Go to About</router-link>
</p>
<router-view></router-view>
</div>

Nested-routes is not working in vue-router 2

Here is the codes.
html
<div id="app">
<nav>
<ul>
<router-link to="/user">User List</router-link>
</ul>
</nav>
<router-view></router-view>
</div>
Routes definition
const routes = [
{
path: '/user', component: User,
children: [
{path: '', name:'user-list', component: UserList},
{path: ':id', name: 'user-detail', component: UserDetail}
]
}];
let router = new VueRouter({routes});
export default router;
User
<template>
<div>
<h2>User Center</h2>
<router-view></router-view>
</div>
</template>
<script>
export default {
data () {
return {
}
},
methods:{
}
}
</script>
User list
<template>
<div>
<!--<ul>-->
<!--<li v-for="u of userList">-->
<!--<router-link :to="{ name:'user-detail', params: { id: '4343' }}">{{u.name}}</router-link>-->
<!--</li>-->
<!--</ul>-->
<router-link :to="{ name:'user-detail', params: { id: '4343' }}">3434</router-link>
<!--<a #click="query">++++</a>-->
</div>
</template>
<script>
import {mapActions} from 'vuex'
import {USER_QUERY} from '../store/user.type'
export default {
data () {
return {
userList: []
}
},
methods: {
query: function () {
this.$store.dispatch(USER_QUERY, [{name:'111'},{name:'1222'}])
}
}
}
</script>
User detail
<template>
<div>
<h2>{{ $route.params.id }}</h2>
</div>
</template>
<script>
export default {
data () {
return {
}
},
methods: {
test: ()=> {
}
}
}
</script>
I want click the link in the UserList can navitage to the UserDetail,but it is not working,someone help to check it?
Like this
App
--User
----UserList
http://localhost:8080/#/user
change to
App
--User
----UserDetail
http://localhost:8080/#/user/5454
you have to give path in to in outer-link as /user/:id in your HTML code, like following:
<router-link :to="'/users/' + id">3434</router-link>
See working fiddle here.
I made a stupid mistake like this.
import User from './component/user-list.vue';