drag and drop rows from grid to grid

  • I know this problem has been posted a bunch of times but this is more about the example someone gave me...
    http://tdg-i.com/js/extexamples/dnd_grid_to_grid/dnd_grid_to_grid.html

    from this post...
    http://extjs.com/forum/showthread.php?t=39277

    His example works great but he creates grid objects instead of using xtypes. The problem is I'm using xtypes and theres no real way that I can think of to tie his droptargets to my xtypes.

    For a little background on what I'm trying to do, I have a bunch of grids in my app and all of them show different types of data (a contact grid, an address grid, a phone number grid, etc etc) I would like to be able to drag and drop between each grid to represent associations between the rows in those grids. For example, if I want to associate 2 addresses to a contact, I would multi select 2 addresses from the addresses grid and drag/drop them to the contact in the contact grid. No new rows would be created in the target grid and no current rows would be deleted from the source grid. To make things easier on myself, all my grids extend a myGridCls class that extends the Ext.grid.EditorGridPanel class so I can make changes to my grids in one place. Is there any way I could include a droptarget config in myGridCls so that way I wouldn't have to make a separate droptarget config for every single one of my grids.

    Heres some sample code...

    var myGridCls = Ext.extend(Ext.grid.EditorGridPanel, {
    initComponent:function() {
    Ext.apply(this, {
    enableDragDrop: true,
    loadMask: true,
    sm: new Ext.grid.RowSelectionModel(),
    autoScroll: true,
    viewConfig: {
    forceFit: true
    }
    });

    this.on('afteredit',function(e){
    Ext.Ajax.request({
    url: 'editfield.php',
    method: 'GET',
    timeout: 90000,
    params: {
    EntryType: this.EntryType,
    Entry_ID: e.record.data.Entry_ID,
    Field: e.field,
    Value: e.value
    }
    });
    },this);

    myGridCls.superclass.initComponent.apply(this, arguments);
    }, onRender:function() {
    this.on({
    rowcontextmenu: function(g,ri,e){
    e.stopEvent(); // Prevent the browser to show its default contextmenu
    gridCtxMenu.rowIndex = ri; // It's important! you'll need the rowIndex (the row that right clicked on it) on future.
    gridCtxMenu.srcId = 'protoid';
    gridCtxMenu.showAt(e.getXY()); // Get the current X and Y coordinates and show the gridCtxMenu (my custom created menu) on that location.
    },
    scope: this
    });

    if( this.DeleteEntries==true ){
    this.on('keydown',function(e){
    debug(e);
    debug(e.getCharCode());
    if( e.getCharCode()==46){
    this.getSelectionModel().selections.each(function( item){
    Ext.Ajax.request({
    url: 'deleterow.php',
    method: 'POST',
    params: {
    EntryType: this.EntryType,
    ParentEntry_ID: this.Entry_ID,
    Entry_ID: item.data.Entry_ID
    }
    });
    },this );
    Ext.each(this.getSelectionModel().getSelections(), this.getStore().remove, this.getStore());
    }
    },this);
    }

    myGridCls.superclass.onRender.apply(this, arguments);
    }
    });

    var addressEditGridCls = Ext.extend(myGridCls, {
    initComponent:function() {
    Ext.apply(this, {
    height: 100,
    DeleteEntries: true,
    columns: addyGridFields,
    EntryType: 'ADDRESS',
    store: new Ext.data.SimpleStore({
    proxy: new Ext.data.HttpProxy({
    timeout: 60000,
    url: 'loadlist.php',
    method: 'GET'
    }),
    baseParams: {
    Type: 'CONTACT_ADDRESSES'
    },
    fields: addyGridFields
    }),
    tbar: [{
    text: 'Add Address',
    iconCls: 'add',
    handler: function(){
    Ext.getCmp('triggerform').layout.setActiveItem('ne wAddressForm');
    Ext.getCmp('newAddressForm').Entry_ID=this.Entry_I D;
    Ext.getCmp('newAddressForm').getForm().reset();
    debug(this);
    }, scope: this
    }]
    });
    addressEditGridCls.superclass.initComponent.apply( this, arguments);

    },onRender:function() {
    addressEditGridCls.superclass.onRender.apply(this, arguments);
    }
    });
    Ext.reg('addressEditGrid', addressEditGridCls);

    var phoneEditGridCls = Ext.extend(myGridCls, {
    initComponent:function() {
    Ext.apply(this, {
    height: 100,
    DeleteEntries: true,
    columns: phoneGridFields,
    EntryType: 'PHONE',
    store: new Ext.data.SimpleStore({
    proxy: new Ext.data.HttpProxy({
    timeout: 60000,
    url: 'loadlist.php',
    method: 'GET'
    }),
    baseParams: {
    Type: 'CONTACT_PHONES'
    },
    fields: phoneGridFields
    })
    });
    phoneEditGridCls.superclass.initComponent.apply(th is, arguments);
    },onRender:function() {
    phoneEditGridCls.superclass.onRender.apply(this, arguments);
    }
    });
    Ext.reg('phoneEditGrid', phoneEditGridCls);

    var contactCatGridCls = Ext.extend(myGridCls, {
    initComponent:function() {
    Ext.apply(this, {
    store: contactCatGridAllSt,
    hideHeaders: true,
    EntryType: 'CONTACTCATEGORY',
    cm: new Ext.grid.ColumnModel([
    // checkColumn,
    {id: 'ContactCategory', header: "Contact Category", width: 350, sortable: false, dataIndex: 'ContactCategoryLabel'}
    ])
    // sm: checkColumn
    });
    contactCatGridCls.superclass.initComponent.apply(t his, arguments);
    },onRender:function() {
    contactCatGridCls.superclass.onRender.apply(this, arguments);
    }
    });
    Ext.reg('contactCatGrid', contactCatGridCls);


  • Can't you just implement the droptarget in your new subclass?


  • holly smokes, 2 for 2. I got this working as well!

    Ext.override(Ext.grid.GridView, {
    onRowOver : function(e, t){
    var row;
    if((row = this.findRowIndex(t)) !== false){
    this.grid.droprow=this.grid.getStore().getAt(row);
    this.addRowClass(row, 'x-grid3-row-over');
    }
    }
    });


  • There is one more example: http://examples.extjs.eu/?ex=ddgrids


  • jsakalos....you....are....the.... !!!!!!

    this is exactly what I was looking for. So just to understand what I'm doing...

    By putting

    this.dz = new GridDropZone(this, {ddGroup:this.ddGroup 'GridDD'});

    inside the onRender method in my class and after the...
    myGridCls.superclass.onRender.apply(this, arguments);

    I'm saying that after a grid has been created/rendered and all the render type args have been applied, THEN ad the dropzone to it? Anywhere else and the dom div tags of my grid wouldn't be setup at that point in time so there would be nothing for the dropzone to glue it's self on to. Did I get it?


  • I just read one of the dd tutorials on extjs and I'm starting to get this. I think I almost have it working except for the DropZone. In the tutorials example, they just passed it a div tag ID to say that div was ok to drop stuff into. In my case, I'm using a grid class (myGridCls) that other grids are extending from (contactGridCls,addressGridCls,phoneGridCls). Since myGridCls is never instantiated into an object so it would technically never have a div tag generated for it, how would I go about gluing it to the dropzone? and better yet, even if it could be done, it couldn't just blindly drop stuff into the grid, it would have to know which row in the grid it's hovering over.

    var dz1 = new Ext.dd.DropZone(myGridCls.getView().el.dom.childNo des[0].childNodes[1], {ddGroup:'group'});

    this obviously doesn't work but its an example of what I'm talking about.


  • wow, I got it on my own. It was a bit of a workaround but if I mess with the gridview I can get the row index num and through the grids store I can get the data record...


    Ext.override(Ext.grid.GridView, {
    onRowOver : function(e, t){
    var row;
    if((row = this.findRowIndex(t)) !== false){
    this.grid.droprow=this.grid.getStore().getAt(row);
    }
    }
    });


    I just have it store the hovered grid row to this.grid.droprow so I can access it when I drop whatever it is I'm dragging.

    Now my next dilemma is how to get hover over highlighting to work while your dragging over a grid row. When you mouse over a grid row it turns on fine, but when you are dragging something it doesn't show.


  • Exactly! DropZone needs existing markup.


  • Ran into something...

    As I'm dragging my rows, I can easily sniff the selection module of the source grid to see what rows I'm dragging and I can easily dive into what ever grid I'm dropping the rows into but I can't seem to see the target row in the target grid I'm dragging the source rows into. Like if I'm dragging rows 1-7 from grid A into row 10 on grid B, I can get to the 1-7 rows just fine and I can see grid B just fine but I can't get to row 10 in grid B. I checked grid Bs selection model and obviously, the target row doesn't show up since it's not technically selected.


  • You mean like this?
    I honestly have no clue what you mean. Do you mean something like this?


    var myGridCls = Ext.extend(Ext.grid.EditorGridPanel, {
    initComponent:function() {
    Ext.apply(this, {
    enableDragDrop: true,
    loadMask: true,
    droptarget: new Ext.dd.DropTarget({stuff goes here}),
    sm: new Ext.grid.RowSelectionModel(),
    autoScroll: true,
    viewConfig: {
    forceFit: true
    }
    });
    myGridCls.superclass.initComponent.apply(this, arguments);
    }, onRender:function() {
    myGridCls.superclass.onRender.apply(this, arguments);
    }
    });