Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Vuetify Using datatable with external data from an API with Vuex

I want to use the vuetify framework with Vuex , but there is limited documentation about using it with Vuex.

I want to:

  • Get data from an external API ( but only the data needed )
  • Then Save the data in state and edit or whatever
  • Then push any changes back to the api

I have tried some of the external pagination and sorting examples with vuetify , but I can't get it to show all record count unless I hard code it.

I am quite new to Vue and Vuetify , so maybe I am misunderstanding something.

<template>
<div>
    <v-data-table
            :headers='headers'
            :items='items'
            :length='pages'
            :search='search'
            :pagination.sync='pagination'
            :total-items='totalItemCount'
            class='elevation-1'
    >
        <template slot='items' slot-scope='props'>
            <td class='text-xs-right'>{{ props.item.id }}</td>
            <td class='text-xs-right'>{{ props.item.first_name }}</td>
            <td class='text-xs-right'>{{ props.item.last_name }}</td>
            <td class='text-xs-right'>{{ props.item.avatar }}</td>
        </template>
    </v-data-table>
</div>
</template>
<script>
import moment from 'moment'
import axios from 'axios'

export default {
  name: 'test-table',
  watch: {
    pagination: {
      async handler () {
        const rowsPerPage = this.pagination.rowsPerPage
        // const skip = (this.pagination.page - 1) * rowsPerPage
        const pageNumber = this.pagination.page
        const res = await axios.get(`https://reqres.in/api/users?page=${pageNumber}&per_page=${rowsPerPage}`)
        this.items = res.data.data
        this.$store.commit('saveTableData', this.items)
      },
      deep: true
    }
  },
  computed: {
    pages () {
      return 171
    },
    totalItemCount () {
      return 400
    }
  },
  async mounted () {
    const rowsPerPage = this.pagination.rowsPerPage
    const skip = (this.pagination.page - 1) * rowsPerPage
    const res = await axios.get(`https://reqres.in/api/users?page=${skip}&per_page=${rowsPerPage}`)
    this.items = res.data.data
    this.$store.commit('saveTableData', this.items)
  },
  methods: {
    nzDate: function (dt) {
      return moment(dt).format('DD/MM/YYYY')
    }
  },
  data: () => ({
    search: '',
    // totalItems: 0,
    items: [],
    pagination: {
      sortBy: 'Date'
    },
    headers: [
      { text: 'ID', value: 'id' },
      { text: 'First Name', value: 'first_name' },
      { text: 'Last Name', value: 'last_name' },
      { text: 'Avatar', value: 'avatar' }
    ]
  })
}

like image 394
Martin Thompson Avatar asked Mar 03 '18 04:03

Martin Thompson


1 Answers

This is my working setup:

<template>
  <v-data-table
      :total-items="pagination.totalItems"
      :pagination.sync="pagination"
      :items="rows"
      :headers="columns">
      <template slot="headers" slot-scope="props">
        <tr :active="props.selected">
          <th v-for="column in props.headers">
            {{ column.value }}
          </th>
        </tr>
      </template>

    <template slot="items" slot-scope="props">
        <tr>
          <td v-for="cell in props.item.row">
            <v-edit-dialog lazy>
              {{ cell.value }}
              <v-text-field
                :value="cell.value"
                single-line
                counter>
              </v-text-field>
            </v-edit-dialog>
          </td>
        </tr>
      </template>
  </v-data-table>
</template>

<script>
export default {
  data: () => ({
    pagination: {
      page: 1,
      rowsPerPage: 10,
      totalItems: 0
    },

    selected: []
  }),

  computed: {
    columns: {
      get () {
        return this.$store.state.columns
      }
    },

    rows: {
      get () {
        return this.$store.state.rows
      }
    }
  },

  methods: {
    async getRowsHandler () {
      try {
        const {total} = await this.$store.dispatch('getRows', {
          tableIdentifier: this.$route.params.tableIdentifier,
          page: this.pagination.page,
          size: this.pagination.rowsPerPage
        })

        this.pagination.totalItems = total
      } catch (error) {
        // Error
      }
    }
  }
}
</script>

I didn't implement everything. If you miss a specific part ask again and I will update my example. One more tip: You should avoid watch deep wherever possible. It can result in heavy calculations.

like image 126
Julian Avatar answered Oct 22 '22 12:10

Julian