Drop
Drop defines an area into which data can be dropped. Targets can be nested to form hierarchies of arbitrary depth; the foremost participating target under the pointer becomes active.
Events
| Event | Description |
|---|---|
dragenter | This component becomes the foremost participating target. |
dragleave | This component stops being the foremost participating target. |
dragover | The pointer moves while this component is the foremost participating target. |
dragend | The operation ends while this component is the active target, including cancellation with Escape. |
drop | A permitted operation is released on this component. |
These events receive a DnDEventPayload.
Props
| Prop | Type / Default | Description |
|---|---|---|
tag | String or component ('div') | Root element or Vue component. A component must render one HTML root element; its props, attributes, listeners, and slots are forwarded. |
accepts-type | String, Number, Array, Function, or null (null) | Accepted drag type, accepted type array, or (type) => boolean predicate. null accepts every type. |
accepts-data | Function (() => true) | (data, type) => boolean predicate evaluated for participating drag data. |
mode | String ('copy') | Event name sent back to the source after a successful drop. The documented modes are copy and cut. |
drag-image-opacity | Number (0.7) | Opacity applied to a custom drag image supplied by this target. |
Slots
| Slot | Props | Description |
|---|---|---|
default | Props forwarded by a component passed to tag | Content rendered inside the target root. |
drag-image | type, data | Optional image used while this participating target is active. |
Other named slots are forwarded when tag is a Vue component.
CSS classes
| Class | Applied when |
|---|---|
dnd-drop | Always on the Drop root. |
type-allowed / type-forbidden | The active drag type is accepted or rejected. |
drop-in / drop-out | This component is or is not the foremost participating target. |
drop-allowed / drop-forbidden | Participating drag data is accepted or rejected. |
The state classes are present only while a drag is active where their value can be determined. A type-forbidden target does not become the active target; an accepting ancestor may become active instead.
Modes
The target's mode describes the successful operation from the source's perspective:
copyleaves source state unchanged unless the application chooses otherwise.cutnormally removes or updates the source item.
After drop is emitted on the target, the same payload is emitted on the source Drag using the mode as the event name. The library does not mutate application state, so implement @cut when the source item should be removed.
<Drag :data="item" @cut="remove(item)">
{{ item.label }}
</Drag>
<Drop mode="cut" @drop="receive">
Move here
</Drop>A mode is not made invalid by the absence of a source listener. Use the documented copy and cut modes so Vue can validate the declared source events.
Copy leaves the source intact. Cut emits back to the source so it can be removed.
View example code
Template
<div class="dnd-demo__row">
<Drag
v-for="item in items"
:key="item"
class="dnd-demo__item"
:data="item"
@cut="remove(item)"
>
{{ item }}
</Drag>
</div>
<div class="dnd-demo__grid" style="margin-top: 1rem">
<Drop
class="dnd-demo__zone"
mode="copy"
@drop="record('Copied', $event)"
>
<span class="dnd-demo__label">Copy</span>
</Drop>
<Drop
class="dnd-demo__zone"
mode="cut"
@drop="record('Cut', $event)"
>
<span class="dnd-demo__label">Cut</span>
</Drop>
</div>TypeScript
import { ref } from 'vue';
import { Drag, Drop } from 'vue-easy-dnd';
import type { DnDEventPayload } from 'vue-easy-dnd';
const initialItems = ['One', 'Two', 'Three'];
const items = ref([...initialItems]);
const status = ref('Choose a target');
const remove = (item: string) => {
items.value = items.value.filter(value => value !== item);
};
const record = (action: string, event: DnDEventPayload) => {
status.value = `${action} ${String(event.data)}`;
};
const reset = () => {
items.value = [...initialItems];
status.value = 'Choose a target';
};Restricting droppable data
accepts-type determines whether a target participates in an operation. Once it participates, accepts-data receives (data, type) and determines whether dropping is permitted.
<Drop
accepts-type="number"
:accepts-data="data => typeof data === 'number' && data % 2 === 0"
@drop="receiveEvenNumber"
>
Even numbers only
</Drop>All items share a type; accepts-data decides whether each value is allowed.
View example code
Template
<div class="dnd-demo__row">
<Drag
v-for="number in numbers"
:key="number"
class="dnd-demo__item"
type="number"
:data="number"
@cut="remove(number)"
>
{{ number }}
</Drag>
</div>
<div class="dnd-demo__grid" style="margin-top: 1rem">
<Drop
class="dnd-demo__zone"
:accepts-data="isEven"
@drop="record('Even', $event)"
>
<span class="dnd-demo__label">Copy even numbers</span>
</Drop>
<Drop
class="dnd-demo__zone"
:accepts-data="isOdd"
@drop="record('Odd', $event)"
>
<span class="dnd-demo__label">Copy odd numbers</span>
</Drop>
<Drop
class="dnd-demo__zone"
mode="cut"
@drop="record('Removed', $event)"
>
<span class="dnd-demo__label">Cut any number</span>
</Drop>
</div>TypeScript
import { ref } from 'vue';
import { Drag, Drop } from 'vue-easy-dnd';
import type { DnDEventPayload, DragData } from 'vue-easy-dnd';
const numbers = ref([1, 2, 3, 4, 5]);
const status = ref('Try each target');
const isEven = (data: DragData) => typeof data === 'number' && data % 2 === 0;
const isOdd = (data: DragData) => typeof data === 'number' && data % 2 === 1;
const remove = (number: number) => {
numbers.value = numbers.value.filter(value => value !== number);
};
const record = (target: string, event: DnDEventPayload) => {
status.value = `${target}: ${String(event.data)}`;
};
const reset = () => {
numbers.value = [1, 2, 3, 4, 5];
status.value = 'Try each target';
};