ExtJS Maximum call stack size exceeded when reordering tree

岁酱吖の 提交于 2019-12-24 16:23:02

问题


I'm reordering the hierarchy of a tree with drag and drop. After moving multiple nodes I get the error Uncaught RangeError: Maximum call stack size exceeded. The error appears in NodeInterface.js. The updateInfo function crashes in the following line

for (i = 0; i < childCount; i++) { children[i].updateInfo(commit, childInfo); }

What could cause this problem?

The following code shows how I implemnted the drag and drop and reordering in ExtJS 6.5.2. Maybe you can find what's causing the problem.

Plugin

Ext.define('test.component.plugin.TreeDragger', {
extend: 'Ext.AbstractPlugin',
alias: 'plugin.treedrag',

mixins: ['Ext.mixin.Observable'],

constructor: function (config) {
    this.mixins.observable.constructor.call(this, config);
},

init: function (component) {
    var me = this;

    this.source = new Ext.drag.Source({
        element: component.element,
        handle: '.x-gridrow',
        constrain: {
            element: true,
            vertical: true
        },
        describe: function (info) {
            var row = Ext.Component.from(info.eventTarget, component);
            info.row = row;
            info.record = row.getRecord();
        },
        proxy: {
            type: 'placeholder',
            getElement: function (info) {
                console.log('proxy: getElement');                    

                var el = Ext.getBody().createChild({
                    style: 'padding: 10px; width: 100px; border: 1px solid gray; color: red;',
                });
                el.show().update(info.record.get('description'));
                return el;
            }
        },
        // autoDestroy: false,
        listeners: {
            scope: me,
            beforedragstart: me.makeRelayer('beforedragstart'),
            dragstart: me.makeRelayer('dragstart'),
            dragmove: me.makeRelayer('dragmove'),
            dragend: me.makeRelayer('dragend')
        }
    });
},

disable: function () {
    this.source.disable();
},

enable: function () {
    this.source.enable();
},

doDestroy: function () {
    Ext.destroy(this.source);
    this.callParent();
},

makeRelayer: function (name) {
    var me = this;
    return function (source, info) {
        return me.fireEvent(name, me, info);
    };
}
});

Tree

xtype: 'tree',
    hideHeaders: true,

    plugins: {
        treedrag: {
            type: 'treedrag',
            listeners: {
                beforedragstart: function (plugin, info) {
                    console.log('listeners: beforedragstart');
                }
            }
        }
    },
    columns: [{
            xtype: 'treecolumn',
            flex: 1,
        }
    ]

Controller

afterLoadApportionmentObjectsForTree: function (succes) {
    if (succes) {

        tree = this.getView().down('tree');
        if (tree) {
            tree.expandAll();
            tree.updateHideHeaders(tree.getHideHeaders());
            var store = tree.getStore();
            store.remoteFilter = false;
            store.filterer = 'bottomup';

            this.createDropTargets();
        }
    }
},

createDropTargets: function () {
    var me = this,
        rows = tree.innerItems;
    Ext.each(rows, function (el) {
        var target = new Ext.drag.Target({
            element: el.element,
            listeners: {
                scope: me,
                drop: me.onDrop
            }
        });
    });
},

onDrop: function (target, info, eOpts) {
    var source = info.record,
        row = Ext.Component.from(target.getElement(), tree),
        destination = row.getRecord(),
        parentNode = source.parentNode;

    destination.appendChild(source);
    destination.expand();

    if (!parentNode.hasChildNodes()) {
        parentNode.set('leaf', true);
    }
}

Edit

It seems that updateInfo is called recursive, but I can't figure out why or how I could prevent it.


回答1:


I could find the mistake by myself. It was possible to drag nodes on their own children which relates to an recursive adding and removing of the same nodes over and over again. To prevent the user from doing this, I added an listener for the beforeDrop event to my Ext.drag.Target. There it returns false, if the target node is the same as the source node and it returns false if the target node is a child node of the source node.

 onBeforeDrop: function (target, info, eOpts) {
    var source = info.record,
        row = Ext.Component.from(target.getElement(), tree),
        destination = row.getRecord();

    if (source == destination) {
        return false;
    }
    if (source.findChild('number', destination.get('number'), true) != null) {
        return false;
    }

    return true;
}

I also used the beforedragstart event to prevent moving the root node.

Maybe this is helpful for someone else.



来源:https://stackoverflow.com/questions/51743538/extjs-maximum-call-stack-size-exceeded-when-reordering-tree

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!