当前位置: 首页 > 工具软件 > Handsontable > 使用案例 >

handsontable+vue+ 自定义多选

盖嘉庆
2023-12-01
js
export let customDropdownRenderer = (instance, td, row, col, prop, value, cellProperties) => {
  // let selectedId
  // console.log('答应optionsList', instance, td, row, col, prop, value, cellProperties)
  let optionsList = cellProperties.chosenOptions.data
  if (typeof optionsList === 'undefined' || typeof optionsList.length === 'undefined' || !optionsList.length) {
    Handsontable.cellTypes.text.renderer(instance, td, row, col, prop, value, cellProperties)
    return td
  }
  //
  let values = (value + '').split(',')
  value = []
  for (var index = 0; index < optionsList.length; index++) {
    if (values.indexOf(optionsList[index].id + '') > -1) {
      // selectedId = optionsList[index].id
      value.push(optionsList[index].label)
    }
  }
  value = value.join(', ')

  Handsontable.cellTypes.text.renderer(instance, td, row, col, prop, value, cellProperties)
  // td.innerText = values
  return td
}


<hot-table :settings="hotSettings" :data="hotData" ref="table">
</hot-table>


 class Myselect extends TextEditor {
  // const CustomEditor = Handsontable.editors.BaseEditor.prototype.extend()

  // ...rest of the editor code
  // console.log('触发')

  // eslint-disable-next-line no-useless-constructor
  constructor (props) {
    super(props)
  }
  // let MySelectEditor = Handsontable.editors.TextEditor.prototype.extend()

  prepare (row, col, prop, td, originalValue, cellProperties) {
    super.prepare(row, col, prop, td, originalValue, cellProperties)
    this.options = {}
     console.log('答应prepare', originalValue)
    if (this.cellProperties.chosenOptions) {
      this.options = $.extend(this.options, cellProperties.chosenOptions)
    }
    this.originalValue = originalValue
    cellProperties.chosenOptions = $.extend({}, cellProperties.chosenOptions)
  }
  createElements () {
    let $ = window.$
    super.createElements()
    // this.$body = $(document.body)

    this.TEXTAREA = document.createElement('select')

    // Handsontable copy paste plugin calls this.TEXTAREA.select()
    this.TEXTAREA.select = function () { }

    // this.TEXTAREA.setAttribute('type', 'text');
    this.$textarea = $(this.TEXTAREA)

    Handsontable.dom.addClass(this.TEXTAREA, 'handsontableInput')

    this.textareaStyle = this.TEXTAREA.style
    this.textareaStyle.width = 0
    this.textareaStyle.height = 0

    this.TEXTAREA_PARENT = document.createElement('DIV')
    Handsontable.dom.addClass(this.TEXTAREA_PARENT, 'handsontableInputHolder')

    this.textareaParentStyle = this.TEXTAREA_PARENT.style
    this.textareaParentStyle.top = 0
    this.textareaParentStyle.left = 0
    this.textareaParentStyle.display = 'none'
    this.textareaParentStyle.width = '200px'

    this.TEXTAREA_PARENT.appendChild(this.TEXTAREA)

    this.instance.rootElement.appendChild(this.TEXTAREA_PARENT)

    let that = this
    this.instance._registerTimeout(setTimeout(function () {
      that.refreshDimensions()
    }, 0))
  }

  onChosenChanged () {
    let options = this.cellProperties.chosenOptions

    if (!options.multiple) {
      this.close()
      this.finishEditing()
    }
  }
  onChosenClosed () {
    let options = this.cellProperties.chosenOptions

    if (!options.multiple) {
      this.close()
      this.finishEditing()
    } else {
    }
  }
  onBeforeKeyDown (event) {
    let instance = this
    let that = instance.getActiveEditor()

    let keyCodes = Handsontable.helper.KEY_CODES
    let ctrlDown = (event.ctrlKey || event.metaKey) && !event.altKey // catch CTRL but not right ALT (which in some systems triggers ALT+CTRL)

    // Process only events that have been fired in the editor
    if (event.target.tagName !== 'INPUT') {
      return
    }
    if (event.keyCode === 17 || event.keyCode === 224 || event.keyCode === 91 || event.keyCode === 93) {
      // when CTRL or its equivalent is pressed and cell is edited, don't prepare selectable text in textarea
      event.stopImmediatePropagation()
      return
    }

    let target = event.target

    switch (event.keyCode) {
      case keyCodes.ARROW_RIGHT:
        if (Handsontable.dom.getCaretPosition(target) !== target.value.length) {
          event.stopImmediatePropagation()
        } else {
          that.$textarea.trigger('chosen:close')
        }
        break

      case keyCodes.ARROW_LEFT:
        if (Handsontable.dom.getCaretPosition(target) !== 0) {
          event.stopImmediatePropagation()
        } else {
          that.$textarea.trigger('chosen:close')
        }
        break

      case keyCodes.ENTER:
        if (that.cellProperties.chosenOptions.multiple) {
          event.stopImmediatePropagation()
          event.preventDefault()
          event.stopPropagation()
        }

        break

      case keyCodes.A:
      case keyCodes.X:
      case keyCodes.C:
      case keyCodes.V:
        if (ctrlDown) {
          event.stopImmediatePropagation() // CTRL+A, CTRL+C, CTRL+V, CTRL+X should only work locally when cell is edited (not in table context)
        }
        break

      case keyCodes.BACKSPACE:
        let txt = $(that.TEXTAREA_PARENT).find('input').val()
        $(that.TEXTAREA_PARENT).find('input').val(txt.substr(0, txt.length - 1)).trigger('keyup.chosen')

        event.stopImmediatePropagation()
        break
      case keyCodes.DELETE:
      case keyCodes.HOME:
      case keyCodes.END:
        event.stopImmediatePropagation() // backspace, delete, home, end should only work locally when cell is edited (not in table context)
        break
    }
  }
  open (keyboardEvent) {
    this.refreshDimensions()
    this.textareaParentStyle.display = 'block'
    this.instance.addHook('beforeKeyDown', this.onBeforeKeyDown)

    this.$textarea.css({
      height: $(this.TD).height() + 4,
      'min-width': $(this.TD).outerWidth() - 4
    })

    // display the list
    this.$textarea.hide()

    // make sure that list positions matches cell position
    // this.$textarea.offset($(this.TD).offset());

    let options = $.extend({}, this.options, {
      width: '100%',
      search_contains: true
    })

    if (options.multiple) {
      this.$textarea.attr('multiple', true)
    } else {
      this.$textarea.attr('multiple', false)
    }

    this.$textarea.empty()
    this.$textarea.append("<option value=''></option>")
    let el = null
    let originalValue = (this.originalValue + '').split(',')
    if (options.data && options.data.length) {
      for (let i = 0; i < options.data.length; i++) {
        el = $('<option />')
        el.attr('value', options.data[i].id)
        el.html(options.data[i].label)

        if (originalValue.indexOf(options.data[i].id + '') > -1) {
          el.attr('selected', true)
        }

        this.$textarea.append(el)
      }
    }

    if ($(this.TEXTAREA_PARENT).find('.chosen-container').length) {
      this.$textarea.chosen('destroy')
    }
    // console.log('thishtishthsi', this)
    this.$textarea.chosen(options)

    let self = this
    setTimeout(function () {
      self.$textarea.on('change', this.onChosenChanged.bind(self))
      self.$textarea.on('chosen:hiding_dropdown', this.onChosenClosed.bind(self))

      self.$textarea.trigger('chosen:open')

      $(self.TEXTAREA_PARENT).find('input').on('keydown', function (e) {
        if (e.keyCode === Handsontable.helper.KEY_CODES.ENTER /* || e.keyCode === Handsontable.helper.KEY_CODES.BACKSPACE */) {
          if ($(this).val()) {
            e.preventDefault()
            e.stopPropagation()
          } else {
            e.preventDefault()
            e.stopPropagation()

            self.close()
            self.finishEditing()
          }
        }

        if (e.keyCode === Handsontable.helper.KEY_CODES.BACKSPACE) {
          let txt = $(self.TEXTAREA_PARENT).find('input').val()

          $(self.TEXTAREA_PARENT).find('input').val(txt.substr(0, txt.length - 1)).trigger('keyup.chosen')

          e.preventDefault()
          e.stopPropagation()
        }

        if (e.keyCode === Handsontable.helper.KEY_CODES.ARROW_DOWN || e.keyCode === Handsontable.helper.KEY_CODES.ARROW_UP) {
          e.preventDefault()
          e.stopPropagation()
        }
      })

      setTimeout(function () {
        self.$textarea.trigger('chosen:activate').focus()

        if (keyboardEvent && keyboardEvent.keyCode && Number(keyboardEvent.keyCode) !== 113) {
          let key = keyboardEvent.keyCode
          let keyText = (String.fromCharCode((key >= 96 && key <= 105) ? key - 48 : key)).toLowerCase()

          $(self.TEXTAREA_PARENT).find('input').val(keyText).trigger('keyup.chosen')
          self.$textarea.trigger('chosen:activate')
        }
      }, 1)
    }, 1)
  }

  init () {
    Handsontable.editors.TextEditor.prototype.init.apply(this, arguments)
  }

  close () {
    this.instance.listen()
    this.instance.removeHook('beforeKeyDown', this.onBeforeKeyDown)
    this.$textarea.off()
    this.$textarea.hide()
    Handsontable.editors.TextEditor.prototype.close.apply(this, arguments)
  }

  getValue () {
    if (!this.$textarea.val()) {
      return ''
    }
    if (typeof this.$textarea.val() === 'object') {
      return this.$textarea.val().join(',')
    }
    return this.$textarea.val()
  }
   // setValue(value) {
   //  console.log('答应setValue', value)
   //   this.select.value = value;
   // }
  focus () {
    this.instance.listen()

    // DO NOT CALL THE BASE TEXTEDITOR FOCUS METHOD HERE, IT CAN MAKE THIS EDITOR BEHAVE POORLY AND HAS NO PURPOSE WITHIN THE CONTEXT OF THIS EDITOR
    // Handsontable.editors.TextEditor.prototype.focus.apply(this, arguments);
  }

  beginEditing (initialValue) {
    let onBeginEditing = this.instance.getSettings().onBeginEditing
    if (onBeginEditing && onBeginEditing() === false) {
      return
    }

    Handsontable.editors.TextEditor.prototype.beginEditing.apply(this, arguments)
  }

  finishEditing (isCancelled, ctrlDown) {
    this.instance.listen()
    return Handsontable.editors.TextEditor.prototype.finishEditing.apply(this, arguments)
  }
}
{
  tittle: '媒介',
  editor: Myselect,
  data:'fdMediaIds',
  renderer: customDropdownRenderer,
  chosenOptions: {
    multiple: true,
    data: [
      {
        id: '1',
        label: 'NNN'
      }, {
        id: '2',
        label: 'YYY'
      }, {
        id: '3',
        label: 'QQQ'
      }, {
        id: '4',
        label: 'TTT'
      }
    ]
  },
  width: 150
}




 代码不全 但是关键配置都在这里 需要的话可以看官方文档补全

通过修改里面的一些配置

Cell editor - Guide - Handsontable Documentation

关键的api 有
this.$refs.table.hotInstance.loadData(this.hotData) // 更新数据

let index = this.$refs.table.hotInstance.getDataAtRow(i) // 获取 行数据
this.hotSettings.columns[11].source = res.data.data
this.$refs.table.hotInstance.updateSettings(this.hotSettings) // 更新setting

上面大部分覆盖了大部分场景 定制需求的话需要理解render和edit的写法 会稍微复杂点

 类似资料: