I have a ProjectPage.vue page that displays issues in a v-data-table. Projects are retrieved from a server api call in the sidebar and displayed there. After I choose a project, I would like to use that project's id to get its issues from the server. Is it possible to do so using Vuex.
Is it possible using Vuex, that each project can use the same .js file to retreive its issues, since there could be any number of projects.
What I am trying to do is from VerticalNavMenu.vue, pass an id and project as props to ProjectPage, so I can pass the id as a parameter to mapAction inside ProjectPage to retreive its issues.
The I'm way doing it now is not working. The table has no data available when I open a project's table
I hope Peoject_Pages.js helps understand what I'm asking about.
VerticalNavMenu.vue (related template lines are 38 -> 48)
<template>
<v-navigation-drawer
:value="isDrawerOpen"
app
expand-on-hover
mini-variant-width="60px"
floating
width="260"
:right="$vuetify.rtl"
@input="val => $emit('update:is-drawer-open', val)"
>
<!-- Navigation Header -->
<div >
<router-link to="/" >
<v-slide-x-transition>
<h2 >ITrackerHub</h2>
</v-slide-x-transition>
</router-link>
</div>
<!-- Navigation Items -->
<v-list expand shaped >
<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 >{{ icons.mdiAccountGroup }}</v-icon>
<v-list-item-content>
<router-link
: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 >
<h1 >
{{ 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 >
<v-dialog v-model="dialog" width="500">
<template v-slot:activator="{ on }">
<v-btn 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 >
<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()
"
>
<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"
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
}
CodePudding user response:
There are 2 ways of solving your problem.
- Or you pass an object with the key
projectid
in thefetchProjectIssueList
method - Or you do not need to destructure the object in the
fetchProjectIssueList
method
this.fetchProjectIssueList({ projectid: this.id })
...
async fetchProjectIssueList({ commit }, {projectid}) { ... }
or
this.fetchProjectIssueList(this.id)
...
async fetchProjectIssueList({ commit }, projectid) { ... }