rosebrit3
rosebrit3

Reputation: 523

Moving nodes in a tree in EXTJS 4

Am working on moving nodes in a tree, and as they are moved, their ID's are updated in the database through C# in the back-end. Till now, i have managed to update the position of the node that is being moved, but after its moved, the position of the other nodes in the tree should also get updated. Could anyone tell me how to proceed with this?

itemmove : {
fn : function(v, oldParent, newParent, index, eOpts) {
var nodeID = v.data.id;
var oldParent = oldParent.data.id;
var newParent = newParent.data.id;
var index = index;
var level = v.data.level;
movenode(nodeID, oldParent, newParent, index, level);
}
}


function movenode(nodeID, oldParent, newParent, index, level) {
Ext.Ajax.request({
    url : 'data/pages.aspx',
    params : {
        UserID : USER.UserID,
        mode : 'MOVENODE',
        currentNode : nodeID,
        oldParentNode : oldParent,
        newParentNode : newParent,
        index : index,
        level : level,
        ProjDB : projDB
    },
    success : function() {
        loadTREEst();
        genMessage(LANG.Suc, LANG.SaveOK, 'tick', false);

    },
    failure : function() {
        genMessage(LANG.Warn, LANG.GenWarn, 'warn', false);
    }
});
}

So, i send the parameters to SQl, and then update the index of the node that has been moved.

For example, if i move a node from position 8 to 1, the index of the 8th node changes to 1 in the database, but the index of the first node remains at 1. And because of this, the tree also doesnt get updated. i want all the other nodes in the tree to get updated as well. So, in this case, the node in index 1 will become index 2, the node in index 2 will become index 3, and so on. Can anyone explain me how to do this.

Is there any other method other than autosync or sync to do this? Thanks in advance.

Upvotes: 0

Views: 5265

Answers (2)

Izhaki
Izhaki

Reputation: 23586

Here is some sample code that works with 4.1:

Ext.define('BS.model.ItemCategory', {
    extend: 'Ext.data.Model',
    fields: [
        {name: 'name'     , type: 'string'},
        {name: 'iconCls'  , type: 'string', defaultValue: 'treenode-no-icon'},
        {name: 'leaf'     , type: 'boolean', defaultValue: false},
        {name: 'expanded' , type: 'boolean', defaultValue: true, persist: false},
        {name: 'index'     , type: 'int'},        
    ],

    proxy: {
        type: 'direct',

        api: {
            create: ItemCategories.Create,
            read: ItemCategories.Read,
            update: ItemCategories.Update,
            destroy: ItemCategories.Delete,
        },
    }, 
});

You won't be having a direct proxy as your server isn't php, but just put the corresponding server scripts (see docs).

Then my store:

Ext.define('BS.store.ItemCategories', {

    extend: 'Ext.data.TreeStore',    
    model: 'BS.model.ItemCategory',

    autoSync: true,

    root: {
        text: 'Root',
        id: 'NULL',
        expanded: true
    },

    clearOnLoad: true,
});

And the view:

Ext.define('BS.view.admin.pages.item-categories.ItemCategories' ,
{
    extend: 'Ext.tree.Panel',
    alias : 'widget.item-categories-tree',

    store: 'ItemCategories',

    displayField: 'name',

    rootVisible: false,
    useArrows: true,
    multiSelect: false,
    singleExpand: false,    
    allowDeselect: true,

    plugins: {
        ptype: 'treeviewdragdrop',                    
    },          
});

That's pretty much it! When you move a node you'll see ExtJS sends an update request to the server with an array of all the nodes whose index (sort) has changed.

Upvotes: 1

Izhaki
Izhaki

Reputation: 23586

This is the code I had for 4.0.7, to my memory it solved this problem.

// This happens after drag and drop
onItemMove: function(aNode, aOldParent, aNewParent, aIndex, aOptions)
{

    // Update the indeces of all the parent children (not just the one that moved)
    for ( i = 0; i < aNewParent.childNodes.length; i++ )
    {
        aNewParent.childNodes[i].data.sort = i;
        aNewParent.childNodes[i].setDirty();
    }

    this.mStore.sync();
},

Notice that you won't have mStore.sync() as you are sending your own request to the server, which only involves one record. By setting child nodes as dirty, sync sends more than one record to the server's update call (in my case, I'm using autosync and direct).

You should consider what happens when the user moves a node from a parent node to the parent's sibling - the index (sort) of some nodes in both the old and new parent will change. So you might end up with 6 records that need updating on the server.

All I'm saying is that given 4.1 already handles node moving correctly, you might be better off upgrading to 4.1 and take advantage of the native support for this than coding it yourself. If you stick to 4.0.7, just remember to consider that a moving a node could require the updating of many nodes.

Upvotes: 1

Related Questions