-
-
Save szabba/4b4152fb8478e4960eea to your computer and use it in GitHub Desktop.
Dropdown in Elm
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module Dropdown where | |
import List exposing (..) | |
import Html exposing (..) | |
import Html.Attributes exposing (style) | |
import Html.Events exposing (onClick, onBlur) | |
-- MODEL | |
type alias Item = | |
{ label : String | |
, id : Int | |
} | |
isSelected : Int -> Item -> Bool | |
isSelected id item = | |
id == item.id | |
type alias Model = | |
{ options : List Item | |
, selected : Int | |
, open : Bool | |
} | |
-- UPDATE | |
type Action = Click | Blur | Select Int | |
update : Action -> Model -> Model | |
update action model = | |
case action of | |
Click -> { model | open = not model.open } | |
Blur -> { model | open = False } | |
Select a -> { model | selected = a | |
, open = False } | |
outMenu : Model -> Model | |
outMenu model = | |
update Blur model | |
-- VIEW | |
itemView : Signal.Address Action -> Int -> Item -> Html | |
itemView address selected item = | |
div [ onClick address (Select item.id) | |
, onBlur address Blur | |
, itemStyle | |
] | |
[ text (if selected == item.id | |
then "Selected" | |
else item.label )] | |
view : Signal.Address Action -> Model -> Html | |
view address model = | |
div [] | |
[ button [ onClick address Click | |
, itemStyle | |
] | |
(let selectedItem = head (filter (isSelected model.selected) model.options) | |
in | |
[ text (case selectedItem of | |
Just value -> value.label | |
Nothing -> "Select") | |
]) | |
, if model.open | |
then | |
let n = length model.options | |
in | |
ul [] (map (itemView address model.selected) model.options) | |
else div [] [ text "" ] | |
] | |
itemStyle : Attribute | |
itemStyle = | |
style | |
[ ("font-size", "14px") | |
, ("border-style", "solid") | |
, ("border-width", "1px") | |
, ("width", "70px") | |
] | |
countStyle : Attribute | |
countStyle = | |
style | |
[ ("font-size", "20px") | |
, ("font-family", "monospace") | |
, ("display", "inline-block") | |
, ("width", "50px") | |
, ("text-align", "center") | |
] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Html exposing (..) | |
import StartApp exposing (start) | |
import Dropdown | |
import Effects | |
import Task | |
import Mouse | |
import Keyboard | |
-- Model -- | |
dropdownA : Dropdown.Model | |
dropdownA = { open = False | |
, selected = 0 | |
, options = [ { id = 1, label = "Abeja" } | |
, { id = 2, label = "Boa" } | |
, { id = 3, label = "Cuervo" } | |
] | |
} | |
dropdownB : Dropdown.Model | |
dropdownB = { open = False | |
, selected = 0 | |
, options = [ { id = 4, label = "Azul" } | |
, { id = 5, label = "Bordo" } | |
, { id = 6, label = "Celeste" } | |
] | |
} | |
type alias Model = | |
{ dropdownA : Dropdown.Model | |
, dropdownB : Dropdown.Model | |
} | |
initState : Model | |
initState = { dropdownA = dropdownA | |
, dropdownB = dropdownB | |
} | |
-- Update -- | |
type Action | |
= A Dropdown.Action | |
| B Dropdown.Action | |
| Out | |
| NoOp | |
onlyModel : Model -> ( Model, Effects.Effects Action ) | |
onlyModel m = (m, Effects.none) | |
update : Action -> Model -> ( Model, Effects.Effects Action ) | |
update action model = | |
case action of | |
A act -> | |
onlyModel { model | dropdownA = Dropdown.update act model.dropdownA } | |
B act -> | |
onlyModel { model | dropdownB = Dropdown.update act model.dropdownB } | |
Out -> | |
onlyModel { model | |
| dropdownA = Dropdown.outMenu model.dropdownA | |
, dropdownB = Dropdown.outMenu model.dropdownB } | |
NoOp -> | |
onlyModel model | |
-- View -- | |
view : Signal.Address Action -> Model -> Html | |
view address model = | |
div [] | |
[ Dropdown.view (Signal.forwardTo address A) model.dropdownA | |
, Dropdown.view (Signal.forwardTo address B) model.dropdownB | |
] | |
-- INPUTS | |
isEsc : Bool -> Action | |
isEsc esc = | |
if esc == True | |
then Out | |
else NoOp | |
inputs : List (Signal Action) | |
inputs = | |
[ Signal.map (\_ -> Out ) Mouse.clicks | |
, Signal.map isEsc (Keyboard.isDown 27) | |
] | |
-- MAIN | |
init = (initState, Effects.none) | |
app = start | |
{ init = init | |
, view = view | |
, update = update | |
, inputs = inputs | |
} | |
main = | |
app.html | |
port tasks : Signal (Task.Task Effects.Never ()) | |
port tasks = | |
app.tasks |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment