Drag-and-drop
The @react-querybuilder/dnd
package augments React Query Builder with drag-and-drop functionality. Click here for demo.
Usage
To enable drag-and-drop on a query builder, install react-dnd
and either react-dnd-html5-backend
or react-dnd-touch-backend
(or both), then render the QueryBuilderDnD
context provider somewhere higher in the component tree than QueryBuilder
.
Note: The
enableDragAndDrop
prop does not need to be set directly on theQueryBuilder
component unless it is explicitlyfalse
to override the implicittrue
value set byQueryBuilderDnD
.
When the enableDragAndDrop
prop is true
, a drag handle is displayed on the left-hand side of each rule and each group header. Clicking and dragging the handle element allows users to visually reorder the rules and groups.
- npm
- Bun
- Yarn
- pnpm
npm i react-querybuilder @react-querybuilder/dnd react-dnd react-dnd-html5-backend react-dnd-touch-backend
bun add react-querybuilder @react-querybuilder/dnd react-dnd react-dnd-html5-backend react-dnd-touch-backend
yarn add react-querybuilder @react-querybuilder/dnd react-dnd react-dnd-html5-backend react-dnd-touch-backend
pnpm add react-querybuilder @react-querybuilder/dnd react-dnd react-dnd-html5-backend react-dnd-touch-backend
import { QueryBuilderDnD } from '@react-querybuilder/dnd';
import * as ReactDnD from 'react-dnd';
import * as ReactDndHtml5Backend from 'react-dnd-html5-backend';
import * as ReactDndTouchBackend from 'react-dnd-touch-backend';
import { QueryBuilder } from 'react-querybuilder';
const App = () => (
<QueryBuilderDnD dnd={{ ...ReactDnD, ...ReactDndHtml5Backend, ...ReactDndTouchBackend }}>
<QueryBuilder />
</QueryBuilderDnD>
);
Styling
Special styles are applied by the default stylesheet during drag-and-drop operations to help anticipate the result of the impending drop. For more information, see Styling overview § Drag-and-drop.
Cloning and grouping
By default, as successful drag-and-drop action will move a rule or group to a new location within the query builder, but there are also three alternative behaviors:
- Clone: Hold down the Alt key (⌥ Option on macOS) before and during the drag to clone the dragged rule/group instead of moving it. The original object will be left in place and the clone will be inserted at the drop location.
- Group: Hold down the Ctrl key before and during the drag to create a new group at the drop location. The
rules
array of the new group will contain the rule or group originally at the drop location and the dragged rule/group, in that order. (This operation is similar to how new folders are created on iOS by dragging one app icon on top of another.) - Clone into group: Hold down the Alt/⌥ Option and Ctrl keys before and during the drag to create a new group at the drop location, but clone the dragged rule/group into the new group instead of moving it.
The keys that determine alternate behaviors are configurable. See copyModeModifierKey
and groupModeModifierKey
.
Existing drag-and-drop contexts
If your application already uses react-dnd
, use QueryBuilderDndWithoutProvider
instead of QueryBuilderDnD
. They are functionally equivalent, but the former assumes a <DndProvider />
already exists higher up in the component tree. The latter renders its own DndProvider
which will conflict with any pre-existing ones. (If you use the wrong component, you will probably see the error message "Cannot have two HTML5 backends at the same time" in the console.)
Props
The following props are accepted on the QueryBuilderDnD
and QueryBuilderDndWithoutProvider
components.
dnd
typeof import('react-dnd') & { ReactDndBackend?: BackendFactory; HTML5Backend?: BackendFactory; TouchBackend?: BackendFactory; }
Provide this prop if you want the query builder to render immediately with drag-and-drop enabled. Otherwise, the component will asynchronously load react-dnd
, react-dnd-html5-backend
, and react-dnd-touch-backend
. Drag-and-drop features will only be enabled once those packages have loaded.
When both backends are provided, the touch backend will be preferred when a touch device is detected.
canDrop
(params: { dragging: RuleGroupTypeAny, hovering: RuleGroupTypeAny, groupItems?: boolean }) => boolean
This function determines whether a "drop" at the current hover location is valid during a drag operation. The dragging
and hovering
properties represent the dragged rule/group and the rule/group that is currently hovered over, respectively. Each of those properties includes the object's original path
and qbId
. groupItems
is true
if the groupModeModifierKey
is currently pressed.
copyModeModifierKey
string
Key code for the modifier key that puts a drag-and-drop action in "copy" mode. Default is "alt"
(Alt on Windows and Linux, ⌥ Option on macOS).
groupModeModifierKey
string
Key code for the modifier key that puts a drag-and-drop action in "group" mode. Default is "ctrl"
(Ctrl).