Handsontable example

HTML

<script src="https://cdn.jsdelivr.net/npm/handsontable@latest/dist/handsontable.full.min.js"></script>
<link type="text/css" rel="stylesheet" href="https://cdn.jsdelivr.net/npm/handsontable@latest/dist/handsontable.full.min.css">

<div id="example"></div>

JavaScript

/**
 * The cell type adds supports for displaing the label value except the key in the key-value
 * dropdown editor type.
 */
class KeyValueListEditor extends Handsontable.editors.HandsontableEditor {
  prepare(row, col, prop, td, value, cellProperties) {
    super.prepare(row, col, prop, td, value, cellProperties);
    
    const tdWidth = td.offsetWidth

    Object.assign(this.htOptions, {
      licenseKey: 'non-commercial-and-evaluation',
      data: this.cellProperties.source,
      columns: [
        {
          data: '_name',
        },
        {
          data: 'label',
        },
      ],
      hiddenColumns: {
        columns: [1],
      },
      colWidths: tdWidth, // This line ensures that the dropdown stretches to match the width of the table cell.
      beforeValueRender(value, { row, instance }) {
        return instance.getDataAtRowProp(row, 'label');
      },
    });

    if (cellProperties.keyValueListCells) {
      this.htOptions.cells = cellProperties.keyValueListCells;
    }
  }
  
  setValue(value) {
  	// Fix to display the title instead of the ID in the cell.
  
     setTimeout(() => {
      const index = this.htEditor?.getDataAtProp('_name').findIndex((id) => +id === +value)
      value = this.htEditor.getDataAtRowProp(index, 'label')
      this.TEXTAREA.value = value
    }, 0)
    
    if (this.htEditor) {
      const index = this.htEditor.getDataAtProp('_name').findIndex(name => name === value);

      if (index !== -1) {
        value = this.htEditor.getDataAtRowProp(index, 'label');
      }
    }
    super.setValue(value);
  }
  
  getValue() {
    const value = super.getValue();

    if (this.htEditor) {
      const labels = this.htEditor.getDataAtProp('label');
      const row = labels.indexOf(value);

      if (row !== -1) {
        return this.htEditor.getDataAtRowProp(row, '_name');
      }
    }

    return value;
  }
}

const keyValueListValidator = function(value, callback) {
  let valueToValidate = value;

  if...