I'm trying to dynamically update a <router-link> path based on what view component it is used within. Below is the <router-link> that is looping through the compItems array which is populated by each view component.
<router-link :to="{ name: compItem.name, params: { compItems: compItem.router } }" class="cz-ds-view-related-comp" v-for="compItem in compItems" :key="compItem.name">
<div class="related-comp_icon"><img class="related-comp_icon" :src="require('#/assets/home/icons/' + compItem.atomicIcon + '')" alt=""></div>
<div class="related-comp_title"><h3>{{ compItem.name }}</h3> <img src="../../assets/home/icons/arrow-right.svg"></div>
</router-link>
export default {
name: 'relatedSection',
props: {
compItems: {
type: Array
}
}
}
</script>
Below is an example of a view component defining router.
data () {
return {
compItems: [
{ name: 'Links', atomicIcon: 'atom.svg', router: 'links'},
{ name: 'Form Elements', atomicIcon: 'atom.svg', router: 'form-elements'},
{ name: 'Avatars', atomicIcon: 'atom.svg', router: 'avatars'},
{ name: 'Badges', atomicIcon: 'atom.svg', router: 'badges'}
]
}
}
And this is the console error I'm getting.
Thanks in advance!
Edit:
Here's a snapshot of the router file:
const routes = [{
path: '/',
name: 'home',
props: true,
component: Home
}, {
path: '/avatars',
name: 'avatars',
props: true,
component: Avatars
}, {
path: '/badges',
name: 'badges',
props: true,
component: Badges
}, {
path: '/buttons',
name: 'buttons',
props: true,
component: Buttons
}, {
path: '/breadcrumbs',
name: 'breadcrumbs',
props: true,
component: Breadcrumbs
}, {
path: '/form-elements',
name: 'form-elements',
props: true,
component: FormElements
}, {
path: '/icons',
name: 'icons',
props: true,
component: Icons
},
...
The router's route definitions all have lowercase name properties. When you use a <router-link> to access them by name, you need to use an exact match, but your compItems have capitalized names.
Also, you are using route params in the link but none of your routes have any defined.
Here is a refactoring to make the code clearer and correct:
<template v-for="compItem in compItems">
<router-link :to="{ name: compItem.name }" class="cz-ds-view-related-comp">
<div class="related-comp_icon">
<img class="related-comp_icon" :src="require('#/assets/home/icons/' + compItem.atomicIcon + '')" alt="">
</div>
<div class="related-comp_title">
<h3>{{ compItem.title }}</h3>
<img src="../../assets/home/icons/arrow-right.svg">
</div>
</router-link>
</template>
data () {
return {
compItems: [
{ title: 'Links', atomicIcon: 'atom.svg', name: 'links'},
{ title: 'Form Elements', atomicIcon: 'atom.svg', name: 'form-elements'},
{ title: 'Avatars', atomicIcon: 'atom.svg', name: 'avatars'},
{ title: 'Badges', atomicIcon: 'atom.svg', name: 'badges'}
]
}
}
Related
**I'm getting this error - vue #/src/assets/images/1.jpg: hasn't been transpiled yet error. I'm looping through tha App component static array. The src is specified correctly though. Using require vue method.
https://codesandbox.io/s/eloquent-grass-j1usw8?file=/src/components/v-carousel-item.vue
**
// APP
<template>
<v-carousel :carousel_data="sliderItems" />
</template>
<script>
import vCarousel from "./components/v-carousel.vue";
export default {
name: "App",
data() {
return {
sliderItems: [
{ id: 1, name: "img1", img: "1.jpg" },
{ id: 2, name: "img2", img: "2.jpg" },
{ id: 3, name: "img3", img: "3.jpg" },
],
};
},
components: {
vCarousel,
},
};
</script>
// Parent
<template>
<div class="container">
<div class="v-carousel">
<v-carousel-item
v-for="item in carousel_data"
:key="item.id"
:item_data="item"
/>
</div>
</div>
</template>
<script>
import vCarouselItem from "./v-carousel-item.vue";
export default {
components: {
vCarouselItem,
},
props: {
carousel_data: {
type: Array,
default: () => [],
},
},
};
</script>
// Child
<template>
<div class="v-carousel-item">
<img :src="require(`../assets/images/` + item_data.img)" alt="" />
</div>
</template>
<script>
export default {
props: {
item_data: {
type: Object,
default: () => {},
},
},
};
</script>
You want to require the images upfront.
export default {
name: "App",
data() {
return {
sliderItems: [
{ id: 1, name: "img1", img: require("#/assets/images/1.jpg") },
{ id: 2, name: "img2", img: require("#/assets/images/2.jpg") },
{ id: 3, name: "img3", img: require("#/assets/images/3.jpg") },
],
};
},
Then update the carousel item component.
<div class="v-carousel-item">
<img :src="item_data.img" alt="" />
</div>
Example: https://codesandbox.io/s/little-bush-ino5zc?file=/src/components/v-carousel-item.vue:11-91
I created a PrimeNG Dialog with Steps module to create a new document, but not showing nothing inside <router-outlet>, what am I doing wrong?
Routes in lazy module Inbox: inbox.module.ts
const routes: Routes = [
{ path: '', component: InboxPageComponent },
{
path: 'new-document', component: NewDocumentComponent,
children: [
{ path: '', redirectTo: 'general', pathMatch: 'full' },
{ path: 'general', component: StepGeneralPageComponent },
{ path: 'flux', component: StepFluxPageComponent },
]
},
];
This is the dialog, inside Inbox template, inbox.component.html:
<p-dialog header="Nuevo Documento" [(visible)]="displayNewDocumentDialog" position="top" [modal]="true"
[style]="{width: '50vw'}" [draggable]="false" [resizable]="false">
<app-new-document></app-new-document>
<ng-template pTemplate="footer">
<p-button label="Limpiar campos" icon="pi pi-refresh" class="p-button-outlined"></p-button>
<p-button label="Guardar y Activar" icon="pi pi-check-circle" class="p-button-outlined"></p-button>
<p-button label="Guardar" icon="pi pi-save" class="p-button-outlined"></p-button>
</ng-template>
</p-dialog>
In component NewDocument:
this.stepItems = [
{ label: 'Generales', routerLink: 'general' },
{ label: 'Flujo documento', routerLink: 'flux' },
{ label: 'Adicionales', routerLink: '' },
{ label: 'Archivado', routerLink: '' }
]
<p-steps [model]="stepItems" [readonly]="false" styleClass="mb-3"></p-steps>
<router-outlet></router-outlet>
This is the result:
Result
I'd like to ask about render default child for view.
I know that exists topic with a similar problem but I'm pretty sure that it was for VUE2 and older vue-router. I'm having trouble rendering the default child for view Category. When I'd go to <router-link :to="{ name: routeName, params: { category: item.id } }
everything render okay except <router-view /> it's empty...
I came up with a solution with beforeUpdate(),beforeCreate() but it seems like reinventing the wheel.
If I go to /category/{id} then to /category/{id}/room/{id} and go back one page, the default view will be rendered
How to make the default child load after going to /category/{id}?
router.js
{
path: '/category/:category',
name: 'Category',
props: true,
component: Category,
children: [
{
path: '',
name: 'FavouriteDevicesInCategory',
component: Devices,
props: true,
},
{
path: 'room/:room',
name: 'Devices',
component: Devices,
props: true,
},
],
},
Category.vue - view
<template>
<div class="control">
<div class="left">
[...]
</div>
<div class="right">
<router-view />
</div>
</div>
</template>
<script>
export default {
props: ['category', 'room'],
/** generate default router-view */
beforeUpdate() {
this.$router.push('');
},
beforeCreate() {
this.$router.push('');
},
};
If your default component is Category, you have to create the routes like this:
{
path: '/category',
name: 'Category',
props: true,
component: Category,
children: [
{
path: '/:categoryId',
name: 'FavouriteDevicesInCategory',
component: Devices,
props: true,
},
{
path: 'room/:roomId',
name: 'Devices',
component: Devices,
props: true,
},
],
},
By default it will render the Category component and if you add an id to the url it will go the the Devices component
I think I found a solution, a little messy, but it seems to be the best solution to this problem
{
path: '/category/:category',
// name: 'Category',
props: true,
component: Category,
children: [
{
path: '',
name: 'Category',
component: Devices,
props: true,
},
{
path: 'room/:room',
name: 'Devices',
component: Devices,
props: true,
},
],
},
Versions:
"bootstrap-vue": "^2.0.0-rc.27",
"vue": "^2.6.10",
"vue-router": "^3.0.3",
My vue-router has children on the /app/groups route. Within the children, I created <b-nav pills> in order to navigate groups however the tabs are not showing up as .active. I'm using params on the routes, not sure if this affects it. Any ideas?
GroupContainer.vue
<template>
<div>
<b-container class="pt-3">
<b-nav pills align="center">
<b-nav-item :to="{ name: 'group.edit', params: { id: this.$route.params.id }}" >Group</b-nav-item>
<b-nav-item :to="{ name: 'group.users', params: { id: this.$route.params.id }}" >Users</b-nav-item>
</b-nav>
</b-container>
<DefaultPage title="Group name" subtitle="Settings">
<router-view></router-view>
</DefaultPage>
</div>
</template>
<script>
import DefaultPage from '../layouts/DefaultPage.vue'
export default {
name: 'GroupContainer',
components: {
DefaultPage
}
}
</script>
router.js
{ path: "/app/group", component: GroupContainer,
children: [
{ path: "", component: NotFound },
{ path: ":id", name: "group.edit", component: GroupEdit },
{ path: ":id/delete", name: "group.delete", component: GroupDelete },
{ path: ":id/users", name: "group.users", component: GroupUsers },
{ path: ":id/users/:userID", name: "group.users.edit", component: GroupEditUser },
{ path: ":id/users/:userID/delete", name: "group.users.delete", component: GroupDeleteUser },
{ path: ":id/add-user", name: "group.addUser", component: GroupAddUser },
]
},
use the active-class or exact-active-class prop, and set it to 'active'
<b-nav pills align="center">
<b-nav-item
:to="{ name: 'group.edit', params: { id: this.$route.params.id }}"
:exact-active-class="active"
>Group</b-nav-item>
<b-nav-item
:to="{ name: 'group.users', params: { id: this.$route.params.id }}"
:exact-active-class="active"
>Users</b-nav-item>
</b-nav>
https://bootstrap-vue.js.org/docs/reference/router-links
i'm doing a project with VueJS, Lodash and Babel, and my problem is that i need to populate a sidebar in my app with routes from a routes.js file. Problem is i don't really know how i can retrieve the data i need.
export default [
{
path: "/admin/login",
name: "admin.login",
component: Login
},
{
path: "/admin",
component: MasterLayout,
meta: { auth: true },
children: [
{
path: "/admin/dashboard",
alias: "/",
menu: { text: "", icon: ""},
name: "admin.dashboard",
component: DashboardIndex
}
]
},
{
path: '/403',
name: 'error.forbidden',
component: ErrorForbidden
},
{
path: "*",
name: 'error.notfound',
component: ErrorPageNotFound
}
];
That is my routes file, i basically need to iterate over each route, check if it has children or a menu property, if it has a menu it gets added to my list of sidebar items, and it's children get added as well with their own menu properties being withdrawn
In the end i'd like to get something like the following
sidebarItems: [
{
name: 'Dashboard',
icon: 'dashboard',
name: 'admin.dashboard'
},
{
name: 'OtherRoute',
icon: 'other-route',
name: 'admin.other-route',
children: [
{
name: 'SubRoute',
icon: 'sub-route',
name: 'admin.sub'
}
]
}
]
This should only account for the routes that contain a menu property.
You basically need iterate recursive over the array, so please try this:
function iterateArrayRoutes(routeArray) {
if(routeArray instanceof Array) {
var routeFormatted = routeArray.reduce(function(last, route){
if (route.hasOwnProperty("menu")) {
var item = {
name: route.name,
icon: route.menu.icon
};
if(route.hasOwnProperty("children") && route.children.length > 0) {
item.children = iterateArrayRoutes(route.children);
}
last.push(item);
}
return last;
}, []);
return routeFormatted;
}
};
Here you have a Demo https://jsfiddle.net/vm1hrwLL/