SitePen / dgrid

A lightweight, mobile-ready, data-driven, modular grid widget designed for use with dstore
http://dgrid.io/
Other
628 stars 295 forks source link

It becomes impossible to do DnD after a column has been sorted #1363

Closed AlexArcPy closed 6 years ago

AlexArcPy commented 7 years ago

An issue which seems to be easy to reproduce.

  1. Go to http://dgrid.io/js/dgrid/demos/laboratory/ and add DnD support.
  2. Drag and drop some rows. Works fine.
  3. Click on a column to sort it.
  4. Now you cannot drag and drop rows any longer.

This behavior is seen in my own applications using dgrid. Tested on latest Chrome, Firefox and IE.

This is the code I've copied from the dgrid laboratory just after adding DnD support:

require([
    'dojo/_base/declare',
    'dstore/Memory',
    'dstore/Trackable',
    'dgrid/OnDemandGrid',
    'dgrid/extensions/DnD'
], function (declare, Memory, Trackable, OnDemandGrid, DnD) {
    var store = new (declare([Memory, Trackable]))({
        data: createData()
    });

    // Instantiate grid
    var grid = new (declare([OnDemandGrid, DnD]))({
        collection: store,
        columns: {
            First_Name: {
                label: 'First Name'
            },
            Last_Name: {
                label: 'Last Name'
            }
        }
    }, 'grid');

    grid.startup();

    function createData() {
        var data = [];
        var column;
        var i;
        var item;

        for (i = 0; i < 50; i++) {
            item = {};
            for (column in { First_Name: 1, Last_Name: 1 }) {
                item.id = i;
                item[column] = column + '_' + (i + 1);
            }
            data.push(item);
        }

        return data;
    }
});
edhager commented 7 years ago

This is basically a works-as-designed situation. The DnD extension only works with an unsorted store. The DnD extension manipulates the rows by removing and inserting items in the store. With sorting is applied, the store will always return the items to the grid in the order determined by the sorting.

One idea that might help... Create a memory store that does not track the sorting but always rearranges the items in the store's data array. Here is an example:

define([
    'dojo/_base/declare',
    'dojo/when',
    'dstore/Memory'
], function (declare, when, Memory) {
    /**
     * A memory store that does not create a query log.  Items are always fetched in the order they
     * exist in the data array.  When this store is sorted, the data items are always rearranged in the data array.
     */
    return declare([Memory], {
        sort: function () {
            var sorterStore = (new Memory({ data: this.data })).sort.apply(sorterStore, arguments);
            this.setData(sorterStore.fetchSync());
            return this;
        }
    });
});

This store will allow you to click on a grid heading, sort the rows and then use drag and drop to reorder the rows. One problem that remains is the grid heading will contains an arrow that indicates the sorting direction. After dragging and dropping a row, that arrow will no longer be a correct indication of the sortings.