Skip to content

Instantly share code, notes, and snippets.

@bsermons
Last active December 8, 2016 16:11
Show Gist options
  • Select an option

  • Save bsermons/ff11bf2fdd2f3a02642d to your computer and use it in GitHub Desktop.

Select an option

Save bsermons/ff11bf2fdd2f3a02642d to your computer and use it in GitHub Desktop.
Elm login example
module Login where
import Html exposing (..)
import Html.Attributes exposing (..)
import Html.Events exposing (on, onClick, targetValue)
import Http
import Json.Encode as Encode exposing (encode)
import Json.Decode as Decode
import String
import Task exposing (Task, andThen, onError)
import Debug
type Actions
= NoOp
| UpdateLogin String
| UpdatePassword String
| PostMessage String
| ShowErrors
type alias LoginViewModel =
{ login : String
, password : String
, signinAttempts : Int
, message : Maybe String
}
emptyModel =
{ login = ""
, password = ""
, signinAttempts = 0
, message = Nothing
}
loginUrl =
"http://localhost/login"
getErrors {login, password} =
let errors =
[ (String.isEmpty login, "Login is required.")
, (String.isEmpty password, "Password is required.")
]
in
List.filterMap (\(erred, msg) -> if erred then Just msg else Nothing) errors
errItem msg =
div [] [ text msg ]
onChange action =
on "change" targetValue (Signal.message actions.address << action)
field lbl typ action =
let lblWidth = style [("width", "120px")]
in
div [] [ label [ for lbl, lblWidth ] [ text lbl ]
, input [ name lbl, type' typ, onChange action ] []
]
encode model =
Encode.encode 0 (Encode.object
[ ("login", Encode.string model.login)
, ("password", Encode.string model.password)
])
loginSuccessHandler resp =
let _ = Debug.log "INFO(resp)" resp
in
Signal.send actions.address (PostMessage "Thanks for logging in.")
loginErrorHandler err =
let _ = Debug.log "INFO(err)" "ERROR"
in
Signal.send actions.address (PostMessage "Something went wrong.")
login model =
(Http.fromJson Decode.string
(Http.send Http.defaultSettings
{ verb = "POST"
, headers = [("Content-Type", "application/json")]
, url = loginUrl
, body = Http.string (encode model)
}))
`andThen` loginSuccessHandler
`onError` loginErrorHandler
loginClick model =
onClick taskMailbox.address (login model)
view : LoginViewModel -> Html
view model =
let errors = getErrors model
viewErrors = if model.signinAttempts > 0
then List.map errItem errors
else []
message = case model.message of
Nothing -> div [] []
Just msg -> div [] [ text msg ]
clickHandler = if List.length errors == 0
then loginClick model
else (onClick actions.address ShowErrors)
in
div []
[ h1 [] [ text "Sign In1" ]
, message
, field "Login" "text" UpdateLogin
, field "Password" "password" UpdatePassword
, button [ clickHandler ] [ text "Login" ]
, div [ class "errors" ] viewErrors
]
update action model =
case Debug.log "INFO" action of
UpdateLogin val ->
{ model | login <- val }
UpdatePassword val ->
{ model | password <- val }
ShowErrors ->
{ model | signinAttempts <- model.signinAttempts + 1}
PostMessage msg ->
{ model |
signinAttempts <- model.signinAttempts + 1,
message <- Just msg }
actions =
Signal.mailbox NoOp
taskMailbox =
Signal.mailbox (Task.succeed ())
port requestPort : Signal (Task x ())
port requestPort =
taskMailbox.signal
model =
Signal.foldp update emptyModel actions.signal
main =
Signal.map view model
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment