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:
How do I properly render the table after the dropdown selection?
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With