This library helps easily create a list of dom elements which can be sortable by drag and drop. The API design follows reusable views described in [evancz/elm-sortable-table]: https://github.com/evancz/elm-sortable-table.
Prepare a model which will be the content of the draggable target. Since this library does not care about what are contained, you can provide a model with any fields you want but including a field to compare the ordering. Also you need to supply two functions for the update function, the one is for setting the order, the other one is for getting the order from the Model. Finally you supply a View for your purpose.
Create the Config
for your view
and update
function.
import DragDrop
type Msg = DragDrop Image Image | ...
config : DragDrop.Config Image Msg
config =
DragDrop.config
{ onDrop = DragDrop
, htmlTag = "img"
, attributes = (\image -> [("src", image.src)])
}
You provide the following infomation in you configuration:
onDrop
— send a Msg with your data of dragged and dropped when drop event fired.htmlTag
— name of html tag to be rendered, which will be draggable.attributes
— list of extra attributes for the draggable element.
The model holds list of your data and State
of DragDrop library.
type alias Model =
{ images : List Image
, dragDropState : DragDrop.State Image
}
Your data is stored seprately from the library, you can provide any shape of your need.
type alias Image =
{ id : String
, order : Int
, src : String
}
type Msg
= DragDrop Image Image
| DragDropMsg (DragDrop.Msg Image)
DragDrop
— called when drop event is fired, in the update you need to swap dragged and dropped elements in you model.DragDropMsg
— map child message from parent to child.
imageView : Model -> Image -> Html Msg
imageView { dragDropState } target =
let
base =
[ ( "display", "flex" )
, ( "flex-direction", "column" )
, ( "padding", "5px" )
, ( "border", "2px solid #FFF" )
]
dragDropStyle =
case ( dragDropState.dragging, dragDropState.hovering ) of
( Just dragged, Just hovered ) ->
if target == dragged then
[ ( "opacity", "0.4" ) ]
else if target == hovered then
[ ( "border", "2px dashed #000" ) ]
else
[]
_ ->
[]
style_ =
base ++ dragDropStyle
in
div [ style base ]
[ Html.map DragDropMsg (DragDrop.view config style_ target)
, div []
[ text <| "id : " ++ target.id ]
]