Vue-Router: Nested routes not displaying - vue.js

When using nested routes, the component does not display. If I do not use nested route, the component displays as expected. Any ideas on what I may be doing wrong with nested route?
import ManufacturersReport from "#/components/ManufacturersReport";
import Reports from "#/components/Reports";
Vue.use(Router);
export default new Router({
routes: [
{
path: "/reports",
name: "Reports",
component: Reports,
children: [
{ path: "manufacturer_report", component: ManufacturersReport }
]
}
],
mode: "history"
});
<template>
<header class="header">
<h1>Reports</h1>
<div id="nav">
<router-link to="/reports/manufacturer_report">MF Report</router-link>|
</div>
</header>
</template>

I got it working by adding <router-view></router-view> to my template code.
<template>
<header class="header">
<h1>Reports</h1>
<div id="nav">
<router-link to="/reports/manufacturer_report">MF Report</router-link>|
<router-link to="/ping">Reports</router-link>
<router-view></router-view>
</div>
</header>
</template>

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

How to use children path in Vue.Js

This code
index.js
{
path: '/test',
name: 'test',
component: Test,
children: [{
path: 'p1',
name: 'p1',
component: P1
}]
}
in Component Test
test.vue
<template>
<div>
<h1>Test</h1>
<button v-on:click="navigateTo('/test/p1')">p1</button>
</div>
</template>
<script>
export default {
methods: {
navigateTo(route) {
this.$router.push(route)
}
}
}
</script>
in Component P1
<template>
<div>
<h1>P1</h1>
</div>
</template>
When i click button p1 i has path in browser but not load component p1. why??
I'm new in vue.js
I think you missed the <router-view></router-view> in your parent template (in test.vue). Router view is where the child component gets rendered. i.e.
<template>
<div>
<h1>Test</h1>
<button v-on:click="navigateTo('/test/p1')">p1</button>
<router-view></router-view>
</div>
</template>

can't rendering router children

i have a router called '/shop' and the children is /list/:id for the component named is listproduct
but when i render on the link i go like mylocalhost/shop/list/0812018381 it does render ?
here is my routes
{
path: '/shop',
name: 'shop',
component: () => import('./components/shop.vue'),
children: [
{
path: '/list/:id',
name: 'list',
component: () => import('./views/detail.vue'),
},
],
}
the component on my shop is something like this
<b-col>
<div class="thiscaption my-4 p-2">
<b-link :to="`/shop/${product._id}`">
<h4>{{ product.productName }}</h4>
</b-link>
<span>
{{
product.desc
.split(' ')
.slice(0, 8)
.join(' ')
}}...</span
>
<br />
<span>
<b>${{ product.price }} </b>
</span>
<br />
<b-button type="submit" variant="primary" class="p-2
my-4">add to cart</b-button>
</div>
</b-col>
i have tried to move that component list to not in children of shop, it was work, but when i use it on children shop, it doesnt render and work
If you use the children property of a route, any child routes are mounted in the parent component. In your case it means it is mounted in shop.vue. To be able to mount the component in the parent component, the parent component must contain a <router-view /> element.
Take for example the following components:
<!-- App.vue -->
<template>
<div id="app">
<span>Start App.vue</span>
<router-view/>
<span>End App.vue</span>
</div>
</template>
<!-- ParentComponent.vue -->
<template>
<div class="parent-component">
<span>Start Parent component</span>
<router-view/>
<span>End Parent component</span>
</div>
</template>
<!-- Child1.vue -->
<template>
<div class="comp-child1">Child1.vue</div>
</template>
Furthermore, we have the following router:
// router.js
import Vue from "vue";
import VueRouter from "vue-router";
import ParentComponent from "./components/ParentComponent";
import Child1 from "./components/Child1";
import Child2 from "./components/Child2";
Vue.use(VueRouter);
const routes = [
{
path: "/",
component: ParentComponent,
children: [
{
path: "",
redirect: "/child1"
},
{
path: "child1",
component: Child1
},
{
path: "child2",
component: Child2
}
]
}
];
export default new VueRouter({
routes
});
In this case, App.vue is the root component, because this is defined in main.js. The router says that child1 is a child route from /, which renders component ParentComponent. Therefore we will see the start and end of app.vue. Nested in there we will see the start and end of ParentComponent. Then nested inside of that, we see Child1. Without router-view in either of these components, there would be no place for their children to be mounted.

Getting a value from a nested template in vue

So basically I have something like this in my home page
<template>
<div id="body">
<sideBar :menu="menu" :tableName='tableName' titleOfPage='titleOfPage'></sideBar>
<div id="menu">
HOME PAGE
</div>
</div>
</template>
In the sidebar template you can select your page. It will forward you this template
<template>
<div id="body">
<sideBar :menu="menu" :tableName='tableName' :titleOfPage='titleOfPage'></sideBar>
<div id="main">
<h1>{{ titleOfPage }}</h1>
....
I need the sidebar template to set the titleOfPage as it corresponds to the page clicked. I tried different ways but didn't manage. I appreciate the help by explaining me how to solve this issue.
The Vue docs recommend not using $router directly but instead configuring props to pass to the routed components:
const routes = [
{ path: '/', redirect: '/page-a', component: { template: `<router-view></router-view>` }, name: 'Home' },
{ path: '/page-a', component: Page, props: { titleOfPage: 'Page A' }},
{ path: '/page-b', component: Page, props: { titleOfPage: 'Page B' }},
];
If your props are dynamic and depend on the current route, you can pass a function to the props property of each route configuration:
{ path: '...', component: ..., props: (route) => ({ query: route.query.q }) }
To solve your issue, you can simply create a page component which receives the props from the router and render your sidebar component in its template:
<!-- template for page component -->
<template>
<div id="body">
<sideBar :menu="menu" :tableName='tableName' :titleOfPage='titleOfPage'></sideBar>
<div id="main">
<h1>{{ titleOfPage }}</h1>
<!-- ... -->
</div>
</div>
</template>
DEMO: stackblitz

VueJS - passing data from a v-for to a component, and then to another component

I have a <header-row> component which I put at the top of all pages to show a title and a subtitle. This is what I'm wanting to do:
Show a list of objects from an array, with each item "clickable" to show that item's detail on a separate page (this part is easy)
Pass a field of the item (like item.display) from the list to the next page as a prop
In the new page, use that prop in my <header-row> component to show the title for that page.
Seems simple, but I can't get the last two steps working:
Header Component:
<template>
<div>
<h3 class='text-primary'>{{ title }}</h3>
<h5 class='text-muted'>{{ subTitle }}</h5>
</div>
</template>
<script>
export default {
props: [
'title',
'subTitle'
]
}
</script>
List items:
<router-link v-for="item in items" :to="{ name: 'some-page' } myProp="item.name">
{{ item.display }}
</router-link>
Child Component
<template>
<div>
<header-row title="myProp"></header-row>
<div class='container-fluid'>
<div class='row'>
<div class='col-4'>
... stuff here....
</div>
</div>
</div>
</div>
</template>
<script>
export default {
name: 'child-stuff',
props: [
'myProp'
]
}
</script>
Routing Code:
import Vue from 'vue'
import Router from 'vue-router'
import Dashboard from '#/views/Dashboard'
... more here ....
import AROverview from '#/views/ar/Overview'
import Invoice from '#/views/ar/Invoice'
import APOverview from '#/views/ap/Overview'
Vue.use(Router)
export default new Router({
routes: [
{
path: '/',
name: 'dashboard',
component: Dashboard
},
{
path: '/receivables/:id',
name: 'ar',
component: AROverview
},
{
path: '/invoice/:id',
name: 'invoice',
component: Invoice
},
... more ...
{
path: '/payables/:id',
name: 'ap',
component: APOverview
}
]
})