I have a ProjectPage.vue page which displays issues in v-data-table. Items are retrieved from server API calls in the sidebar and displayed there. After selecting a project, I want to get its issues from the server using the project's id. Is it possible to do this using Vuex.
Is it possible to use Vuex so that every project can use the same .js file to retrieve its issue since there could be any number of projects.
What I want to do is pass the id and item as props from VerticalNavMenu.vue to ProjectPage so that I can pass the id as a parameter to the mapAction inside the ProjectPage to retrieve its issue.
The method I'm doing now doesn't work. When I open the project's table, the table has no data available
I hope Peoject_Pages.js helps to understand my problem.
VerticalNavMenu.vue (Related Template Behavior 38 -> 48)
<template> <v-navigation-drawer :value="isDrawerOpen" app expand-on-hover mini-variant-width="60px" floating width="260" class="app-navigation-menu" :right="$vuetify.rtl" @input="val => $emit('update:is-drawer-open', val)" > <!-- Navigation Header --> <div class="vertical-nav-header d-flex items-center ps-6 pe-5 pt-5 pb-2"> <router-link to="/" class="d-flex align-center text-decoration-none"> <v-slide-x-transition> <h2 class="app-title text--primary">ITrackerHub</h2> </v-slide-x-transition> </router-link> </div> <!-- Navigation Items --> <v-list expand shaped class="vertical-nav-menu-items pr-5"> <nav-menu-link title="Dashboard" :to="{ name: 'dashboard' }" :icon="icons.mdiHomeOutline" ></nav-menu-link> <v-list> <v-list-group :prepend-icon="icons.mdiTelevisionGuide"> <template v-slot:activator> <v-list-item-content> <v-list-item-title v-text="'My Projects'"></v-list-item-title> </v-list-item-content> </template> <v-list-item v-for="(project, index) in ProjectList" :key="index"> <v-icon class="mx-2">{{ icons.mdiAccountGroup }}</v-icon> <v-list-item-content> <router-link class="d-flex align-center text-decoration-none black--text" :to="{ name: 'ProjectPage', params: { id: project.id, project} }" > {{ project.title }} </router-link> </v-list-item-content> </v-list-item> </v-list-group> </v-list> <nav-menu-link title="My Issues" :to="{ name: 'MyIssues' }" :icon="icons.mdiBookEditOutline"></nav-menu-link> <nav-menu-link style="position:relative; top:70px;" title="Account Settings" :to="{ name: 'pages-account-settings' }" :icon="icons.mdiAccountCogOutline" ></nav-menu-link> <nav-menu-link style="position: relative; top: 200px" title="Create Project" :to="{ name: 'CreateProject' }" :icon="icons.mdiPlusMinus" ></nav-menu-link> </v-list> </v-navigation-drawer> </template> <script> // eslint-disable-next-line object-curly-newline import { mdiHomeOutline, mdiAlphaTBoxOutline, mdiEyeOutline, mdiCreditCardOutline, mdiTable, mdiFileOutline, mdiFormSelect, mdiAccountCogOutline, mdiAccountGroup, mdiAccountMultiple, mdiTelevisionGuide, mdiBookEditOutline, mdiPlusMinus, } from '@mdi/js' // import NavMenuSectionTitle from './components/NavMenuSectionTitle.vue' import NavMenuGroup from './components/NavMenuGroup.vue' import NavMenuLink from './components/NavMenuLink.vue' import { mapGetters, mapActions } from 'vuex' export default { components: { // NavMenuSectionTitle, NavMenuGroup, NavMenuLink, }, computed: { ...mapGetters(['ProjectList']) }, methods: { ...mapActions(['fetchProjects']) }, created() { // this.getProjectList() this.fetchProjects() }, props: { isDrawerOpen: { type: Boolean, default: null, }, }, setup() { return { icons: { mdiHomeOutline, mdiAlphaTBoxOutline, mdiEyeOutline, mdiCreditCardOutline, mdiTable, mdiFileOutline, mdiFormSelect, mdiAccountCogOutline, mdiAccountGroup, mdiAccountMultiple, mdiTelevisionGuide, mdiBookEditOutline, mdiPlusMinus, }, } }, } </script> <style lang="scss" scoped> .app-title { font-size: 1.25rem; font-weight: 700; font-stretch: normal; font-style: normal; line-height: normal; letter-spacing: 0.3px; } // ? Adjust this `translateX` value to keep logo in center when vertical nav menu is collapsed (Value depends on your logo) .app-logo { transition: all 0.18s ease-in-out; .v-navigation-drawer--mini-variant & { transform: translateX(-10px); } } @include theme(app-navigation-menu) using ($material) { background-color: map-deep-get($material, 'background'); } .app-navigation-menu { .v-list-item { &.vertical-nav-menu-link { ::v-deep .v-list-item__icon { .v-icon { transition: none !important; } } } } } </style>
NavBar.js
import axios from 'axios' const state = { Projects: [], } const getters = { ProjectList: (state) => state.Projects } const actions = { async fetchProjects({ commit }) { const response = await axios.get('https://fadiserver.herokuapp.com/api/v1/my-projects/') commit('setProjects', response.data) } } const mutations = { setProjects: (state, Projects) => (state.Projects = Projects) } export default { state, getters, actions, mutations }
ProjectPage.vue
<template> <v-card> <v-card-title class="text-center justify-center py-6"> <h1 class="font-weight-bold text-h2 basil--text"> {{ project.title }} </h1> </v-card-title> <v-tabs v-model="tab" background-color="primary" dark centered> <v-tab v-for="item in items" :key="item.tab">{{ item.tab }}</v-tab> </v-tabs> <v-tabs-items v-model="tab"> <v-tab-item v-for="item in items" :key="item.tab"> <v-card flat> <v-card v-if="item.tab == 'Issues'"> <template> <div class="text-center"> <v-dialog v-model="dialog" width="500"> <template v-slot:activator="{ on }"> <v-btn class="success" dark v-on="on"> <v-icon align-self: left> mdi-plus-thick </v-icon> Add Issue </v-btn> </template> <v-card> <v-card-title> <h2>Add Issue</h2> </v-card-title> <v-card-text> <v-form class="px-3"> <v-text-field v-model="title" label="Title"></v-text-field> <v-textarea v-model="description" label="Description"></v-textarea> <v-select item-text="text" item-value="value" :items="time_est" v-model="time_estimate" label="Time Estimate" ></v-select> <v-select item-text="title" item-value="id" :items="issueType" v-model="issue_type" label="Issue Type" ></v-select> <v-select item-text="title" item-value="id" v-model="issue_status" label="Issue Status" :items="issueStatus" ></v-select> <v-select item-text="title" item-value="id" :items="issueSeverity" v-model="issue_severity" label="Issue Severity" ></v-select> <v-spacer></v-spacer> <v-btn flat @click=" postIssue() reloadPage() " class="success mx-0 mt-3" > <v-icon align-self:left>mdi-content-save-check-outline</v-icon> Save</v-btn > </v-form> </v-card-text> </v-card> </v-dialog> </div> </template> <v-card> <v-data-table :headers="headers" :items="Project_Issues" item-key="full_name" class="table-rounded" hide-default-footer enable-sort @click:row="handleClick" > </v-data-table> </v-card> </v-card> </v-card> </v-tab-item> </v-tabs-items> </v-card> </template> <script> import axios from 'axios' import { mapGetters, mapActions } from 'vuex' export default { props: ['id', 'project'], computed: { ...mapGetters(['Project_Issues']), }, data() { return { tab: null, items: [{ tab: 'Issues' }, { tab: 'Calender' }, { tab: 'About' }], title: '', description: '', time_estimate: '', issue_type: '', issue_status: '', issue_severity: '', time_est: [ { value: '1', text: '1' }, { value: '2', text: '2' }, { value: '3', text: '3' }, { value: '4', text: '4' }, { value: '5', text: '5' }, { value: '6', text: '6' }, { value: '7', text: '7' }, { value: '8', text: '8' }, ], } }, setup() { return { headers: [ { text: 'Title', value: 'title' }, { text: 'Description', value: 'description' }, { text: 'Estimate', value: 'time_estimate' }, { text: 'Assignees', value: 'user' }, { text: 'Type', value: 'issueType' }, { text: 'Status', value: 'issueStatus' }, { text: 'Severity', value: 'issueSeverity' }, ], } }, methods: { ...mapActions(['fetchProjectIssueList']), handleClick(issue) { this.$router.push({ name: 'IssuePage', params: { id: issue.id, issue }, }) }, postIssue() { axios .post('https://fadiserver.herokuapp.com/api/v1/my-issues/', { title: this.title, description: this.description, time_estimate: this.time_estimate, userid: 'f3260d22-8b5b-4c40-be1e-d93ba732c576', projectid: this.id, issueTypeId: this.issue_type, issueStatusId: this.issue_status, issueSeverityId: this.issue_severity, }) .then(response => { console.log(response) }) .catch(error => { console.log(error) }) }, reloadPage() { window.location.reload() }, }, mounted() { this.fetchProjectIssueList(this.id) }, } </script> <style scoped> .v-btn { left: 43%; } </style>
Project_Page.js
import axios from 'axios' const state = { issuesList: [], } const getters = { Project_Issues: (state) => state.issuesList } const actions = { async fetchProjectIssueList({ commit }, {projectid}) { const response = await axios.get('https://fadiserver.herokuapp.com/api/v1/my-issues-titles/?projectid=' + projectid) commit('setProjectIssues', response.data) }, } const mutations = { setProjectIssues: (state, issuesList) => (state.issuesList = issuesList) } export default { state, getters, actions, mutations }
There are two ways to solve your problem.
projectid
in thefetchProjectIssueList
methodfetchProjectIssueList
methodor