Dragging and dropping nodes within trees is easy with Ext JS 4. To allow the drag-and-drop action within a tree, we need to add the TreeViewDragDrop
plugin as follows:
Ext.define('TTT.view.admin.CompanyTree', { extend: 'Ext.tree.Panel', xtype: 'companytree', title: 'Company -> Projects -> Tasks', requires: ['TTT.store.CompanyTree','Ext.tree.plugin.TreeViewDragDrop'], store: 'CompanyTree', lines: true, rootVisible: false, hideHeaders: true, viewConfig: { preserveScrollOnRefresh: true, plugins: { ptype: 'treeviewdragdrop' } }, etc
This simple inclusion will enable the drag-and-drop support for your tree. You will now be able to drag-and-drop any node to a new parent. Unfortunately, this is not exactly what we need. A task node should only be allowed to drop on a project node, while a project node should only be allowed to drop on a company node. How can we restrict the drag-and-drop action to these rules?
There are two events that can be used to configure this functionality. These events are fired from the TreeViewDragDrop
plugin and can be configured in the doAfterActivate
function of the AdminController
in the following way:
doAfterActivate:function(){ var me = this; me.getCompanyStore().load(); me.getProjectStore().load(); me.getTaskStore().load(); me.getCompanyTreeStore().on('append' , me.doSetTreeIcon, me); me.getCompanyTree().getView().on('beforedrop', me.isDropAllowed,me); me.getCompanyTree().getView().on('drop', me.doChangeParent, me); me.getCompanyTreeStore().load(); }
The beforedrop
event can be used to test whether the drag
and drop
actions are valid. Returning false
will stop the drop
action from occurring and animate the node back to the origin of the action. The drop
event can be used to process the drop
action, most likely to persist the change to the underlying storage.
The isDropAllowed
function returns true
or false
depending on whether the drop target is valid for the node:
isDropAllowed: function(node, data, overModel, dropPosition) { var dragNode = data.records[0]; if (!Ext.isEmpty(dragNode) && !Ext.isEmpty(overModel)) { var dragIdSplit = dragNode.getId().split('_'), var dropIdSplit = overModel.getId().split('_'), if (dragIdSplit[0] === 'T' && dropIdSplit[0] === 'P') { return true; } else if (dragIdSplit[0] === 'P' && dropIdSplit[0] === 'C') { return true; } } return false; }
This function will restrict the drag
and drop
actions to two valid scenarios: dragging a project to a new company and dragging a task to a new project. All the other drag
and drop
actions are not allowed.
Dragging and dropping alone is not enough; we now need to save the new parent after a successful drop. This action is handled in the doChangeParent
function:
doChangeParent: function(node, data, overModel, dropPosition, eOpts) { var me = this; var dragNode = data.records[0]; if (!Ext.isEmpty(dragNode) && !Ext.isEmpty(overModel)) { var dragIdSplit = dragNode.getId().split('_'), var dropIdSplit = overModel.getId().split('_'), if (dragIdSplit[0] === 'T' && dropIdSplit[0] === 'P') { var idTask = Ext.Number.from(dragIdSplit[1]); var idProject = Ext.Number.from(dropIdSplit[1]); var rec = me.getTaskStore().getById(idTask); if (!Ext.isEmpty(rec)) { rec.set('idProject', idProject); rec.save(); } } else if (dragIdSplit[0] === 'P' && dropIdSplit[0] === 'C') { var idProject = Ext.Number.from(dragIdSplit[1]); var idCompany = Ext.Number.from(dropIdSplit[1]); var rec = me.getProjectStore().getById(idProject); if (!Ext.isEmpty(rec)) { rec.set('idCompany', idCompany); rec.save(); } } } }
Dragging a valid node to a new parent is now persisted when the record is saved. You will now be able to drag-and-drop between valid tree nodes and automatically save the changes.
The animations provided by Ext JS 4 trees will guide your drag
and drop
actions. Dragging the Database Development node will animate the action as shown in the following screenshot:
Should the drop action not be allowed, the node will animate back to the original position, providing instant visual feedback for the user.
Ext JS 4 trees are very flexible components, and there is still much to learn if you want to fully leverage trees in your application. We recommend that you explores the many tree examples on the Sencha Docs website for more complex examples including the drag
and drop
actions between trees and persisting model-based data nodes.
3.144.15.154