DnD Source
Influenced by react-dnd
, we have concept of:
- DnD source, a DOM element that you can drag, plus associated logic.
- DnD target, a DOM element that you can drop onto, plus associated logic.
Since the source and target are bound to DOM element, you need to register and deregister them in the right Aurelia life-cycle callbacks.
The common practice is to do
addSource
,addTarget
inattached()
, and doremoveSource
,removeTarget
indetached()
.
Let’s implement our first example “move box” step by step.
There is a container of three boxes inside. To implement moving box, we register every box as a source (we want to drag), and register the container as the target (receives a drop).
Implement source
The box component.
export class Box {
// ...
attached() {
this.dndService.addSource(this);
}
detached() {
this.dndService.removeSource(this);
}
}
dndService.addSource(delegate, options)
takes two arguments.
- most of the time
delegate
object is the current Aurelia component (this
). options
is optional, they alter default behaviour. We will explore options in next few pages.
The first thing that a source delegate
needs to provide, is a reference to the DOM element we want to drag.
By default,
DndService
get DOM element fromdelegate.dndElement
. The easiest way to set that reference is to useref="dndElement"
in your view template.
<template>
<require from="./box.css"></require>
<div
ref="dndElement"
class="box"
style.bind="positionCss"
>
${item.name}
</div>
</template>
When you use
ref="dndElement"
in view template, Aurelia (notDndService
) creates a propertydndElement
in your component pointing to the DOM element, you can accessthis.dndElement
inside your component code.
Note,
removeSource()
andremoveTarget()
can be called with eitherdelegate
object or element object. So in here,this.dndService.removeSource(this.dndElement)
works same asthis.dndService.removeSource(this)
.
Now DOM is hooked up, source delegate
needs to provide dndModel()
callback, it should return a model which describes the meaning of the drag.
When
DndService
detected user started a drag, it asks (only once) the sourcedelegate
dndModel()
callback to return a model.
export class Box {
//...
dndModel() {
return {
type: 'moveItem',
item: this.item
};
}
//...
}
DndService
has zero requirement on the shape of the model. Even if you returnundefined
,DndService
would not complain, although there is no practical usage of returningundefined
.
You should make your own convention of the model shape. A common practice is to provide a
type
in the model, which you can easily check against in other parts of your app.
Here is what we got so far, movable boxes
There is no effect on drop, because we have not registered any DnD target yet.
Let’s move on to understand DnD Preview.