1

Actually I'm going to implement a tree view, where the user should have the option to reorder the structure with drag and drop. Actually I can't figure out how to enable drag and drop. I found a lot of examples using the 'treeviewdragdrop' plugin, which is just working with the classic toolkit.

The following Code made me move the first node but not more.

this.toParentSource = new Ext.drag.Source({
                element: this.getView().element.down('.x-gridcell'),
                constrain: {
                    element: this.getView().body,
                    vertical: true
                }
            });

Can you help me with this problem? I'm using ExtJS 6.5.2 modern toolkit.

4

1 回答 1

1

This is how I enabled drag and drop for trees in modern Ext JS:

First I've written a plugin which creates the sources that should be draggable.

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

Next I used this plugin inside my tree.

Tree

xtype: 'tree',
    hideHeaders: true,

    plugins: {
        treedrag: {
            type: 'treedrag',
            listeners: {
                beforedragstart: function (plugin, info) {
                    // logic to identify the root and prevent it from being moved
                    console.log('listeners: beforedragstart');
                }
            }
        }
    },
    columns: [{
            xtype: 'treecolumn',
            flex: 1,
        }
    ]

Then I defined the drop targets inside the controller.

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,
                beforeDrop: me.onBeforeDrop
            }
        });
    });
},

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

onBeforeDrop: function (target, info, eOpts) {
    var source = info.record,
        row = Ext.Component.from(target.getElement(), tree),
        destination = row.getRecord();
    // prevent the user to drop the node on itself
    // this would lead to an error caused by recursive method calls 
    if (source == destination) {
        return false;
    }
    // prevent the user to drop a node on it's children
    // this would lead to an error caused by recursive method calls
    if (source.findChild('number', destination.get('number'), true) != null) {
        return false;
    }

    return true;
}
于 2018-08-09T05:28:11.290 回答