RowReorder

Allows user to reorder rows by dragging them. To get notified about row reorder listen to change event on the grid store.

This feature is disabled by default. For info on enabling it, see GridFeatures. This feature is enabled by default for Gantt.

Row reorder
//<code-header>
fiddle.title = 'Row reorder';
//</code-header>
const grid = new Grid({
    appendTo : targetElement,

    // makes grid as high as it needs to be to fit rows
    autoHeight : true,

    features : {
        // enable row reordering by dragging
        rowReorder : {
            showGrip : true
        }
    },

    data : DataGenerator.generateData(10),

    columns : [
        { field : 'firstName', text : 'First name', width : 150, locked : true },
        { field : 'surName', text : 'Surname', width : 150, locked : true },
        { field : 'city', text : 'City', flex : 1 },
        { field : 'team', text : 'Team', flex : 1 },
        { field : 'score', text : 'Score', flex : 1 },
        { field : 'rank', text : 'Rank', flex : 1 }
    ]
});

If the grid is set to readOnly, reordering is disabled. Inside all event listeners you have access a context object which has a record property (the dragged record).

Usage when grouping

When the TreeGroup feature is active, note that row reordering is only possible for leaf rows and only when grouping is done using Model fields (not function-based grouping).

Row reordering is also disabled when the store is grouped using the Group feature and the "group by" field is an array value. In this case records may also be present in more than one group and so some records will be linked records, not the real records.

Validation

You can validate the drag drop flow by listening to the gridrowdrag event. Inside this listener you have access to the index property which is the target drop position. For trees you get access to the parent record and index, where index means the child index inside the parent.

You can also have an async finalization step using the gridRowBeforeDropFinalize, for showing a confirmation dialog or making a network request to decide if drag operation is valid (see code snippet below)

features : {
    rowReorder : {
        showGrip : true
    },
    listeners : {
       gridRowDrag : ({ context }) => {
          // Here you have access to context.insertBefore, and additionally context.parent for trees
       },

       gridRowBeforeDropFinalize : async ({ context }) => {
          const result = await MessageDialog.confirm({
              title   : 'Please confirm',
              message : 'Did you want the row here?'
          });

          // true to accept the drop or false to reject
          return result === MessageDialog.yesButton;
       }
   }
}

Note, that this feature uses the concept of "insert before" when choosing a drop point in the data. So the dropped record's position is before the visual next record's position.

This may look like a pointless distinction, but consider the case when a Store is filtered. The record above the drop point may have several filtered out records below it. When unfiltered, the dropped record will be below these because of the "insert before" behaviour.

Behavior with multiple subgrids

For grids with multiple subgrids, row reordering is only enabled for the first subgrid.

Dragging rows between different grids

You can enable dragging to different Grid instances by enabling the allowCrossGridDrag. This lets you both move and copy (using Ctrl/Meta key) records to other grids. You can also configure a special transferData method to take full control over what happens on drop onto another grid.

NOTE: This feature cannot be used simultaneously with the enableTextSelection config.

Reordering rows in a chained store

When using a chained flat store (created using chain), reordering rows will by default not change the order of the records in the original store. This behavior can be changed by setting the syncOrder config to true on the chained store.

When on the other hand using a chained tree store (created using chainTree), the order of the records in the original store will always be changed.

When Store has lazyLoad, row reordering might cause data inconsistency and is not recommended.

Configs

18

Common

disabledInstancePlugin
listenersEvents

Other

allowCrossGridDrag: Boolean | Object

Enables dragging rows to other grid instances. By default, this will remove from the source grid store and add the dragged record(s) to the target grid store. If you would like to implement another transfer of the data (e.g. to copy instead of move), you can provide an object with a transferData method.

features : {
    rowReorder : {
         allowCrossGridDrag : {
             async transferData({ records, insertBefore, parent }) {
                 records = records.map((rec) => rec.copy());
                 await parent.insertChild(records, this.over ? parent.children?.[0] : insertBefore);
             }
        }
    }
}
ParameterTypeDescription
allowCrossGridDrag.transferDatafunction

A function which decides what should happen to the dragged records upon drop. It receives a single context object with information about the drag drop state.

allowCrossGridDrag.transferData.sourceGridGridBase

The source grid

allowCrossGridDrag.transferData.targetGridGridBase

the target grid

allowCrossGridDrag.transferData.recordsModel[]

The dragged records

allowCrossGridDrag.transferData.insertBeforeModel

The record to insert before

allowCrossGridDrag.transferData.parentModel

The parent record of the current drop position (only applicable for trees)

copyIconCls: String

The CSS class to add to the icon element indicating it is a copy operation.

An object used to configure the internal DragHelper class

dropOnLeaf: Boolean

Enables creation of parents by dragging a row and dropping it onto a leaf row. Only works in a Grid with a tree store. This option is true by default in the Gantt product.

gripOnly: Boolean

Set to true to only allow reordering by the showGrip config.

If hovering over a parent node for this period of a time in a tree, the node will expand.

preserveSorters: Boolean= false

Set to true to preserve sorters after a drop operation, if that operation leads to the store still being sorted.

showGrip: Boolean | String

Set to true to show a grip icon on the left side of each row. Or set to 'hover' to reserve space for the grip but only show it when hovering over the row.

touchStartDelay: Number= 300

The amount of milliseconds to wait after a touchstart, before a drag gesture will be allowed to start.

Misc

clientInstancePlugin
localeClassLocalizable
localizableLocalizable

Properties

15

Common

disabledInstancePlugin

Class hierarchy

isRowReorder: Boolean= truereadonly
Identifies an object as an instance of RowReorder class, or subclass thereof.
isRowReorder: Boolean= truereadonlystatic
Identifies an object as an instance of RowReorder class, or subclass thereof.
isEventsEvents
isInstancePluginInstancePlugin
isLocalizableLocalizable

Lifecycle

configBase

Misc

clientInstancePlugin
localeHelperLocalizable
localeManagerLocalizable

Other

Functions

28

Configuration

applyDefaultsstaticBase

Events

Lifecycle

destroystaticBase

Misc

doDisableInstancePlugin
initClassstaticBase
isOfTypeNamestaticBase
mixinstaticBase
optionalLstaticLocalizable

Other

LstaticLocalizable
onEvents
relayAllEvents
triggerEvents
unEvents

Events

11

Fired before dragging starts, return false to prevent the drag operation.

// Adding a listener using the "on" method
rowReorder.on('gridRowBeforeDragStart', ({ source, context, context.records, event }) => {

});
ParameterTypeDescription
sourceGridBase
contextObject
context.recordsModel[]

The dragged row records

eventMouseEvent | TouchEvent

Fired before the row drop operation is finalized. You can return false to abort the drop operation, or a Promise yielding true / false which allows for asynchronous abort (e.g. first show user a confirmation dialog).

// Adding a listener using the "on" method
rowReorder.on('gridRowBeforeDropFinalize', ({ source, context, context.valid, context.insertBefore, context.parent, context.records, context.oldPositionContext, event }) => {

});
ParameterTypeDescription
sourceGridBase
contextObject
context.validBoolean

Set this to true or false to indicate whether the drop position is valid

context.insertBeforeModel

The record to insert before (null if inserting at last position of a parent node)

context.parentModel

The parent record of the current drop position (only applicable for trees)

context.recordsModel[]

The dragged row records

context.oldPositionContextRecordPositionContext[]

An array of objects with information about the previous tree position. Objects contain the record, and its original parentIndex and parentId values

eventMouseEvent

Fired while the row is being dragged, in the listener function you have access to context.insertBefore a grid / tree record, and additionally context.parent (a TreeNode) for trees. You can signal that the drop position is valid or invalid by setting context.valid = false;

// Adding a listener using the "on" method
rowReorder.on('gridRowDrag', ({ source, context, context.valid, context.insertBefore, context.parent, context.records, event }) => {

});
ParameterTypeDescription
sourceGridBase
contextObject
context.validBoolean

Set this to true or false to indicate whether the drop position is valid.

context.insertBeforeModel

The record to insert before (null if inserting at last position of a parent node)

context.parentModel

The parent record of the current drop position (only applicable for trees)

context.recordsModel[]

The dragged row records

eventMouseEvent

Fired when a row drag operation is aborted

// Adding a listener using the "on" method
rowReorder.on('gridRowDragAbort', ({ source, context, context.records, event }) => {

});
ParameterTypeDescription
sourceGridBase
contextObject
context.recordsModel[]

The dragged row records

eventMouseEvent

Fired when dragging starts.

// Adding a listener using the "on" method
rowReorder.on('gridRowDragStart', ({ source, context, context.records, event }) => {

});
ParameterTypeDescription
sourceGridBase
contextObject
context.recordsModel[]

The dragged row records

eventMouseEvent | TouchEvent

Fired after the row drop operation has completed, regardless of validity

// Adding a listener using the "on" method
rowReorder.on('gridRowDrop', ({ source, context, context.valid, context.insertBefore, context.parent, context.records, context.oldPositionContext, event }) => {

});
ParameterTypeDescription
sourceGridBase
contextObject
context.validBoolean

true or false depending on whether the drop position was valid

context.insertBeforeModel

The record to insert before (null if inserting at last position of a parent node)

context.parentModel

The parent record of the current drop position (only applicable for trees)

context.recordsModel[]

The dragged row records

context.oldPositionContextRecordPositionContext[]

An array of objects with information about the previous tree position. Objects contain the record, and its original parentIndex and parentId values

eventMouseEvent
catchAllEvents
destroyEvents
disableInstancePlugin
enableInstancePlugin

Event handlers

11

Called before dragging starts, return false to prevent the drag operation.

new RowReorder({
    onGridRowBeforeDragStart({ source, context, event }) {

    }
});
ParameterTypeDescription
sourceGridBase
contextObject
context.recordsModel[]

The dragged row records

eventMouseEvent | TouchEvent

Called before the row drop operation is finalized. You can return false to abort the drop operation, or a Promise yielding true / false which allows for asynchronous abort (e.g. first show user a confirmation dialog).

new RowReorder({
    onGridRowBeforeDropFinalize({ source, context, event }) {

    }
});
ParameterTypeDescription
sourceGridBase
contextObject
context.validBoolean

Set this to true or false to indicate whether the drop position is valid

context.insertBeforeModel

The record to insert before (null if inserting at last position of a parent node)

context.parentModel

The parent record of the current drop position (only applicable for trees)

context.recordsModel[]

The dragged row records

context.oldPositionContextRecordPositionContext[]

An array of objects with information about the previous tree position. Objects contain the record, and its original parentIndex and parentId values

eventMouseEvent

Called while the row is being dragged, in the listener function you have access to context.insertBefore a grid / tree record, and additionally context.parent (a TreeNode) for trees. You can signal that the drop position is valid or invalid by setting context.valid = false;

new RowReorder({
    onGridRowDrag({ source, context, event }) {

    }
});
ParameterTypeDescription
sourceGridBase
contextObject
context.validBoolean

Set this to true or false to indicate whether the drop position is valid.

context.insertBeforeModel

The record to insert before (null if inserting at last position of a parent node)

context.parentModel

The parent record of the current drop position (only applicable for trees)

context.recordsModel[]

The dragged row records

eventMouseEvent

Called when a row drag operation is aborted

new RowReorder({
    onGridRowDragAbort({ source, context, event }) {

    }
});
ParameterTypeDescription
sourceGridBase
contextObject
context.recordsModel[]

The dragged row records

eventMouseEvent

Called when dragging starts.

new RowReorder({
    onGridRowDragStart({ source, context, event }) {

    }
});
ParameterTypeDescription
sourceGridBase
contextObject
context.recordsModel[]

The dragged row records

eventMouseEvent | TouchEvent

Called after the row drop operation has completed, regardless of validity

new RowReorder({
    onGridRowDrop({ source, context, event }) {

    }
});
ParameterTypeDescription
sourceGridBase
contextObject
context.validBoolean

true or false depending on whether the drop position was valid

context.insertBeforeModel

The record to insert before (null if inserting at last position of a parent node)

context.parentModel

The parent record of the current drop position (only applicable for trees)

context.recordsModel[]

The dragged row records

context.oldPositionContextRecordPositionContext[]

An array of objects with information about the previous tree position. Objects contain the record, and its original parentIndex and parentId values

eventMouseEvent
onDestroyEvents
onDisableInstancePlugin
onEnableInstancePlugin

Typedefs

2

Object with information about a tree position

ParameterTypeDescription
recordModel

Tree node

parentIndexNumber

Index among parents children

parentIdString | Number

Parent node's id

CSS variables

7
NameDescription
--b-row-reorder-indicator-sizeDrop indicator size
--b-row-reorder-grip-iconGrip icon (font icon)
--b-row-reorder-indicator-colorDrop indicator color
--b-row-reorder-indicator-invalid-colorDrop indicator color when invalid
--b-row-reorder-box-shadowDrag proxy box shadow
--b-row-reorder-invalid-backgroundDrag proxy background when invalid
--b-row-reorder-proxy-opacityOpacity of the drag proxy (rows being dragged)