Drag-and-drop made easy

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:

Drag-and-drop made easy

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.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.144.15.154