Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Issue with update content data in handsontable

I'm trying to implement handsontable. As per my requirement, I want to re-render handsontable from changing a dropdown value, but on dropdown selection, the handsontable does not update properly. Below is my code:

Handsontable.vue:

<template>
  <div id="hot-preview">
    <HotTable :settings="settings" :ref="referenceId"></HotTable>
    <div></div>
  </div>
</template>

<script>
import { HotTable } from '@handsontable-pro/vue';

export default {
  components: {
    HotTable
  },
  props: ['settings', 'referenceId'],
}
</script>

<style>
#hot-preview {
  max-width: 1050px;
  height: 400px;
  overflow: hidden;
}
</style>

Parent component:

<template>
  <div id="provisioning-app">
    <v-container grid-list-xl fluid>
      <v-select
          :items="selectList"
          item-text="elementName"
          item-value="elementName"
          label="Standard"
          v-model="selected"></v-select>
        <handsontable :settings.sync="settings" :referenceId="referenceId"></handsontable>
     </v-container>
  </div>
</template>

<script>
import Handsontable from '@/components/Handsontable';
import PrevisioningService from '@/services/api/PrevisioningService';

export default {
  components: {
    Handsontable
  },
  data: () => ({
    selectList: [],
    selectApp: [],
    selectedOption: '',
    referenceId: 'provision-table',
  }),

  created(){
    PrevisioningService.getProvisioningList(this.$session.get('userId'), this.$session.get('customerId')).then(response => {
      this.provisioningList = response;
    });
  },

  beforeUpdate() {
    this.provisioningApp = this.getProvisioningAppList;
  },
  computed: {
    settings () {
      return {
          data: this.getSelectApp,
          colHeaders: ["Data Uploaded on", "Duration in Minutes", "Start Time", "Shift","Description","Next Day Spill Over", "Site Name"],
          columns: [
            {type: 'text'},
            {type: 'text'},
            {type: 'text'},
            {type: 'text'},
            {type: 'text'},
            {type: 'text'},
            {type: 'text'}
          ],
          rowHeaders: true,
          dropdownMenu: true,
          filters: true,
          rowHeaders: true,
          search: true,
          columnSorting: true,
          manualRowMove: true,
          manualColumnMove: true,
          contextMenu: true,
          afterChange: function (change, source) {
            alert("after change");
          },
          beforeUpdate: function (change, source) {
            alert("before update");
          }
        }
    },

    getSelectApp () {
      if(this.selectedOption !== undefined && this.selectedOption !== null && this.selectedOption !== ''){
        PrevisioningService.getProvisioningAppList(this.selectedOption, this.$session.get('userId'), this.$session.get('customerId')).then(response => {
          this.provisioningApp = response;
          return this.provisioningApp;
        });
      }
    }
  },
  method: {
    getSelected () {
      return this.selectedOption;
    }
  }
};
</script>

With the above code, my data is received successfully from the server, but I'm unable to update the data in handsontable, as shown in the following screenshots:

Here how to show Handsontable when No any value selected on drop-down

And 2nd image show how the table looks after change dropdown value

How do I properly render the table after the dropdown selection?

like image 920
Maulik Kakadiya Avatar asked Oct 18 '18 18:10

Maulik Kakadiya


1 Answers

I see two issues:

  • handsontable appears to not handle dynamic settings (see console errors), so settings should not be a computed property. Since the only settings property that needs to be updated is settings.data, that property alone should be mutated (i.e., don't reset the value of settings).

    To address this, move settings into data(), initializing settings.data to null so that it would still be reactive:

    data() {
      settings: {
        data: null,
        colHeaders: [...],
        ...
      }
    },
    computed: {
      // settings() { }  // DELETE THIS
    }
    
  • getSelectApp is a computed property that is incorrectly asynchronous (i.e., in this case, it fetches data and handles the response later). A computed property cannot be asynchronous, so this computed property actually returns undefined. While there is a return call inside the computed property, the return does not set the value of the computed property because it's inside a Promise callback:

    PrevisioningService.getProvisioningAppList(/*...*/).then(response => {
      this.provisioningApp = response;
      return this.provisioningApp; // DOES NOT SET COMPUTED PROPERTY VALUE
    });
    

    Also note the side effect from this.provisioningApp = response. It doesn't seem this.provisionApp is needed in this code in any case, so it should be removed as clean-up.

    It seems the intention of this computed property is to update settings.data based on the value of the selected option. To accomplish that, you would have to use a watcher on selectedOption, which would change settings.data.

    watch: {
      selectedOption(val) {
        PrevisioningService.getProvisioningAppList(/*...*/).then(response => {
          this.settings.data = response;
        });
      }
    },
    

demo

like image 162
tony19 Avatar answered Nov 12 '22 05:11

tony19