Created
March 2, 2016 12:30
-
-
Save newlandsvalley/c3f67710eb9520768845 to your computer and use it in GitHub Desktop.
Disable a button in elm whilst the task which it kicks off is in flight
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 Disable where | |
{- | |
This gist shows one method of temporarily disabling a button whilst a task (which it has kicked off) | |
is in flight. My need to do this comes from an audio 'play' button which kicks of an audio | |
'play sounds' task. Although the task returns immediately, I know the duration of the sound clip | |
so I suspend the UI whilst the clip is played. The trick is to split the 'play' task into two parts | |
so that the view has the chance to update in between them. The first action (Play) disables the button | |
and plays the clip, the second action (ShowButton) re-enables the button. | |
Many thanks to Max GoldStein and Dave Keen on elm-discuss for their helpful suggestions. | |
-} | |
import Effects exposing (Effects, Never, task) | |
import Html exposing (..) | |
import Html.Attributes exposing (..) | |
import Html.Events exposing (onClick) | |
import Task exposing (Task, andThen, succeed) | |
import String exposing (..) | |
import Debug exposing (..) | |
-- MODEL | |
type alias Model = | |
{ | |
buttonDisabled : Bool | |
} | |
init : String -> (Model, Effects Action) | |
init topic = | |
( { | |
buttonDisabled = False | |
} | |
, Effects.none | |
) | |
-- UPDATE | |
type Action | |
= NoOp | |
| Play | |
| ShowButton | |
update : Action -> Model -> (Model, Effects Action) | |
update action model = | |
case (log "action" action) of | |
NoOp -> (model, Effects.none ) | |
Play -> ({model | buttonDisabled = True } , play ) | |
ShowButton -> ( {model | buttonDisabled = False } , Effects.none ) | |
{- play the clip, supend the UI and then set the next action to ShowButton -} | |
play : Effects Action | |
play = | |
playAndSuspend | |
|> Task.map (\_ -> ShowButton) | |
|> Effects.task | |
{- play the task and suspend the UI -} | |
playAndSuspend : Task Never Action | |
playAndSuspend = | |
succeed (True) -- this task just simulates the player which actually returns immediately | |
`andThen` (\_ -> suspend 5) | |
{- sleep for a number od seconds -} | |
suspend : Int -> Task Never Action | |
suspend secs = | |
let | |
time = 1000 * secs | |
in | |
Task.sleep time | |
`andThen` (\_ -> succeed (NoOp)) | |
{- just the ShowButton action wrapped in a Task -} | |
showButton : Task Never Action | |
showButton = succeed (ShowButton) | |
-- VIEW | |
view : Signal.Address Action -> Model -> Html | |
view address model = | |
div [] | |
[ | |
h1 [ bStyle ] [ text ("test disabling buttons - disabled " ++ toString model.buttonDisabled)] | |
, div | |
[ bStyle ] | |
-- I'm trying to wait a few seconds before disabling the button | |
[ button [ onClick address Play, disabled model.buttonDisabled ] [ text "play" ] | |
] | |
] | |
bStyle : Attribute | |
bStyle = | |
style | |
[ | |
("text-align", "center") | |
, ("margin", "auto") | |
] | |
-- INPUTS | |
signals : List (Signal Action) | |
signals = [] | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment