PDA

View Full Version : Draggable Grid in TabPanel in ViewPort



rdowling
10 Apr 2012, 6:28 AM
I am trying to create a draggable grid inside of a TabPanel item inside of a TabPanel inside of a Viewport (Viewport > TabPanel > items[] > gridpanel), bound by the fullpage TabPanel container. I could put the following grid panels into windows, getting draggability out of the box, and then add this window to a TabPanel, but the Extjs4 layout documentation seems to explicitly warn against this: "Overnesting is a common problem. An example of overnesting occurs when a GridPanel is added to a TabPanel by wrapping the GridPanel inside a wrapping Panel (that has no layout specified) and then add that wrapping Panel to the TabPanel. The point to realize is that a GridPanel is a Component which can be added directly to a Container."

-- Note: Data and example code heavily lifted from sencha designed example I put together; pls ignore that the grids are empty. --


<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">


<link rel="stylesheet" type="text/css" href="/ext/resources/css/ext-all.css" />


<script src="/ext/bootstrap.js"></script>


<script type="text/javascript">

Ext.onReady( function() {
Ext.create('Ext.container.Viewport', {
renderTo: Ext.getBody(),
items:
[
{ xtype: 'tabpanel',
activeTab: 0,
items:
[
{ xtype: 'panel',
title: 'Tab 1',
items:
[
{ xtype: 'gridpanel',


title: 'Grid Panel One',
closable: true,
collapsible: true, animCollapse: true,
resizable: true,
constrain: true,
headerPosition: 'top',
height: 300,
width: 500,
draggable: true,


columns:
[
{ xtype: 'gridcolumn',
text: 'String'
},
{ xtype: 'numbercolumn',
text: 'Number'
},
{ xtype: 'datecolumn',
text: 'Date'
},
{ xtype: 'booleancolumn',
text: 'Boolean'
}
],//columns
viewConfig: {
plugins: [
Ext.create('Ext.grid.plugin.DragDrop', {
ptype: 'gridviewdragdrop'
})
]//plugins
}//viewConfig


},//gridpanel1


{ xtype: 'gridpanel',

title: 'Grid Panel Two',
closable: true,
collapsible: true, animCollapse: true,
resizable: true,
constrain: true,
headerPosition: 'top',
height: 300,
width: 500,
draggable: true,


columns:
[
{ xtype: 'gridcolumn',
text: 'String'
},
{ xtype: 'numbercolumn',
text: 'Number'
},
{ xtype: 'datecolumn',
text: 'Date'
},
{ xtype: 'booleancolumn',
text: 'Boolean'
}
],//columns


viewConfig: {
plugins: [
Ext.create('Ext.grid.plugin.DragDrop', {
ptype: 'gridviewdragdrop'
})
]//plugins
}//viewConfig


} //gridpanel
]//tabpanel1.items[]
},//tabpanel1

{ xtype: 'panel',
title: 'Tab 2'
},//tabpanel2

{ xtype: 'panel',
title: 'Tab 3'
}//tablpanel3
]//tabpanel.items[]
}//tabpanel
]//Viewport.items[]


});//Viewport

});//onReady


</script>


</head>


<body>
</body>


</html>



This code results in a grid that is draggable (clickable and draggable), but snaps back into the original position as it's dropped (unclicked). What's the best way forward, from a code-to-work as well as a best-practice (if I'm reading the Extjs cautioning I quoted above)? Taking a look at the Window source, I could add the code below to DD, but that does not seems appropriate here (i.e. I am creating a default Grid class to inherit my components from):


initDraggable: function() {
var me = this,
ddConfig;


if (!me.header) {
me.updateHeader(true);
}


/*
* Check the header here again. If for whatever reason it wasn't created in
* updateHeader (preventHeader) then we'll just ignore the rest since the
* header acts as the drag handle.
*/
if (me.header) {
ddConfig = Ext.applyIf({
el: me.el,
delegate: '#' + me.header.id
}, me.draggable);


// Add extra configs if Window is specified to be constrained
if (me.constrain || me.constrainHeader) {
ddConfig.constrain = me.constrain;
ddConfig.constrainDelegate = me.constrainHeader;
ddConfig.constrainTo = me.constrainTo || me.container;
}


me.dd = Ext.create('Ext.util.ComponentDragger', this, ddConfig);
me.relayEvents(me.dd, ['dragstart', 'drag', 'dragend']);
}
}



Is there a mixin available that I'm not aware of, or if not would it be appropriate to create a mixin from the above code?

scottmartin
10 Apr 2012, 7:13 AM
Have a look at our portal example and see if this helps:
http://dev.sencha.com/deploy/ext-4.0.7-gpl/examples/portal/portal.html

Regards,
Scott.

rdowling
10 Apr 2012, 7:18 AM
Hi Scott --

Thanks for following up so quickly. I looked at the portal and I have a couple of questions:
1) It looks as though the drag/drop is from one location to another - if I were to allow for an absolute layout-structure, so that the grids could be dropped anywhere in the view...?
2) Maybe I could get #1 by looking at the code for this page? Best way to do that?

rdowling
12 Apr 2012, 1:02 PM
I've spent some more time trying to figure this out, and below is the dragzone I'm setting up within my grid panel. However, I think the problem I now have is that the event target (e.getTarget()), could be one of a number of grid subcomponents. What's the best way to capture the whole grid element so that I could clone it?


afterRender: function() {
this.callParent(arguments);


var oGridEl = this.el,
oView = this.getView();


new Ext.dd.DragZone(oGridEl, {


getDragData: function(e) {


var oTargetEl = e.getTarget();


console.log(oTargetEl);


if (oTargetEl) {
var d = oTargetEl.cloneNode(true);
d.id = Ext.id();
return {
ddel: d,
repairXY: Ext.fly(oTargetEl).getXY()
};
}
},


getRepairXY: function() {
return this.dragData.repairXY;
}
});

rdowling
17 Apr 2012, 1:31 PM
Although the help warns against it, I ended up adding the GridPanels to Windows as needed, then managed the windows (show/hide) through the activate/deactivate listeners on the tab panel. This was actually recommended to me by a colleague who works heavily with Ext products, and proved to be a very simple solution to implement.

It wouldn't hurt if this was a bit easier somehow, however. This draggable-grid-inside-tabpanel would most likely be pretty common behavior. I've seen other posts trying to get similar drag-and-drop functionality on grids in containers.