'Extjs 4.X Move records of a grid UP/DOWN with a button

This post is continuation of my earlier post (here) for which I couldnt find a working solution (yet). In brief: I have created a Extjs (4.X) grid which has records of parents and childrens. The records are in sorted order where in the childrens always appear just below their parents as shown here, where 'P' designates a record as parent while 'C' designates a record as children.

'May' is the parent of Peter, Odin is the parent of Thor and Loki, Bruce has no children yet marked as Parent (standalone entity)

enter image description here

fiddle: https://fiddle.sencha.com/#view/editor&fiddle/3jks

I wish to change sort order of the parents while also bringing their childrens along when I move the groups up/down. At first I wanted to try drag and drop but I couldnt find a working solution for that (I tried Gird DragAndDrop as well as TreeGrid, fiddles are on my previous post).

Based on a suggestion on the previous open post I tried Grouping which groups parent and child but I lost the ability to drag and drop the entire group. To work with what knowledge I have I have created buttons instead, for moving the groups up or down based on the user click. The grouping is based on Rank column so as soon as I update the rank the records should ideally jump groups. For some reason when I click on "UP" button on the Rank:2 group, BRUCE changes to Rank:1 and May Parker changes to Rank:2 which is correct but the Peter Parker still stays at Rank:1. After debugging the code I found that the store for some reason removed Peter's records and replaced it with another copy of May Parker (the grid doesnt show it though). I have put console messages where we can observe this. What could be the problem here? Pointers and suggestions are very much appreciated. I am open to changing the entire logic as well if there is a better way to move these records based on rank.



Solution 1:[1]

Here is a working fiddle for grid grouper header drag-drop.

Here are more details and some help to build your up-down button example:

You are updating the records several times.

I would suggest, that you set the rank by recordId to ensure each item is processed only once. Otherwise records switch groups while you are working on them.

    // I am using onBeforeGroupClick to handle collapsing correctly
    onBeforeGridGroupClick: function (grid, node, dataIndex, e, eOpts) {
        const targetIsButton = e.getTarget().type === 'button';

        console.log('[onBeforeGridGroupClick] targetIsButton', targetIsButton);

        if (targetIsButton) {
            this.updateRank(grid, node, dataIndex, e)
        }

        // return false will stop gridgroupclick from running
        return !targetIsButton;
    },

    // here I am updating the rank
    updateRank: function (grid, node, group, e) {
        console.log('[updateRank] dataIndex', group);

        const store = grid.getStore();

        // collect the group data for the clicked group
        const groups = store.getGroups(),
            currentGroupIndex = groups.findIndex('rank', group),
            currentGroup = groups.items[currentGroupIndex],
            // Ext.pluck gets the IDs from the current group
            currentRecordIds = Ext.pluck(currentGroup.items, 'id');

        // collecting the group data for the group you want to switch with
        const isUp = e.getTarget().value === 'Up';
            targetId = currentGroupIndex + (isUp ? 1 : -1)
            targetGroupIndex = groups.findIndex('rank', targetId),
            targetGroup = groups.items[targetGroupIndex],
            targetRecordIds = Ext.pluck(targetGroup.items, 'id');

        // define out of range conditions
        if(targetGroupIndex < 0) return;

        // stop the grid from updating while you work on the store
        store.suspendEvents(true);

        // set the rank for the target and current records
        Ext.Array.each(targetRecordIds, function(id) {
            const record = store.findRecord('id', id);
            
            record.set('rank', currentGroupIndex);
        })
        Ext.Array.each(currentRecordIds, function(id) {
            const record = store.findRecord('id', id);
            
            record.set('rank', targetGroupIndex);
        })

        // update the grid from all suspended store events
        store.resumeEvents();
    }

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1