0
votes

I'm quite new to Ext JS and I wanted to understand a bit more about how drag and drop works. So I was looking at the article on http://www.codeslower.com/2011/7/Using-the-draggable-property-in-ExtJS. I wrote a JS Fiddle based on this which is at http://jsfiddle.net/F2xsM/ which uses Ext JS 4.0.7 as per the example. If I swap in Ext JS 4.1.0 or later versions (e.g. JS Fiddle - http://jsfiddle.net/HpPhy/ with 4.2.0) the code doesn't work properly. Only the first drag works. After that there's a load of errors in the console.

Here's the code:

Ext.onReady(function() {
    Ext.create('Ext.container.Viewport', {
        layout: 'vbox',
        items: [{
            xtype: 'panel',
            title: 'Drop a Panel Here',
            listeners: { render: initializeDropTarget },
            cls: 'x-dd-drop-ok',
            layout: {
                type: 'vbox',
                stretch: 'align'
            },
            width: 300,
            height: 300
        }, {
            xtype: 'panel',
            title: 'Drag This Panel',
            draggable: true,
            bodyCls: 'green-body',
            width: 300,
            height: 100
        }, {
            xtype: 'panel',
            title: 'Drag This Panel',
            draggable: true,
            bodyCls: 'blue-body',
            width: 300,
            height: 100
        }, {
            xtype: 'panel',
            title: 'Drag This Panel',
            draggable: true,
            bodyCls: 'red-body',
            width: 300,
            height: 100
        }]
    });
});

/**
 Initialize the DropTarget object associated
 with our panel. The 'cmp' argument will be
 the panel (a Component object).
 */
function initializeDropTarget(targetPanel) {
    // Create the DropTarget object and assign it to the panel. Does not
    // have to be assigned to the panel but needs to be assigned to something,
    // or it will get garbage-collected too soon.
    targetPanel.dropTarget = Ext.create('Ext.dd.DropTarget', targetPanel.el);

    // Called once, when dragged item is dropped in the target area. Return false
    // to indicate an invalid drop. DO NOT MODIFY the UI in
    // this function. Use afterDragDrop and the data object.
    targetPanel.dropTarget.notifyDrop = function(source, evt, data) {
        if(typeof console != "undefined")
            console.log("notifyDrop:" + source.id);

        // The component that was dropped.
        var droppedPanel = Ext.getCmp(source.id);

        // We can't modify the component that was dropped in this
        // function. However, we can add an event handler on the component
        // that will be called shortly.
        //
        // In the handler we clone the component (not strictly necessary, we could
        // do that here) and then remove our old component.
        droppedPanel.dd.afterValidDrop = function() {
            targetPanel.add(droppedPanel.cloneConfig({
                draggable: false,
                title: "Can't Drag This Panel."
            }));

            droppedPanel.destroy();
        };

        return true;
    };

    // Called once, when dragged item enters drop area.
    targetPanel.dropTarget.notifyEnter = function(source, evt, data) {
        if(typeof console != "undefined")
            console.log("notifyEnter:" + source.id);

        return this.callParent(Array.prototype.slice.call(arguments));
    };

    // Called once, when dragged item leaves drop area.
    targetPanel.dropTarget.notifyOut = function(source, evt, data) {
        if(typeof console != "undefined")
            console.log("notifyOut:" + source.id);

        return this.callParent(Array.prototype.slice.call(arguments));
    };

    // Called for each mouse movement as dragged item is over the drop area.
    targetPanel.dropTarget.notifyOver = function(source, evt, data) {
        if(typeof console != "undefined")
            console.log("notifyOver:" + source.id);

        return this.callParent(Array.prototype.slice.call(arguments));
    };
}

What do I need to change to fix this?


Update: I can see it's go tosmething to do with the ghost element and the line droppedPanel.destroy();

1

1 Answers

0
votes

Dropped panel is apparently used somewhere after notifyDrop (you can see in stack trace stopDrag method when exception is thrown).

Easiest way to fix that is to delay destroy call or use endDrag callback:

droppedPanel.dd.endDrag = function() {
    droppedPanel.destroy();
};

Working sample: http://jsfiddle.net/HpPhy/4/