Yeah, maybe.
I have to get custom editors working as per [the other thread] then I may replace the Vue component with the standalone HOT component and see how that goes.
I’ve done a small experiment with updating the original data (as per the poster’s comment re: Vue.set()
) which seems to work, but I’ve not really put it through its paces; for example, I don’t know how HOT will respond with being updated again (if it is).
See the code in the update()
function at the end of this WIP helper:
import Vue from 'vue'
/**
* Helper function to make settings object for HOT table
*
* @param {Vue} vm The Vue object the table is mounted in
* @param {{columns: Array<object>}} settings Additional settings. Expects at least a columns property
* @return {object}
*/
export default function makeSettings (vm, settings = {}) {
const defaults = {
licenseKey: 'non-commercial-and-evaluation',
// layout
width: 'auto',
rowHeight: 32,
rowHeaders: true,
minSpareRows: 1,
// features
selectionMode: 'range',
contextMenu: ['copy', 'cut', '---------', 'remove_row'],
// apply classes from columns
cells (row, col, name) {
return {
className: settings.columns[col].className || ''
}
},
// update cells
afterBeginEditing (row, column) {
const cell = this.getCell(row, column)
const htEditor = this.getActiveEditor()
const editor = htEditor.TEXTAREA
// restyle text editor
if (editor) {
// override editor width
const w = cell.clientWidth
const width = (w - (w % 2 === 0 ? 16 : 16)) + 'px'
editor.style.minWidth = width
editor.style.maxWidth = width
// append cell classes to editor
editor.className = 'handsontableInput htPadded ' + cell.className
}
},
// emit changes
afterChange (changes, source) {
if (source !== 'loadData') {
update(changes)
// changes.forEach(([row, prop, oldValue, newValue]) => {
// console.log(row, prop, oldValue, newValue)
// })
}
},
afterRemoveRow () {
update()
},
}
// mix in settings
settings = {
...defaults,
...settings,
}
// sanity check
if (!settings.columns) {
throw new Error('Parameter "settings" expects a "columns" array of objects')
}
// update function
function update (changes) {
vm.$nextTick(() => {
// grab source data
let data = vm.$refs.table.hotInstance.getSourceData()
if (settings.minSpareRows) {
data = data.slice(0, -settings.minSpareRows)
}
// update existing vue data
vm.data.length = 0
data.forEach(function (row, index) {
Vue.set(vm.data, index, data[index])
})
// tell the world the data has changed
vm.$emit('update', data, changes)
})
}
return settings
}
The refs stuff is pretty kludgy, and feels very un-vue like. Normally, this would be handled using a Vue @event
on the component itself.