Skip to content

Instantly share code, notes, and snippets.

@gabehollombe
Created July 26, 2016 08:04
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save gabehollombe/45cb6f61ccb270931ded71f155ca37fe to your computer and use it in GitHub Desktop.
Save gabehollombe/45cb6f61ccb270931ded71f155ca37fe to your computer and use it in GitHub Desktop.
Example solution for Exercises from the Elm guide chapter on Forms
module Main exposing (..)
import Html exposing (..)
import Html.App as Html
import Html.Attributes exposing (..)
import Html.Events exposing (onInput, onClick)
import List exposing (..)
import String exposing (..)
import Char exposing (..)
main : Program Never
main =
Html.beginnerProgram { model = model, view = view, update = update }
-- MODEL
type alias Model =
{ name : String
, age : String
, password : String
, passwordAgain : String
, validationErrors : List String
}
model : Model
model =
Model "" "" "" "" []
-- UPDATE
type Msg
= Name String
| Age String
| Password String
| PasswordAgain String
| Validate
update : Msg -> Model -> Model
update msg model =
case msg of
Name name ->
{ model | name = name }
Age age ->
{ model | age = age }
Password password ->
{ model | password = password }
PasswordAgain password ->
{ model | passwordAgain = password }
Validate ->
{ model | validationErrors = validate model }
-- VIEW
view : Model -> Html Msg
view model =
div []
[ input [ type' "text", placeholder "Name", onInput Name ] []
, input [ type' "text", placeholder "Age", onInput Age ] []
, input [ type' "password", placeholder "Password", onInput Password ] []
, input [ type' "password", placeholder "Re-enter Password", onInput PasswordAgain ] []
, viewValidation model
, button [ onClick Validate ] [ text "Submit" ]
]
type alias Validator =
{ f : Model -> Bool, error : String }
checkValidator : Model -> Validator -> String
checkValidator model validator =
if not (validator.f model) then
validator.error
else
""
validate : Model -> List String
validate model =
let
isPositiveInt =
(\s -> (Result.withDefault 0 (String.toInt s)) > 0)
ageIsInt =
Validator (\m -> isPositiveInt m.age) "Age must be a positive integer!"
passwordsMatch =
Validator (\m -> m.password == m.passwordAgain) "Passwords do not match!"
passwordLength =
Validator (\m -> String.length m.password >= 8) "Password must be at least 8 characters!"
passwordHasCapital =
Validator (\m -> String.any isUpper m.password) "Password must have a capital letter."
passwordHasLowercase =
Validator (\m -> String.any isLower m.password) "Password must have a lowercase letter."
passwordHasNumber =
Validator (\m -> String.any isDigit m.password) "Password must have a number."
validators =
[ ageIsInt, passwordsMatch, passwordLength, passwordHasCapital, passwordHasLowercase, passwordHasNumber ]
in
validators
|> List.map (checkValidator model)
|> List.filter (not << String.isEmpty)
viewValidation : Model -> Html msg
viewValidation model =
let
( color, errorLIs ) =
if List.length model.validationErrors > 0 then
( "red", List.map (\e -> li [] [ text e ] ) model.validationErrors )
else
( "green", [] )
in
div [ style [ ( "color", color ) ] ] [ ul [] errorLIs ]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment