Search code examples
javascriptextjscheckboxdrag-and-dropgrid

Extjs drag and drop single item on grid with checkbox model


I modified the following example code to checkbox model. Here is the link http://docs.sencha.com/extjs/4.2.1/#!/api/Ext.grid.plugin.DragDrop

Two questions, first:
When dragging an item, all the selected items are being moved too. How to drag only one item each time?

Another question:
When dragging an item, it is forced to become selected. How to make it remain state unchange? (keep unselected when it is unselected before the drag, and vice versa)

And I am using version 4.2.1.

Here is the code modified from the given example:

Ext.onReady(function () {
    Ext.create('Ext.data.Store', {
        storeId: 'simpsonsStore',
        fields: ['name'],
        data: [
            ["Lisa"],
            ["Bart"],
            ["Homer"],
            ["Marge"]
        ],
        proxy: {
            type: 'memory',
            reader: 'array'
        }
    });

    Ext.create('Ext.grid.Panel', {
        store: 'simpsonsStore',
        selModel: {mode: 'SIMPLE'}, //added
        selType: 'checkboxmodel', //added
        columns: [{
            header: 'Name',
            dataIndex: 'name',
            flex: true
        }],
        viewConfig: {
            plugins: {
                ptype: 'gridviewdragdrop',
                dragText: 'Drag and drop to reorganize'
            }
        },
        height: 200,
        width: 400,
        renderTo: Ext.getBody()
    });
});

Thank you!


Solution

    1. You need to overwrite the dragZone in the DragDrop plugin, so it is only sending this record.

    2. the drag has a mousedown event, which is selecting the rows in the grid (because this has a mousedown event too), so it's fired before drag ends.

    To understand this I explain this events (for more info w3schools:

    1. row selection event: this is a mousedown event on a grid row.
    2. row drag event: drag = mousepress + (optional) mousemove, BUT: mousepress doesn't really exist so it decides it with the help of time between mousedown and mouseup
      • the time measurement is done with delayedTasks
      • if mouseup fired before the delayed time, then it will not be executed, else drag starts
    3. row drop event: drop = dragged + mouseup

      There are more ways to prevent this:

      1. try to put the selection to another event, which is fired after drag starts, but it can be messy because this event is used lots of times...
      2. it's selecting it on mousedown, but we deselect it on drag start event and at drop we prevent the selection, I do this in the code.

    The working code:

    Ext.create('Ext.data.Store', {
        storeId:'simpsonsStore',
        fields:['name'],
        data: [["Lisa"], ["Bart"], ["Homer"], ["Marge"]],
        proxy: {
            type: 'memory',
            reader: 'array'
        }
    });
    
    Ext.create('Ext.grid.Panel', {
        store: 'simpsonsStore',
        selModel: {mode: 'SIMPLE'}, //added
        selType: 'checkboxmodel', //added
        columns: [
            {header: 'Name',  dataIndex: 'name', flex: true}
        ],
        viewConfig: {
            plugins: {
                ptype: 'gridviewdragdrop',
                dragText: 'Drag and drop to reorganize',
                onViewRender : function(view) {
                    var me = this,
                        scrollEl;
                    if (me.enableDrag) {
                        if (me.containerScroll) {
                            scrollEl = view.getEl();
                        }                   
                        me.dragZone = new Ext.view.DragZone({
                            view: view,
                            ddGroup: me.dragGroup || me.ddGroup,
                            dragText: me.dragText,
                            containerScroll: me.containerScroll,
                            scrollEl: scrollEl,
                            //to remember if the row was selected originally or not
                            onBeforeDrag: function(data, e) {                            
                                var me = this,                               
                                    view = data.view,
                                    selectionModel = view.getSelectionModel(),
                                    record = view.getRecord(data.item);
                                if (!selectionModel.isSelected(record)) {
                                    data.rowSelected = false;
                                } 
                                return true;
                            },
    
                            onInitDrag: function(x, y) {
                                var me = this,
                                    data = me.dragData,
                                    view = data.view,
                                    selectionModel = view.getSelectionModel(),
                                    record = view.getRecord(data.item);
                                //for deselect the dragged record
                                if (selectionModel.isSelected(record) && data.rowSelected == false) {
                                    selectionModel.deselect(record, true);                                
                                }
                                //added the original row so it will handle that in the drag drop
                                data.records = [record];                            
                                me.ddel.update(me.getDragText());
                                me.proxy.update(me.ddel.dom);
                                me.onStartDrag(x, y);
                                return true;
                            }
                        });
                    }
    
                    if (me.enableDrop) {
                        me.dropZone = new Ext.grid.ViewDropZone({
                            view: view,
                            ddGroup: me.dropGroup || me.ddGroup,
                            //changed the selection at the end of this method
                            handleNodeDrop : function(data, record, position) {
                                var view = this.view,
                                    store = view.getStore(),
                                    index, records, i, len;
    
                                if (data.copy) {
                                    records = data.records;
                                    data.records = [];
                                    for (i = 0, len = records.length; i < len; i++) {
                                        data.records.push(records[i].copy());
                                    }
                                } else {                                
                                    data.view.store.remove(data.records, data.view === view);
                                }                    
                                if (record && position) {
                                    index = store.indexOf(record);
                                    if (position !== 'before') {
                                        index++;
                                    }
                                    store.insert(index, data.records);
                                }                            
                                else {
                                    store.add(data.records);
                                }
                                if (view != data.view) {
                                    view.getSelectionModel().select(data.records);
                                }                                                   
                            }
                        });
                    }
                }
            }        
        },
        height: 200,
        width: 400,
        renderTo: Ext.getBody()
    });