Search code examples
laravelvue.jsvuejs2vue-tables-2

Vuetable return to page 1 after I have clicked page 5 and updated one of the content then click back


First, I clicked page 5 then clicked edit on one of item. Second, I clicked updated and clicked back to previous page which has vuetable. Then the vuetable pagination return back to page 1.

Is there any solution to prevent the page number go back to 1?

I have tried "query-params" but doesn't seem to work.

SalesOrderAdmin.vue

<template>
    <div>
        <section class="content-header">
            <h1>
                Sales Order
            </h1>


        </section>
        <div class="content">

            <div class="row">
              <div class="col-md-12">
                <div class="box box-info">
                  <div class="box-body">
                    <div class="table-responsive">
                        <myvuetable :apiUrl="apiUrl" :fields='fields' :page_no='page_no'></myvuetable>
                    </div>
                  </div>
                </div>
              </div>
            </div>
        </div>
    </div>
</template>

<script>
    export default {
        data() {
            return {
                apiUrl: '/ajax/getsalesorder',
                page_no: 5,
                fields: [
                  {
                    name: '__sequence',
                    title: '#',
                    titleClass: 'center aligned',
                    dataClass: 'center aligned'
                  },
                  {
                    name: 'name',
                    title: 'Name',
                    sortField: 'name',
                    direction: 'asc'
                  },
                  {
                    name: 'payment_type',
                    title: 'Payment Method',
                    sortField: 'payment_type',
                  },
                  {
                    name: 'payment_bank_file',
                    title: 'Payment Bank File',
                    sortField: 'payment_bank_file',
                    callback: 'linkLabel'
                  },
                  {
                    name: 'total_amount',
                    title: 'Paid Amount',
                    sortField: 'total_amount',
                    direction: 'asc'
                  },
                  {
                    name: 'status',
                    title: 'Order Status',
                    sortField: 'status',
                    direction: 'asc'
                  },
                  {
                    name: 'created_by',
                    title: 'Created By',
                    sortField: 'created_by.name',
                  },
                  {
                    name: 'created_at',
                    title: 'Created At',
                    sortField: 'created_at',
                  },
                  {
                    name: '__slot:actions',   // <----
                    title: 'Action',
                    titleClass: 'center aligned',
                    dataClass: 'center aligned'
                  }
                ],
            }
        },
        props: ['is_admin'],
        methods : {
          init () {
            var $vm = this;
          },
        },
        mounted() {
            this.init();
            console.log('Page distributor mounted.')
        }
    }
</script>

Myvuetable.vue

<template>
  <div class="table no-margin">
    <filter-bar></filter-bar>
    <div class="vue-table-wrapper">
        <div class="vue-table-loading"><div class="loader"></div></div>
        <vuetable ref="vuetable" 
          :api-url="apiUrl" 
          :fields="fields" 
          :per-page="20" 
          :css="css" 
          :append-params="appendParams"
          :query-params="{page: 'page_no'}"
          pagination-path="" 
          @vuetable:loading="onLoadingData"
          @vuetable:load-success="onLoadSuccess"
          @vuetable:pagination-data="onPaginationData" 
          @vuetable:checkbox-toggled-all="onCheckboxToggledAll"
          @vuetable:checkbox-toggled="onCheckboxToggled"
        > 
          <template slot="actions" slot-scope="props">
              <router-link v-if="actionsBtnVisibility(props.rowData.actions, 'view')" :to="{ path: props.rowData.actions.view}">
                  <i class="fa fa-search-plus"></i>
              </router-link>
              <router-link v-if="actionsBtnVisibility(props.rowData.actions, 'edit')" :to="{ path: props.rowData.actions.edit}" title="Cloak User">
                  <i class="fa fa-edit"></i>
              </router-link>
              <a v-if="actionsBtnVisibility(props.rowData.actions, 'download')" :href="props.rowData.actions.download"><i class="fa fa-download"></i></a>

              <a v-if="actionsBtnVisibility(props.rowData.actions, 'download_order')" :href="props.rowData.actions.download_order" target="_blank"><i class="fa fa-download"></i></a>

              <a v-if="actionsBtnVisibility(props.rowData.actions, 'download_attachment')" :href="props.rowData.actions.download_attachment" download><i class="fa fa-paperclip"></i></a>

              <a v-if="actionsBtnVisibility(props.rowData.actions, 'popup')" @click="popup(props.rowData.actions.popup)" style="cursor: pointer;">Update</a>

              <a v-if="actionsBtnVisibility(props.rowData.actions, 'login')" :href="props.rowData.actions.login" style="cursor: pointer;" title="Cloak User"><i class="fa fa-key" aria-hidden="true"></i></a>
          </template>
        </vuetable>
      </div>

    <div class="vuetable-pagination ui basic segment grid">
      <vuetable-pagination-info ref="paginationInfo" 
      ></vuetable-pagination-info>

      <vuetable-pagination-bootstrap ref="pagination" @vuetable-pagination:change-page="onChangePage"
          ></vuetable-pagination-bootstrap>
    </div>

  </div>
</template>
<style scoped>
.vue-table-wrapper {
    position: relative;
}
.vue-table-loading {
    position: absolute;
    background: rgba(0,0,0,0.2);
    width: 100%;
    height: 100%;
}
.loader {
    border: 5px solid #f3f3f3;
    border-top: 5px solid #3498db;
    border-radius: 50%;
    width: 50px;
    height: 50px;
    animation: spin 2s linear infinite;
    margin: 00 auto;
    position: relative;
    top: 50%;
    margin-top: -25px;
}

@keyframes spin {
    0% { transform: rotate(0deg); }
    100% { transform: rotate(360deg); }
}
</style>
<script>

export default {
    data(){
      return {
          css: {
            tableClass: 'ui blue selectable celled stackable attached table',
            loadingClass: 'loading', 
            detailRowClass: 'vuetable-detail-row',
            sortHandleIcon: 'grey sidebar icon',
            ascendingIcon: 'fa fa-sort-asc',
            descendingIcon: 'fa fa-sort-desc'
          },
          sortOrder: [
          ], 
          appendParams: {},
          checkboxes: []
      }
    },
    computed: {
        selectAll: {
            get: function () {
                return this.checkboxes.length === this.$refs.vuetable.tableData.length;
            }
        },
    },
    props: [
        'apiUrl', 'fields', 'vueTableParams', 'page_no'
    ], 
    methods: {
        statusLabel (value){
            if(value == 'Success'){
                return '<span class="label label-success">Success</span>';
            }else{
                return '<span class="label label-danger">Failed</span>';
            }
        },
        activeLabel (value){
            if(value == 'active'){
                return '<span class="label label-success">Active</span>';
            }else{
                return '<span class="label label-danger">Inactive</span>';
            }
        },
        yesnoLabel (value){
            if(value == 1){
                return '<span class="label label-success">Yes</span>';
            }else{
                return '<span class="label label-danger">No</span>';
            }
        },
        approvalLabel (value){
            if(value == 'approved'){
                return '<span class="label label-success">Approved</span>';
            }else if(value == 'processing'){
              return '<span class="label label-warning">Processing</span>';
            }else if(value == 'processed'){
              return '<span class="label label-success">Processed</span>';
            }else if(value == 'rejected'){
              return '<span class="label label-danger">Rejected</span>';
            }else{
                return '<span class="label label-warning">Pending</span>';
            }
        },
        transactionLabel (value){
            if(value == 'processed'){
                return '<span class="label label-success">Processed</span>';
            }else if(value == 'rejected'){
                return '<span class="label label-danger">Rejected</span>';
            }else{
                return '<span class="label label-danger">Pending</span>';
            }
        },
        accountLabel (value){
          if(value == 1){
                    return '<span class="label label-success">Enabled</span>';
                }else{
                    return '<span class="label label-danger">Disabled</span>';
                }
        },
        actionsBtnVisibility(actions, btn){
            if(actions && typeof actions[btn] != 'undefined'){
                return true;
            }
            return false;
        },
        linkLabel(value){
            if(value){
                return '<a href= "'+value+'" target="_blank">File</a>';
            }
            else{
                return '-';
            }
        },
        view_order(value){
            if(value){
                var order = value.split("~");
                return '<a href= "/admin/salesorder/view/'+order[0]+'" target="_blank">'+order[1]+'</a>';
            }
            else{
                return '-';
            }
        },
        popup(id){
            this.$emit('updatestat', id);
        },
        onLoadingData (){
            //console.log('loading');
            $('.vue-table-loading').show();
        },
        onLoadSuccess (){
            $('.vue-table-loading').hide();
            //console.log('loading success');
        },
        onPaginationData (paginationData) {
            this.$refs.pagination.setPaginationData(paginationData) 
            this.$refs.paginationInfo.setPaginationData(paginationData) 
        },
        onChangePage (page) {
            this.$refs.vuetable.changePage(page) 
        },
        onFilterSet (filterText) {

            if(typeof this.vueTableParams != 'undefined'){
                this.vueTableParams.filter = filterText;
                this.appendParams = this.vueTableParams
            }else{
                this.appendParams = { filter:filterText  }
            }

            var $vm = this;
            Vue.nextTick( () => $vm.$refs.vuetable.refresh())
        },
        onFilterParams (){
            this.appendParams = this.vueTableParams
            var $vm = this;
            Vue.nextTick( () => $vm.$refs.vuetable.refresh())
        },
        onFilterReset () {
            if(typeof this.vueTableParams != 'undefined'){
                this.vueTableParams.filter = '';
                this.appendParams = this.vueTableParams
            }else{
                this.appendParams = {}
            }

            var $vm = this;
            Vue.nextTick( () => $vm.$refs.vuetable.refresh())
        },
        onCheckboxToggledAll(isChecked){
            this.checkboxes = this.$refs.vuetable.selectedTo;
            this.$emit('update:selected', this.checkboxes)
        },
        onCheckboxToggled(isChecked){
            this.checkboxes = this.$refs.vuetable.selectedTo;
            this.$emit('update:selected', this.checkboxes)
        }
    },
    mounted() {
        this.$events.$on('filter-params', eventData => this.onFilterParams(eventData))
        this.$events.$on('filter-set', eventData => this.onFilterSet(eventData))
        this.$events.$on('filter-reset', e => this.onFilterReset())
    }
}
</script>

Solution

  • I have found the solution which is using local storage in vue.

    In myvuetable.vue

    onLoadingData (){
        if (window.location.href.indexOf("admin/sales_order") > -1) {
            if(Vue.localStorage.get('sales_order_admin_page')){
                this.$refs.vuetable.currentPage = Vue.localStorage.get('sales_order_admin_page');
            }
        }
    }
    

    In route.js

    import VueLocalStorage from 'vue-localstorage'
    Vue.use(VueLocalStorage)
    
    Vue.use(VueLocalStorage, {
      name: 'ls',
      bind: true //created computed members from your variable declarations
    })
    
    Vue.localStorage.remove('sales_order_admin_page')
    

    So when onload all the component I simply remove the local storage data first then whenever there is a page change then it will store the page in local storage. It will detect the url first then only update the page in vuetable. If the user didn't click refresh then it won't re-run all the component which means the route.js also won't reload so the local storage data remain.