Handsontable Angular - Cell Editor

时间:2017-07-19 18:44:31

标签: angular handsontable

我一直在阅读Handsontable for Cell Editors的文档,但我似乎无法正确创建自定义单元格编辑器。

我正在引用Select2 for Handsontable并将此脚本添加到angular-cli中,但没有运气。任何人都知道如何使这项工作?

jsfiddle的代码是:

(function (Handsontable) {
    "use strict";

    var Select2Editor = Handsontable.editors.TextEditor.prototype.extend();

    Select2Editor.prototype.prepare = function (row, col, prop, td, originalValue, cellProperties) {

        Handsontable.editors.TextEditor.prototype.prepare.apply(this, arguments);

        this.options = {};

        if (this.cellProperties.select2Options) {
            this.options = $.extend(this.options, cellProperties.select2Options);
        }
    };

    Select2Editor.prototype.createElements = function () {
        this.$body = $(document.body);

        this.TEXTAREA = document.createElement('input');
        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.TEXTAREA_PARENT.appendChild(this.TEXTAREA);

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

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

    var onSelect2Changed = function () {
        this.close();
        this.finishEditing();
    };
    var onSelect2Closed = function () {
        this.close();
        this.finishEditing();
    };
    var onBeforeKeyDown = function (event) {
        var instance = this;
        var that = instance.getActiveEditor();

        var keyCodes = Handsontable.helper.keyCode;
        var 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).hasClass('select2-input') || event.isImmediatePropagationStopped()) {
            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;
        }

        var target = event.target;

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

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

            case keyCodes.ENTER:
                var selected = that.instance.getSelected();
                var isMultipleSelection = !(selected[0] === selected[2] && selected[1] === selected[3]);
                if ((ctrlDown && !isMultipleSelection) || event.altKey) { //if ctrl+enter or alt+enter, add new line
                    if (that.isOpened()) {
                        that.val(that.val() + '\n');
                        that.focus();
                    } else {
                        that.beginEditing(that.originalValue + '\n')
                    }
                    event.stopImmediatePropagation();
                }
                event.preventDefault(); //don't add newline to field
                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:
            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;
        }

    };

    Select2Editor.prototype.open = function () {
        this.refreshDimensions();
        this.textareaParentStyle.display = 'block';
        this.instance.addHook('beforeKeyDown', onBeforeKeyDown);

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

        //display the list
        this.$textarea.show();

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

        var self = this;
        this.$textarea.select2(this.options)
            .on('change', onSelect2Changed.bind(this))
            .on('select2-close', onSelect2Closed.bind(this));

        self.$textarea.select2('open');
    };

    Select2Editor.prototype.init = function () {
        Handsontable.editors.TextEditor.prototype.init.apply(this, arguments);
    };

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

    Select2Editor.prototype.val = function (value) {
        if (typeof value == 'undefined') {
            return this.$textarea.val();
        } else {
            this.$textarea.val(value);
        }
    };


    Select2Editor.prototype.focus = function () {

        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);
    };

    Select2Editor.prototype.beginEditing = function (initialValue) {
        var onBeginEditing = this.instance.getSettings().onBeginEditing;
        if (onBeginEditing && onBeginEditing() === false) {
            return;
        }

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

    };

    Select2Editor.prototype.finishEditing = function (isCancelled, ctrlDown) {
        this.instance.listen();
        return Handsontable.editors.TextEditor.prototype.finishEditing.apply(this, arguments);
    };

    Handsontable.editors.Select2Editor = Select2Editor;
    Handsontable.editors.registerEditor('select2', Select2Editor);

})(Handsontable);

我也在使用ng2-handsontable组件,我想知道这是否会导致更多问题?

2 个答案:

答案 0 :(得分:0)

我能够让select2在大多数情况下工作。

import * as Handsontable from 'handsontable';

export const Select2Editor = Handsontable.editors.TextEditor.prototype.extend();

Select2Editor.prototype.prepare = function (row, col, prop, td, originalValue, cellProperties) {

    Handsontable.editors.TextEditor.prototype.prepare.apply(this, arguments);

    this.options = {};

    if (this.cellProperties.select2Options) {

        this.options = $.extend(this.options, cellProperties.select2Options);
    }
};

Select2Editor.prototype.createElements = function () {
    this.$body = $(document.body);

    this.TEXTAREA = document.createElement('select');
    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.TEXTAREA_PARENT.appendChild(this.TEXTAREA);

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

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

var onSelect2Changed = function (e) {
    //console.log(e);
    console.log(this.$textarea.val());
    // this.close();
    // this.finishEditing();
};
var onSelect2Closed = function () {
    this.close();
    this.finishEditing();
};
var onBeforeKeyDown = function (event) {
    var instance = this;
    var that = instance.getActiveEditor();

    var keyCodes = (<any>Handsontable.helper).keyCode;
    var 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).hasClass('select2-input') || event.isImmediatePropagationStopped()) {
        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;
    }

    var target = event.target;

    switch (event.keyCode) {
        case keyCodes.ARROW_RIGHT:
            if ((<any>Handsontable.Dom).getCaretPosition(target) !== target.value.length) {
                event.stopImmediatePropagation();
            } else {
                that.$textarea.select2('close');
            }
            break;

        case keyCodes.ARROW_LEFT:
            if ((<any>Handsontable.Dom).getCaretPosition(target) !== 0) {
                event.stopImmediatePropagation();
            } else {
                that.$textarea.select2('close');
            }
            break;

        case keyCodes.ENTER:
            var selected = that.instance.getSelected();
            var isMultipleSelection = !(selected[0] === selected[2] && selected[1] === selected[3]);
            if ((ctrlDown && !isMultipleSelection) || event.altKey) { //if ctrl+enter or alt+enter, add new line
                if (that.isOpened()) {
                    that.val(that.val() + '\n');
                    that.focus();
                } else {
                    that.beginEditing(that.originalValue + '\n')
                }
                event.stopImmediatePropagation();
            }
            event.preventDefault(); //don't add newline to field
            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:
        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;
    }

};

Select2Editor.prototype.open = function () {
    this.refreshDimensions();
    this.textareaParentStyle.display = 'block';
    this.instance.addHook('beforeKeyDown', onBeforeKeyDown);

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

    //display the list
    this.$textarea.show();

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

    var self = this;
    this.$textarea.select2(this.options)
        .on('change', onSelect2Changed.bind(this))
        .on('select2-close', onSelect2Closed.bind(this));

    self.$textarea.select2('open');
};

Select2Editor.prototype.init = function () {
    Handsontable.editors.TextEditor.prototype.init.apply(this, arguments);
};

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

Select2Editor.prototype.val = function (value) {
    if (typeof value == 'undefined') {
        return this.$textarea.val();
    } else {
        this.$textarea.val(value);
    }
};

Select2Editor.prototype.getValue = function() {
  return this.$textarea.val();
};

Select2Editor.prototype.setValue = function(value) {
  this.$textarea.val(value);
};

Select2Editor.prototype.focus = function () {

    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);
};

Select2Editor.prototype.beginEditing = function (initialValue) {
    var onBeginEditing = this.instance.getSettings().onBeginEditing;
    if (onBeginEditing && onBeginEditing() === false) {
        return;
    }

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

};

Select2Editor.prototype.finishEditing = function (isCancelled, ctrlDown) {
    this.instance.listen();
    return Handsontable.editors.TextEditor.prototype.finishEditing.apply(this, arguments);
};

答案 1 :(得分:0)

我正在vue js的Handsontable表中实现select2编辑器解决方案,并出现错误

“未捕获的TypeError:无法读取t.Select2Editor.createElements处未定义的属性'addClass'”

经过一番努力,我可以通过对原始文件https://github.com/trebuchetty/Handsontable-select2-editor/blob/master/select2-editor.js的select2 plugin.js代码进行少量更改来解决问题。

解决方案:

更改

   "Handsontable.Dom" to "Handsontable.dom" in select2 plugin.js

并且select2插件将起作用。