Drag & Drop
import {DragSource, DropZone} from 'cx/widgets';Drag & drop functionality is provided through DragSource and DropZone widgets,
while Grid supports dropping and its rows behave like drag sources.
Drag & drop can be used in many different ways. Let's go through a few common scenarios. Links to advanced examples are provided at the end.
Fixed Positions
The simplest case is when drag sources and drop zones are completely independent.
In the following example, there are two drag sources (B1 and B2) and one drop zone (Z1).
Sources can be dragged around and dropped on drop zones. Each source should define its
data that drop zones use to test if drop should be allowed and, when the drop
occurs, to execute appropriate actions.
<DragSource style="width:80px;height:80px;background:LightSeaGreen;cursor:move" data={{text: 'B1', type: 'b1'}} > B1 </DragSource> <DragSource style="width:80px;height:80px;background:Coral;cursor:move" data={{text: 'B2', type: 'b2'}} cloneStyle="border: 1px solid gray; padding: 10px; transform: scale(0.5)" > B2 </DragSource> <DropZone style="width:80px;height:80px;background:gold;opacity:0.3;transition: all 0.2s" overStyle="background:lightgreen;opacity:1" farStyle="opacity:1" onDropTest={({source}) => source.data.type == 'b1'} onDrop={({source}) => { MsgBox.alert(`Dropped: ${source.data.text}.`); }} inflate={20} > Z1 </DropZone>
During drag & drop operations drop zones should make visual changes to indicate to the user that drop is allowed.
Drag Handles
Drag handles are useful for dragging larger chunks of UI.
<DragSource
style="width: 180px;height:180px;background:moccasin;padding:15px"
data={{type: 'b1', text: 'Box with a drag handle'}}
handled
>
<DragHandle style="background:LightSeaGreen;padding:5px;cursor:move;font-size:10px">
DRAG USING THIS HANDLE
</DragHandle>
</DragSource>Reordering allows users to define order within a list of items.
The following example explains reordering of items positioned horizontally (e.g. tabs).
This is enabled by putting drop zones in gaps between drag sources. When dragging starts,
the source is hidden and its place is occupied by the nearest drop zone. This is achieved
using the matchWidth, matchHeight, and matchMargin flags. Each drop zone
is inflated so it reacts when mouse is in its proximity, not strictly when it's over.
<DropZone
mod="inline-block"
onDropTest={({source}) => source.data.type == 'hbox'}
onDrop={(e, {store}) => {
store.update('items', moveElement, e.source.data.index, 0);
}}
matchWidth
matchHeight
matchMargin
inflate={50}
>
</DropZone>
<Repeater
keyField="id"
records={{
bind: 'items', defaultValue: Array.from({length: 7}, (_, i) => ({
id: i + 1,
text: `Item ${i + 1}`
}))
}}
>
<DragSource
style="display:inline-block; margin: 5px; background: #ddf; cursor: move"
data={{index: {bind: "$index"}, type: 'hbox'}}
hideOnDrag
>
<div text-bind="$record.text" style="padding:5px"/>
</DragSource>
<DropZone
mod="inline-block"
onDropTest={({source}) => source.data.type == 'hbox'}
onDrop={(e, {store}) => {
store.update('items', moveElement, e.source.data.index, store.get('$index') + 1);
}}
matchWidth
matchHeight
matchMargin
inflate={50}
>
</DropZone>
</Repeater>Advanced Examples
Check out the following examples to learn more about drag & drop capabilites in CxJS.
Configuration
DragSourceDropZoneDragDropEvent
| Property | Description | Type |
|---|---|---|
data | Data about the drag source that can be used by drop zones to test if drag source is acceptable and to perform drop operations. | object |
handled | Set to | string |
hideOnDrag | Set to | boolean |
onDragEnd | A callback invoked when drag operation completes.
Arguments are | function |
onDragStart | A callback invoked when drag operation starts.
Arguments are | function |
baseClass | Base CSS class to be applied to the element. Default value is | string |
class | Additional CSS classes to be applied to the element. If an object is provided, all keys with a "truthy" value will be added to the CSS class list. | string/object |
clone | Custom contents to be displayed during drag & drop operation. | config |
cloneClass | Additional CSS class to be applied to the drag clone element. | string |
cloneStyle | Additional style rules to be applied to the drag clone element. | string |
items | List of child elements. | array |
layout | Define an inner layout. | string/object |
mod | Appearance modifier. For example, | string/array |
outerLayout | Defines the outer layout which wraps the widget. | widget |
plainText | Set to | boolean |
preserveWhitespace | Keep whitespace in text based children. Default is | boolean |
putInto | Used with outer layouts. Specifies the name of the content placeholder which should render the widget. | string |
style | Style object applied to the wrapper div. Used for setting the dimensions of the element. | string/object |
trimWhitespace | Remove all whitespace in text based children. Default is | boolean |
vdomKey | Key that will be used as the key when rendering the React component. | string |
visible | Visibility of the widget. Defaults to | boolean |