Search code examples
javascriptvue.jsvuejs2vue-componentvuex

Why line number doesn't work when click on another page?


I use vue js version 2.6.11

I have 3 component vue

My first component like this :

<template>
    ...
        <page-listing
          :lastPage="lastPage"
          :perPage="perPage"
          :changePage="changePage"
        ></page-listing>
      </template>
    ...
</template>

<script>
import { mapActions, mapGetters } from "vuex";
import PageListing from "@/views/app/report/PageListing";

export default {
  components: {
    "page-listing": PageListing
  },
  methods: {
    ...mapActions([
      "getReport", 
      "setPageAction", 
    ]),
    searchChange() {
      this.loadPage()
    },
    async changePage(pageNum) {
      await this.setPageAction(pageNum)
      this.loadPage();
    },
    loadPage(){
      const page = this.page
      this.getReport({page});
    },
  },
  computed: {
    ...mapGetters({
      perPage: "reportPerpage",
      lastPage: "reportLastPage",
      page: "reportPage",
    }),
  },
  mounted() {
    this.loadPage();
  }
};
</script>

My second component like this :

<template>
    ...
        <div class="card-body">
          <p class="mb-0 w-5 w-sm-100">Number</p>
          <div class="w-30 w-sm-100">Description</div>
          <div class="w-20 w-sm-100">Date</div>
          <div class="w-10 w-sm-100">Modified By</div>
        </div>
    ...
    <b-row key="list">
      <b-colxx xxs="12" v-for="(item,index) in itemsWithLineNumber" :key="index" :id="item.id">
        <list-item
          :key="item.id"
          :data="item"
        />
      </b-colxx>
    </b-row>
    <b-row v-if="lastPage>1">
      ...
        <b-pagination-nav
          :number-of-pages="lastPage"
          :link-gen="linkGen"
          :value="page"
          @change="(a)=>changePage(a)"
          :per-page="perPage"
          align="center"
          use-router
        >
      ...
    </b-row>
    ...
</template>
<script>
import { mapActions, mapGetters } from "vuex";
import ListItem from "./ListItem";
export default {
  components: {
    "list-item": ListItem
  },
  props: [
    "lastPage",
    "changePage",
  ],
  methods: {
    ...mapActions(["setItemsAction"]),
    linkGen(pageNum) {
      return pageNum === 1 ? '?' : `?page=${pageNum}`
    },
  },
  computed: {
    ...mapGetters({
      perPage: "reportPerpage",
      page: "reportPage",
      items: "reportItems",
    }),
    filtered() {
      const start = this.page * this.perPage - this.perPage
      return this.items.slice(start, start + this.perPage)
    },
    itemsWithLineNumber() {
      return this.filtered.map((item, idx) => {
        return {...item, lineNumber: (this.page - 1) * this.perPage + idx + 1}
      })
    }
  }
};
</script>

My three component like this :

<template>
<b-card no-body>
    <div class="pl-2 d-flex">
        <div class="card-body">
            <p class="mb-0 text-muted w-5">{{data.lineNumber}}</p>
            <p class="mb-0 text-muted w-30">{{data.description}}</p>
            <p class="mb-0 text-muted w-20">{{data.date}}</p>
            <p class="mb-0 text-muted w-10">{{data.created_by}}</p>
        </div>
    </div>
</b-card>
</template>

<script>
export default {
    props: ['data'],
}
</script>

My vuex store like this :

const state = {
  items: null,
  reportError: '',
  reportSuccess: '',
  page: 1,
  perPage: 4,
  lastPage: 0,
}

const getters = {
  reportError: state => state.reportError,
  reportSuccess: state => state.reportSuccess,
  reportItems: state => state.items,
  reportPage: state => state.page,
  reportPerpage: state => state.perPage,
  reportLastPage: state => state.lastPage,
}

const mutations = {
  getReportSuccess (state, res) {
    state.items = res.data
    state.perPage = res.meta.per_page;
    state.lastPage = res.meta.last_page;
  },
  getReportError (state, error) {
    state.items = null
  },
  setReportPage (state, payload) {
    state.page = payload
  },
  setPageMutation (state, payload) {
    state.page = payload
  },
  setItemsMutation (state, payload) {
    state.items = payload
  },
}

const actions = {
  getReport ({ commit }, payload) {
    ...
    axios
      .get(`${api}/report/list`, { params })
      .then(r => r.data)
      .then(res => {
        if (res.data) {
          commit('getReportSuccess', res.data)
        } else {
          commit('getReportError', 'error:getReport')
        }
      })
  },
  setReportPage ({ commit }, payload) {
    commit('setReportPage', payload)
  },
  setPageAction({ commit}, payload) {
    commit('setPageMutation', payload)
  },
  setItemsAction({ commit}, payload) {
    commit('setItemsMutation', payload)
  },
}

export default {
  state,
  getters,
  mutations,
  actions,
}

When the page loads the first time, the line number works and appears. But when I click on the page 2, the page displays blank data

How can I solve this problem?

Please help. Thanks

Update :

Demo like this : https://codesandbox.io/s/prod-hooks-dzk07b


Solution

  • Your problem is with the filtered

        filtered() {
          const start = this.currentPage * this.perPage - this.perPage;
          return this.items.slice(start, start + this.perPage);
        },
    

    the items response only has the first n results, when you get rid of them using filter, the array is empty.

    you can remove the function and use items result instead

        itemsWithLineNumber() {
          return this.items.map((item, idx) => {
            return {
              ...item,
              lineNumber: (this.currentPage - 1) * this.perPage + idx + 1,
            };
          });
        },