How to make routing differently than is now vuejs routing - vue.js

I have a problem. I made routing what according how many addresses have user it will display them in manner 'Addresses(addrescount)'. global variable for getting address count is '$auth.user.address_count'
Task was if user have addresses show their count in sidebar if user do not have addresses show nothing .I did that but is any chance to have another solution to this problem
Is any chance to make it different then it now is?
how it looks like in programm
see line before {{route.display}}
<template>
<div class="col-lg-3">
<div class="profile-sidebar">
<ul class="list-unstyled">
<li v-for="route in nodes" :key="route.name">
<router-link :to="route.fullPath">
<template v-if="route.display === route.meta.title && $auth.user.address_count>0">
{{ route.display }}({{$auth.user.address_count}})
</template>
<template v-else>
{{ route.display }}
</template>
</router-link>
</li>
</ul>
</div>
</div>
</template>
<script>
import { routes } from '#/routes/routes';
export default {
data() {
return {
nodes: [],
}
},
async created() {
if (!this.$auth.user)
await this.$auth.updateUserInfo();
this.loadProfileNodes();
},
methods: {
loadProfileNodes() {
let node = routes.filter(route => route.path === '/profile').pop();
let hasLocalAccount = this.$auth.hasLocalAccount;
this.nodes = [];
node.children.forEach((route) => {
route['fullPath'] = node.path + '/' + route.path;
if ((!hasLocalAccount && route.path !== 'change-password') || (hasLocalAccount && route.path !== 'set-password')) {
this.nodes.push(route);
}
});
}
},
}
</script>
my routes.js see /profile children address-list route.
const routeOptions = [
{ path: '/', name: 'default', view: 'home', display: 'Home', meta: { showInMenu: true } },
{ path: '/401-forbidden', name: 'forbidden', view: 'errors/401-forbidden', display: '401 Forbidden' },
{ path: '/404-not-found', name: 'not-found', view: 'errors/404-not-found', display: '404 Page Not Found' },
{ path: '/login', name: 'login', view: 'auth/login' },
{ path: '/register', name: 'register', view: 'auth/register' },
{ path: '/auth/forgot-password', view: 'auth/forgot-password' },
{ path: '/auth/reset-password', view: 'auth/reset-password', props: (route) => ({ code: route.query.code }) },
{ path: '/auth/confirm-email', view: 'auth/confirm-email', props: (route) => ({ userId: route.query.userId, token: route.query.token }) },
{ path: '/admin/user-list', view: 'admin/users/user-list', display: 'Users', meta: { showInMenu: true, auth: { roles: 'Admin' } } },
{ path: '/admin/company-list', view: 'admin/companies/company-list', display: 'Companies', meta: { showInMenu: true, auth: { roles: 'Admin' } } },
{
path: '/profile',
view: 'profile/profile',
display: 'Edit profile',
meta: { auth: true },
children: [
{
path: '',
display: 'My Profile',
view: 'profile/edit-profile',
meta: { auth: true }
},
{
path: 'manage-logins',
display: 'External Logins',
view: 'profile/manage-logins',
meta: { auth: true }
},
{
path: 'address-list',
display: 'Addresses',
view: 'profile/addresses/address-list',
meta: { auth: true, title: 'Addresses' }
},
{
path: 'change-password',
display: 'Change Password',
view: 'profile/change-password',
meta: { auth: true }
},
{
path: 'set-password',
display: 'Set Password',
view: 'profile/set-password',
meta: { auth: true }
}
]
},
{ path: '*', redirect: { name: 'not-found' } }
];
function addDynamicImport(route) {
if (!route.view)
return route;
if (route.children && route.children.length) {
route.children = route.children.map(child => {
return addDynamicImport(child);
});
}
return {
...route,
component: () => import(/* webpackChunkName: "[request]" */ `#/components/views/${route.view}`)
}
}
const routes = routeOptions.map(route => {
return addDynamicImport(route);
})
export { routes }
router.js
import Vue from 'vue';
import VueRouter from 'vue-router';
import { routes } from './routes';
Vue.use(VueRouter);
let router = new VueRouter({
mode: 'history',
routes
});
export default router;

Answer is simple. You can add flag into '/profile/addres-list' route meta tag and check it if it is true/ True means we found the needed page
{
path: 'address-list',
display: 'Addresses',
view: 'profile/addresses/address-list',
meta: { auth: true, title: 'Addresses' }
},
into this (difference in the last line)
{
path: 'address-list',
display: 'Addresses',
view: 'profile/addresses/address-list',
meta: { auth: true, isAddressList: true }
}
and change
<template v-if="route.display === route.meta.title &&$auth.user.address_count>0">
to this
<template v-if="route.meta.isAddressList && $auth.user.address_count>0">

Related

Push route to parent component inside a function (Vue)

I feel like I'm missing something very obvious but I can't figure it out. Please help!
I have the following routes defined:
const routes = [
{
path: '/',
name: 'Login',
component: () => import('../views/Login.vue'),
meta: {
authRedirect: true
}
},
{
path: '/companies',
name: 'Companies',
component: () => import('../views/Companies.vue'),
meta: {
requiresAuth: true
}
},
{
path: '/companies/:id',
name: 'Company',
component: () => import('../views/Company.vue'),
meta: {
requiresAuth: true
}
},
{
path: '*',
name: '404',
component: () => import('../views/404.vue')
}
]
Then I have the following in my component:
export default {
name: 'Company',
data() {
return {
company: {}
}
},
methods: {
getCompanyDetails: function() {
let self = this
axios.get('/api/companies/' + this.$route.params.id).then(function(response) {
self.company = response.data
}).catch(function() {
self.$router.push('companies')
})
}
},
created() {
this.getCompanyDetails()
}
}
Essentially everything is working if the API returns data, but inside the catch function I'm trying to push the route back to /companies. But it's redirecting to /companies/companies. How do I redirect it to the correct route?
Did you tried $router.push('/companies') (with a / in the path) ?
Also, you can use $router.push({ name: 'Companies' }) if you want to make it more clear, it will match the name defined in your routes.

Why does the router link not work the first time?

I have a grpc application, there is authorization. When you start a project, you must be logged in. I decided to add under the login button if you are not registered. But the router does not work. Only at the entrance, go to the registration page. Please help to understand what is the mistake? Why is seemingly blocked?
routes.js
const routes = [
{
path: "/",
component: () => import("layouts/MainLayout"),
children: [
{
path: "",
component: () => import("pages/Index"),
meta: { requireAuth: true }
},
{
path: "/logs",
component: () => import("pages/Logs"),
meta: { requireAuth: true, admin: true }
}
]
},
{
path: "/",
component: () => import("layouts/AuthLayout"),
children: [
{
path: "/welcome",
component: () => import("pages/Auth"),
meta: { guest: true }
},
{
path: "/register",
component: () => import("pages/Register"),
meta: { guest: true }
}
]
}
];
I tried many things, like in Auth.vue:
<q-item to='/register'>Sign Up</q-item>
<router-link tag="a" :to="{path:'/register'}" replace>Go</router-link>
<span #click="callSomeFunc()">Register</span>
...
methods: {
callSomeFunc() {
this.$router.push({ path: "/register" });
}
My router-view in App.vue
for more information github repo
You have duplicate routes in your config - the path / is used on 2 routes. You should fix this.
To prevent unauthorized users to see your protected pages you can add a global navigation guard to your router through the beforeEach hook:
import VueRouter from 'vue-router';
const routes = [
{
path: "/",
component: () => import("layouts/MainLayout"),
meta: { requireAuth: true },
children: [
{
path: "",
component: () => import("pages/Index"),
},
{
path: "logs",
component: () => import("pages/Logs"),
meta: { admin: true }
}
]
},
{
path: "/login",
component: () => import("layouts/AuthLayout"),
children: [
{
path: "",
component: () => import("pages/Auth"),
},
{
path: "/register",
component: () => import("pages/Register"),
}
]
}
];
const router = new VueRouter({
routes
});
router.beforeEach((to, from, next) =>
{
if (to.matched.some(route => route.meta.requireAuth))
{
if (userNotLogged) next('/login');
else next();
}
else next();
});
export default router;
You may also consider reading a more verbose tutorial, e.g. https://www.digitalocean.com/community/tutorials/how-to-set-up-vue-js-authentication-and-route-handling-using-vue-router

vue-router returns 'function%20%' in url instead of param

So I'm showing some bread-crumbs like so..
<router-link to="/" class="breadcrumb-item">Home</router-link>
<router-link :to="{name: 'provider-dashboard', params: { id: provider_id }}" class="breadcrumb-item">Provider Dashboard</router-link>
<router-link :to="{name: 'provider-account-dash', params: { provider_id: provider_id, id: account_id }}" class="breadcrumb-item">Account Dashboard</router-link>
<router-link :to="{name: 'resident-profile', params: { account_id: account_id, id: resident_id }}" class="breadcrumb-item">Resident Profile</router-link>
I'm setting the param values with computed props that look like so..
account_id: {
get() {
return this.$store.getters['AssessmentPlanForm/getAccountId'];
},
set(value) {
this.$store.dispatch('AssessmentPlanForm/setAccountId', value);
},
},
provider_id: {
get() {
return this.$store.getters['AssessmentPlanForm/getProviderId'];
},
set(value) {
this.$store.dispatch('AssessmentPlanForm/setProviderId', value);
}
},
resident_id: {
get() {
return this.$store.getters['AssessmentPlanForm/getResidentId'];
},
set(value) {
this.$store.dispatch('AssessmentPlanForm/setResidentId', value);
},
},
I have confirmed that the values of the computed properties are correct, however when I click the router-link breadcrumb to go to desired location, the url shows users/function%20Number() instead of say users/18.
Why is this occurring and how can I get vue-router to properly render the parameter set by computed-prop?
Update from 1st comment
Here are the getters & no I'm not doing that for these attributes.
getId: (state) => {
return state.id;
},
getProviderId: (state) => {
return state.provider_id;
},
getEmployeeId: (state) => {
return state.employee_id;
},
getAccountId: (state) => {
return state.account_id;
},
getResidentId: (state) => {
return state.resident_id;
},
getSlug: (state) => {
return state.slug;
},
Update from 2nd comment
Vue.use(Router);
export default new Router({
mode: "history",
base: process.env.BASE_URL,
routes: [{
path: "/",
name: "home",
component: Splash,
prop: true
},
{
path: "/about",
name: "about",
component: About,
prop: true,
},
{
path: "/contact",
name: "contact",
component: ContactUs,
prop: true,
},
{
path: "/pricing",
name: "pricing",
component: Pricing,
prop: true,
},
{
path: "/faq",
name: "faq",
component: Faq,
prop: true
},
{
path: "/polls",
name: "polls",
component: Polls,
prop: true
},
{
path: "/login",
name: "login",
component: Login,
prop: true
},
{
path: "/provider-signup",
name: "provider-signup",
component: ProviderSignup,
prop: true
},
{
path: "/provider-dashboard/:id",
name: "provider-dashboard",
component: ProviderDash,
prop: true
},
{
path: "/providers/:id/edit",
name: "edit-provider",
component: EditProvider,
prop: true
},
{
path: "/provider/:id/employee-invitation",
name: "employee-invitation",
component: ProviderEmployeeInvite,
prop: true
},
{
path: "/employee-signup",
name: "employee-signup",
component: EmployeeSignup,
prop: true
},
{
path: "/employee-dashboard/:id",
name: "employee-dashboard",
component: EmployeeDash,
prop: true
},
{
path: "/employees/:id/edit",
name: "edit-employee",
component: EditEmployee,
prop: true
},
{
path: "/provider/:provider_id/employees",
name: "employees",
component: Employees,
prop: true
},
{
path: "/provider/:provider_id/accounts/new",
name: "provider-account-signup",
component: ProviderAccountSignup,
prop: true
},
{
path: "/providers/:provider_id/accounts/:id",
name: "provider-account-dash",
component: ProviderAccountDash,
prop: true
},
{
path: "/providers/:provider_id/accounts/:account_id/edit",
name: "edit-provider-account",
component: EditProviderAccount,
prop: true
},
.
.
.
]
});
So the answer was to fix a User error on my part. I forgot to assign the values of those attributes in a page I was working on.
The answer was to load the values of these attributes #created
retrieve(context, record_id) {
let resident_id = router.currentRoute.params.resident_id;
Axios.get(`/residents/${resident_id}/assessment_plan_forms/${record_id}`, {
headers: {
'Authorization': 'Bearer ' + window.$cookies.get('access_token'),
'x-amz-acl': 'public-read'
}
})
.then((response) => {
// let current_user = response.data.locals.current_user;
let provider = response.data.locals.provider;
let resident = response.data.locals.resident;
let account = response.data.locals.account;
let pdf_url = response.data.locals.pdf_url;
let date_of_record = response.data.locals.date_of_record;
let assessment_plan_form = response.data.locals.assessment_plan_form;
context.dispatch('AssessmentPlanForm/setId', assessment_plan_form.id, {
root: true
})
context.dispatch('AssessmentPlanForm/setProviderId', provider.id, {
root: true
})
context.dispatch('AssessmentPlanForm/setAccountId', account.id, {
root: true
})
context.dispatch('AssessmentPlanForm/setResidentId', resident.id, {
root: true
});
context.dispatch('AssessmentPlanForm/setPdfUrl', pdf_url, {
root: true
});
context.dispatch('AssessmentPlanForm/setDateOfRecord', date_of_record, {
root: true
});
context.dispatch('AssessmentPlanForm/setResidentSignature', resident.full_name, {
root: true
});
// redirect to show page
router.push({
name: 'show-assessment-plan',
params: {
resident_id: resident.id,
id: record_id
}
})
})
.catch((error) => {
console.log(error);
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.3/vue.js"></script>
And #retrieve gets called in the Created hook like:
methods: {
loadAssessmentPlan() {
this.$store.dispatch('AssessmentPlanForm/retrieve', this.$route.params.id)
},
},
created() {
this.loadAssessmentPlan();
},

Angular 5 Parent reloads when Child route changes

I am having a problem where my parent component (LoggedInComponent) is getting reloaded every time one of the child components changes (child route change).
I have searched high and low for an answer but can't seem to find anything suitable to my situation.
Here is my app-routing.module.ts
const routes: Routes = [
{ path: 'login', component: LoginComponent },
{
path: '', component: LoggedInComponent, canActivateChild: [AuthGuard], children: [
{ path: '', redirectTo: 'home', pathMatch: 'full' },
{ path: 'home', component: DashboardComponent },
{ path: 'groups', component: GroupsComponent, data: { role: [PermissionEnum.Groups_View] } },
{ path: 'groups/edit/:id', component: GroupDetailComponent, data: { role: [PermissionEnum.Groups_Edit] } },
{ path: 'groups/create', component: GroupDetailComponent, data: { role: [PermissionEnum.Groups_Create] } },
{ path: 'users', component: UsersComponent, data: { role: [PermissionEnum.Users_View] } },
{ path: 'users/edit/:id', component: UserDetailComponent, data: { role: [PermissionEnum.Users_Edit] } },
{ path: 'users/create', component: UserDetailComponent, data: { role: [PermissionEnum.Users_Create] } },
{ path: 'profile', component: ProfileComponent },
{ path: 'profile/:tabindex', component: ProfileComponent },
{ path: 'settings', component: SettingComponent, data: { role: [PermissionEnum.Global_Settings_View] } },
{ path: 'external-login/:result', component: ExternalLoginProvidersComponent },
{ path: 'permissions/:id/:type', component: PermissionsComponent, data: { role: [PermissionEnum.Users_AssignPermissions] } },
{ path: 'permission-denied', component: PermissionDeniedComponent },
{ path: 'reference-data/:type', component: ReferenceDataComponent, data: { role: [PermissionEnum.Sms_Template_View] } },
{ path: 'reference-data/:type/edit/:id', component: ReferenceDataDetailsComponent, data: { role: [PermissionEnum.Sms_Template_Edit] } },
{ path: 'reference-data/:type/create', component: ReferenceDataDetailsComponent, data: { role: [PermissionEnum.Sms_Template_Create] } },
{ path: 'tenants', component: TenantsComponent, data: { role: [PermissionEnum.Tenant_View] } },
{ path: 'tenants/edit/:id', component: TenantDetailComponent, data: { role: [PermissionEnum.Tenant_Edit] } },
{ path: 'tenants/create', component: TenantDetailComponent, data: { role: [PermissionEnum.Tenant_Create] } },
{ path: 'sms-campaigns', component: SmsCampaignsComponent, data: { role: [PermissionEnum.SmsCampaign_View] } },
{ path: 'sms-campaigns/create', component: CreateSmsCampaignComponent, data: { role: [PermissionEnum.SmsCampaign_Create] } },
{ path: 'sms-campaigns/details/:id', component: SmsCampaignDetailsComponent, data: { role: [PermissionEnum.SmsCampaign_View] } },
{ path: 'document-library', component: LibraryDocumentsComponent },
{ path: 'report-management', component: ReportManagementComponent },
{ path: 'report-management/create', component: CreateReportComponent },
{ path: 'report-management/:id', component: IdpComponent },
{ path: 'report-management/edit/:id', component: ReportDetailsComponent },
{ path: 'report/:reportName', component: ReportComponent }
]
}
];
#NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule { }
I have the main router-outlet in my app.component.html which after loggin in takes you to the LoggedInComponenet which has the header, footer, left menu and another router-outlet for the children.
This is my LoggedIn.componenent.html
<app-header></app-header>
<div class="m-grid__item m-grid__item--fluid m-grid m-grid--ver-desktop m-grid--desktop m-body">
<app-left-menu></app-left-menu>
<div *ngIf="loading">
<app-loading-indicator></app-loading-indicator>
</div>
<div class="center-display" *ngIf="childrenLoadingAllowed">
<router-outlet class="m-grid__item m-grid__item--fluid m-wrapper" [ngClass]="{ hidden: loading }"></router-outlet>
</div>
</div>
<app-footer></app-footer>
I then have my LoggedIn.component.ts
import { Component, OnInit } from '#angular/core';
import { BaseComponent } from '../shared/base.component';
#Component({
selector: 'app-logged-in',
templateUrl: './logged-in.component.html',
styleUrls: ['./logged-in.component.css']
})
export class LoggedInComponent extends BaseComponent implements OnInit {
public loading = true;
public childrenLoadingAllowed = false;
constructor() {
super();
}
ngOnInit() {
this.layoutService.setLoadingEvent
.subscribe((res: boolean) => {
if (this.loading !== res)
this.loading = res;
});
}
}
And then finally here is the left-menu which keeps reloading when i load a child
import { Component, OnInit, ViewEncapsulation } from '#angular/core';
import { BaseComponent } from '../../shared/base.component';
import { PermissionEnum, LookupClient, LookupType, LookUpDto } from '../../../services/web-api-generated';
#Component({
selector: 'app-left-menu',
templateUrl: './left-menu.component.html',
styleUrls: ['./left-menu.component.scss'],
encapsulation: ViewEncapsulation.None
})
export class LeftMenuComponent extends BaseComponent implements OnInit {
public hasReports = false;
public reports: Array<LookUpDto> = new Array<LookUpDto>();
constructor(private lookupClient: LookupClient) {
super();
this.loadReportMenuItems();
}
ngOnInit() {
this.layoutService.rebuildReportMenu
.subscribe(res => {
this.loadReportMenuItems();
});
}
private loadReportMenuItems(): void {
this.lookupClient.getLookUpValues(LookupType.MunicipalReports)
.subscribe((res: Array<LookUpDto>) => {
this.reports = res;
this.reports.forEach(element => {
element.value = element.value.replace(/\s+/g, '-').toLocaleLowerCase();
});
this.hasReports = res.length > 0;
});
}
}
I fixed the problem by moving the api call to a service with a variable there and only loading the data if its not already set or if the force variable is passed through.
I believe this is a bug as mentioned here: https://github.com/angular/angular/issues/18374
yes, canActivateChild reloads whole parent component while changing between child routes

How to create dynamic links based on an API request

I am completely new to both vue.js and Javascript. How do I dynamically create nav links from an Axios request?
I am wanting to follow what's being done in the item section which is currently static information, but i want to dynamically return links based on whats returned in the json request.
import * as types from '../../mutation-types'
import lazyLoading from './lazyLoading'
import charts from './charts'
// gathering items from API
const url = 'http://localhost:8080/items/'
data: {
items: []
},
mounted() {
axios.get(url).then(response => {
this.results = items.data
})
}
// Sidebar links are statically created here
const state = {
items: [
{
name: 'Dashboard',
path: '/dashboard',
meta: {
icon: 'fa-tachometer',
link: 'dashboard/index.vue'
},
component: lazyLoading('dashboard', true)
},
{
name: 'Axios',
path: '/axiosDemo',
meta: {
auth: true,
icon: 'fa-rocket',
link: 'axios/index.vue'
},
component: lazyLoading('axios', true)
},
charts,
]
}
const mutations = {
[types.EXPAND_MENU] (state, menuItem) {
if (menuItem.index > -1) {
if (state.items[menuItem.index] && state.items[menuItem.index].meta) {
state.items[menuItem.index].meta.expanded = menuItem.expanded
}
} else if (menuItem.item && 'expanded' in menuItem.item.meta) {
menuItem.item.meta.expanded = menuItem.expanded
}
}
}
export default {
state,
mutations
}
I think what I am wanting to do is something like this (python example):
items:
for i in items_payload:
{
name: i.name,
path: i.url,
meta: {
icon: 'fa-tachometer',
link: i.name+'/index.vue'
},
},
How do I best accomplish this in vue.js? Any help would be appreciated. Thanks.
If you are making the api request from a component, you can create a list of links like follows:
// for demo purposes, let's say links are returned as an array of objects
[
{
href: '/path/to/page1',
linkText: 'Page 1'
},
{
href: '/path/to/page2',
linkText: 'Page 2'
}
]
// MyComponent.vue
<template>
<div class="sidebar">
<ul>
<li v-for="(item, index) in items" :key="index">
<a :href="item.href">{{ item.linkText }}</a>
</li>
</ul>
</div>
</template>
export default {
data () {
return {
links: []
}
},
mounted() {
axios.get(url).then(response => {
this.links = items.data
})
}
}