Home > OS >  How to correctly pass paramters to vuex mapActions
How to correctly pass paramters to vuex mapActions

Time:03-01

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 the fetchProjectIssueList 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) { ... }
  • Related