I have a simple layout consisting of a Ext.tree.Panel
on the left and a Ext.panel.Panel
on the right. The contents of the right-hand panel are intended to be a d3 visualization.
The tree panel is defined as:
Ext.define('MyTreeModel', {
extend: 'Ext.data.Model',
fields: [
{ name: 'id', type: 'string' },
{ name: 'text', type: 'string' },
{ name: 'ddGroup', type: 'string', defaultValue: 'myDropGroup' },
{ name: 'draggable', type: 'boolean', defaultValue: true }
]
});
var myStore = Ext.create('Ext.data.TreeStore', {
model: 'myTreeModel',
autoSync: true,
autoLoad: true,
proxy: {
type: 'ajax',
url: 'myendpoint.json',
reader: { type: 'json' }
}
});
Ext.define('MyTreePanel', {
extend: 'Ext.tree.Panel',
alias: 'widget.mytreepanel',
enableDD: true, // not sure if this is necessary
ddGroup: 'myDropGroup', // "
rootVisible: false,
store: myStore
}
And the panel that should receive the drop events is defined as:
Ext.define('MyDropPanel', {
extend: 'Ext.panel.Panel',
items: [
{
xtype: 'component',
id: 'd3Component',
autoEl: { tag: 'div' }
}
],
ddGroup: 'myDropGroup', // not sure if this is necessary
enableDD: true, // "
listeners: {
render: initializeDropTarget,
afterLayout: buildInitialD3Visualization // here's where the d3 SVG gets set up
}
});
function initializeDropTarget(panel) {
panel.dropTarget = Ext.dd.DropTarget.create(panel.el, {
ddGroup: 'myDropGroup',
notifyDrop: function(dd, e, data) {
console.log("something dropped!"); // so far I have not seen this method fire.
}
});
}
I am new to ExtJS but these are the things I have tried:
treeviewdragdrop
. That allowed dragging and dropping within the tree but did not make and difference on whether my panel received drop events.enableDD
property but that doesn't actually seem to be a defined property on the ExtJS 4 Panel
class. And, it doesn't seem to help so far.I wonder if the existence of a "simple" div (where the visualization is to be displayed) is what's causing the problem?
For Drag and Drop operation in ExtJS you need to configurate drag source and drop target.
The easiest way how to setup tree as dragSource
is by using Ext.tree.plugin.TreeViewDragDrop
plugin. In config of this plugin you should set name of dragGroup
. By this identificator you can bind dragSource
and dropTarget
together.
var tree = Ext.create('Ext.tree.Panel', {
title: 'Simple Tree',
width: 400,
height: 600,
store: store,
rootVisible: false,
viewConfig: {
plugins: {
ptype: 'treeviewdragdrop',
copy: true,
dragGroup: 'myDDGroup'
}
},
});
Then you need to create dropTarget
on your Ext.panel.Panel
. For this you can use Ext.dd.DropTarget
. This class implements some notify methods which you can override and use for handling drag and drop events.
The notifyDrop
method is called when dragged element is dropped on target. If this method returns true
drop is considered as successful.
Because you use as dragSource
treeviewdragdrop
the data
parameter of every notify method also contains array of records which belongs to dragged tree nodes (data.records
).
You can define your own class which extend Ext.dd.DropTarget
:
Ext.define('myPanelDropTarget', {
extend: 'Ext.dd.DropTarget',
notifyEnter : function(source, e, data) {
console.log('enter');
return this.callParent(arguments);
},
notifyOut : function(source, e, data) {
console.log('out');
return this.callParent(arguments);
},
notifyOver : function(source, e, data) {
console.log('over');
return this.callParent(arguments);
},
notifyDrop : function(source, e, data) {
var me = this;
console.log('drop');
var text = data.records[0].get('text');
var d3ComponentEl = me.panel.down('#d3Component').getEl();
d3ComponentEl.insertHtml('beforeEnd', text + '<br />');
return true;
}
});
Finally you can setup your panel as dropTarget
. dropTarget
will be created in afterrender
event handler because you need to bind it to panel DOM element (and this element exists only after panel is rendered). Also you have to configure dropTarget
with same ddGroup
name as you use in treeviewdragdrop
plugin config:
var panel = Ext.create('Ext.panel.Panel', {
title: 'Drop Target Panel',
border: true,
width: 400,
height: 600,
items: [
{
xtype: 'component',
id: 'd3Component',
autoEl: { tag: 'div' }
}
],
listeners: {
'afterrender': function () {
panel.dropZone = Ext.create('myPanelDropTarget', panel.getEl(), {
ddGroup: 'myDDGroup',
panel: panel
});
}
}
});
I also pass panel instance into myPanelDropTarget
objet because for example I am adding dropped node's name into panel content.
Fiddle with complete live example: https://fiddle.sencha.com/#fiddle/340