Checkboxes in Elm
Demo
Source Code
import Browser
import Html exposing (Html, div, label, input, text, span, button)
import Html.Attributes exposing (type_, checked)
import Html.Events exposing (onClick)
type alias Checkbox a =
{ id: String
, checked: Bool
, value: a
}
type alias Checkboxes a = List (Checkbox a)
getChecked : Checkboxes a -> Checkboxes a
getChecked checkboxes =
List.filter .checked checkboxes
getNotChecked : Checkboxes a -> Checkboxes a
getNotChecked checkboxes =
List.filter (\c -> not c.checked) checkboxes
filter : Filter -> Checkboxes a -> Checkboxes a
filter filt checkboxes =
case filt of
Checked ->
getChecked checkboxes
NotChecked ->
getNotChecked checkboxes
None ->
checkboxes
toggle : Checkbox a -> Checkboxes a -> Checkboxes a
toggle {id} checkboxes =
List.map (\checkbox ->
if id == checkbox.id then
{ checkbox | checked = not checkbox.checked }
else checkbox
) checkboxes
toHtml : (Checkbox a -> msg) -> (a -> String) -> Checkbox a -> Html msg
toHtml msg toString checkbox =
label
[]
[ input
[ type_ "checkbox"
, onClick (msg checkbox)
, checked checkbox.checked
]
[]
, span [] []
, text (toString checkbox.value)
]
display : (Checkbox a -> msg) -> (a -> String) -> Checkboxes a -> Html msg
display msg toString checkboxes =
let
divs =
List.map (\checkbox ->
div
[]
[ (toHtml msg toString checkbox) ]
) checkboxes
in
div [] divs
-- MAIN
main =
Browser.element
{ init = init
, view = view
, update = update
, subscriptions = subscriptions
}
type Filter
= Checked
| NotChecked
| None
type alias Model =
{ checkboxes : Checkboxes String
, filter : Filter
}
type Msg
= Toggle (Checkbox String)
| SetFilter Filter
init : () -> (Model, Cmd Msg)
init _ =
let
model =
{ checkboxes =
[ { id = "c1"
, checked = False
, value = "Checkbox 1"
}
, { id = "c2"
, checked = False
, value = "Checkbox 2"
}
, { id = "c3"
, checked = False
, value = "Checkbox 3"
}
]
, filter = None
}
in
(model, Cmd.none)
update : Msg -> Model -> (Model, Cmd Msg)
update msg model =
case msg of
Toggle checkbox ->
({ model | checkboxes = toggle checkbox model.checkboxes }, Cmd.none)
SetFilter filt ->
({ model | filter = filt }, Cmd.none)
subscriptions : Model -> Sub Msg
subscriptions model =
Sub.none
view : Model -> Html Msg
view model =
div
[]
[ display (\c -> Toggle c) identity (filter model.filter model.checkboxes)
, button
[ onClick (SetFilter None) ]
[ text "All" ]
, button
[ onClick (SetFilter Checked) ]
[ text "Checked"]
, button
[ onClick (SetFilter NotChecked) ]
[ text "Not checked" ]
]