PDA

View Full Version : Grid Drag & Drop: Suppress for some records (groups)



suamikim
21 Jun 2012, 2:15 AM
Hy there,

is it possible to control which records can be dragged and where they can be dropped (suppress drag-operation either right from the beginning or in the middle during hovering)?

What i need in detail is the following:

I'm having a grid with some groups (lets say male & female) and only want to activate the d&d inside group 'female' which means 2 things:

1.) I started dragging a record from groue 'female' (Lisa). As soon as the drag is outside the group 'female' it should display an error-state like when dragging outside the bounds of the grid:
36423

2.) Starting to drag an item from group 'male' should either not be possible at all (just don't show the d&d panel) or show the error-state like mentioned above right from the beginning and never change to "correct"-state.

Thanks,

mike

suamikim
30 Aug 2012, 5:04 AM
After some digging around in the sources of ext i just found a solution which works but isn't perfect at all:

The "drop-allowed-indication" can be handled by the underlying DropZone which is created in onViewRender of the treeviewdragdrop-plugin. This is not documented but can be seen in the source-code (http://docs.sencha.com/ext-js/4-1/source/TreeViewDragDrop.html#Ext-tree-plugin-TreeViewDragDrop) of the plugin.

Everything that needs to be done (at least for this example) is to override/extend the onNodeOver- & onContainerOver-method of the DropZone to return the appropriate css-class for the drop-not-allowed- or drop-allowed-indication.


Ext.override(Ext.view.DropZone, {
onNodeOver: function(nodeData, source, e, data) {
if (data && data.records && data.records[0]) {
// The check should be better specified, e.g. a
// female with the name 'Malena' would be recognized as male!
if (nodeData.innerHTML.indexOf(data.records[0].get('sex')) < 0) {
return this.dropNotAllowed;
}
}
return this.callOverridden([nodeData, source, e, data]);
},
onContainerOver: function(source, e, data) {
return this.dropNotAllowed;
}
});

Working example: http://jsfiddle.net/suamikim/auXdQ/

There are a few things i don't like about this solution:



The override changes (per definition...) the behaviour of all DropZones in my application. How can i only override/extend the specific DropZone of one grid?

I've tried the following:

Add an interceptor to the dropZone after the gridview has been rendered: http://jsfiddle.net/suamikim/uv8tX/

At first this seems to work because it shows the correct drop-allowed-indication but it drops the record even if the indicator shows that it's not allowed (it always shows the "green line"...)

Define a new dnd-plugin which extends the treeviewdragdrop-plugin and just override the onNodeOver-method of the dropZone after it's creation: http://jsfiddle.net/suamikim/5v67W/

This kind of does the opposite from the interception-method. It also shows the correct indication but it never shows the "green line" and won't allow the drop anywhere...
The class i'm overriding (Ext.view.DropZone) is marked private in the documentation (http://docs.sencha.com/ext-js/4-1/#%21/api/Ext.grid.ViewDropZone) with a note that it shouldn't be used directly...


I would really appreciate some comments on those 2 issues and maybe even some better solutions!

Thanks, mik

suamikim
11 Sep 2012, 12:23 AM
I adjusted the version in which i defined a new dnd-plugin which extended the original gridviewdragdrop-plugin. The "magic" was to also extend gridviewdropzone and extend the onNodeOver-method instead of just overriding it.

This needs to be done because the original onNodeOver-method which is now called by callParent handles the "green line" and finally allows the drop.

The only thing my extended gridviewdragdrop-plugin does now is to create a instance of the new dropzone-class instead of the standard gridviewdropzone in the onViewRender-method.
This seems like a reasonable way so far:


// Extend the treeview dropzone
Ext.define('ExtendedGridViewDropZone', {
extend: 'Ext.grid.ViewDropZone',

onNodeOver: function(nodeData, source, e, data) {
if (data && data.records && data.records[0]) {
// The check should be specified, e.g. a female with the name 'Malena' would be recognized as male!
if (nodeData.innerHTML.indexOf(data.records[0].get('sex')) < 0) {
return this.dropNotAllowed;
}
}

return this.callParent(arguments);
},
onContainerOver: function(source, e, data) {
return this.dropNotAllowed;
}
});

Ext.define('ExtendedGridDnD', {
extend: 'Ext.grid.plugin.DragDrop',
alias: 'plugin.extendeddnd',

onViewRender: function(view) {
this.callParent(arguments);

// Create a instance of ExtendedGridViewDropZone instead of Ext.grid.ViewDropZone
this.dropZone = Ext.create('ExtendedGridViewDropZone', {
view: view,
ddGroup: this.dropGroup || this.ddGroup
});
}
});

Working example: http://jsfiddle.net/5v67W/1/

Nonetheless I'd still appreciate different approaches because it still feels like it could be done easier...