Source data after row > remove > undo is different from data before

Tags: #<Tag:0x00007f8b1d384668>

We’re using object-data for the table, but are finding that data after undoing a row-delete is missing data that was in the data before.

It’s perhaps best shown via a GIF:

Two things to note here:

  1. the hidden stock.id is missing
  2. the visible stock.shortName is missing

I’m worried about these two for different reasons:

  1. we would like to keep the database id of course
  2. the missing visible data is going to be disconcerting for users

Is there something we can do about this?

This topic seem to be related to Vue source data does not seem to be referenced

Have you experienced the following in the Vue application?

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.

Hi again @aleksandra_budnik,

So it seems this undo issue is not related to Vue after all.

Check these two demos on a vanilla HOT; try deleting a row then undoing:

EDIT: actually, it seems that readOnly cells do not update after an undo!

I have updated the array data fiddle to use editor: false:

However, this is an issue for us as we need some of the columns to be read only - or at least not copy / pasteable.

What do you think?

I am wondering if the index mapper will help here. When why to do the same with columns it also breaks the data but in a different way https://github.com/handsontable/handsontable/issues/5000
Now the branch with the mapper is incomplete so I cannot check it, but I’ll ask the developer if while testing he would be able to spot a difference.

I’ve compiled a kind of bugs / discrepancies hit-list for HOT and I think we’re going to work around the problem in this case by:

  1. Using arrays not objects, even if that means using hidden columns, and referencing where needed external data in renderers / editors
  2. Disabling row delete, and instead adding checkbox controls to mark rows for deletion when the user submits

Item #2 actually suits our workflow quite well, as the table of items is designed to be reviewed and edited in several steps by several people.

FWIW I could also share the list with yourselves, as it would probably be interesting from a customer perspective. Also, it would be good to get feedback on that in one hit rather than lots of forum posts :slight_smile:

Talking of customers, we are probably pretty close to making a purchase decision, so I will follow all that up with Natalia!

TTFN,
Dave

I agree in 100% :slight_smile:

Talking of customers, we are probably pretty close to making a purchase decision, so I will follow all that up with Natalia!

I would do my best to help you check if Handsontable meets your requirements before the purchase. But, after having a chance to meet many developers I can say that you are a fast learner! I’d love to see your project as a part of our case studies section.