Example app demonstrating a list with drag and drop reordering.
- Make sure you have elm 0.18 installed
- The example also needs the Mouse package
- Copy or clone the 2 files from the /src folder
- You can run elm-sortable-table.elm in elm-reactor
The example uses subscriptions to Mouse.moves
and Mouse.ups
to track the drag movement in the vertical axis.
The basic drag function is an adaption from the drag example on
https://elm-lang.org/examples/drag
Combined with styles for animation, and a helper function to move the dragged item to the new position.
For readability of the main app, the styles have been placed in a separate Styles.elm module.
The app's main model keeps track of:
- Indicate whether app is in reorderable state (top-right button)
isReordering : Bool
- List of
data : List String
- Possible drag tracking
drag : Maybe Drag
The Drag
is a record containing:
- index of the item being moved
- startY position of the mouse
- currentY position of the mouse
The difference between currentY and startY is used to move the item while dragging.
The app's update function handles the following message types:
ToggleReorder
- to turn reordering state on or offDragStart Int Position
- start of drag, with index of item clicked + mouse positionDragAt Position
- a mouse movement with new mouse positionDragEnd Position
- a mouse up event to drop the item
The DragStart
message is generated by a (custom) onMouseDown
event on an item from the list.
The DragAt
and DragEnd
messages are both generated by a subscription.
The DragEnd
message calls a helper function, that moves the item to its new location in the list.
Since the items have a known height of 50px,
the calculation of the offset (how many items to move up or down)
is relatively straightforward.
The offset is based on pixels of drag that took place (currentY - startY), divided by 50.
Some correction is done to round up or down if dragged for about half an item.
Once an item is in drag mode - the view derives this from the drag state in the model - a styles are added to lift it visually, and put it in front of all other items in the list.
The currentY and startY are used to determine the position of the dragged item.
This is translated to a transform: translateY()
style on the item for display.
For all the other items in the list, the view checks whether the item being dragged is
above or passed it, to make room for the dragged item by shifting up or down.
With styles, a transition is added, so the items slide smoothly beneath the dragged item.