Add function to include client-side validation.

This commit is contained in:
Dillon Kearns 2022-01-06 09:44:46 -08:00
parent e22d688920
commit e042393830
3 changed files with 86 additions and 4 deletions

View File

@ -207,6 +207,14 @@ form user =
"first"
(textInput "First name")
|> Form.withInitialValue user.first
|> Form.withClientValidation
(\first ->
if first |> String.toList |> List.head |> Maybe.withDefault 'a' |> Char.isUpper then
Ok first
else
Err "Needs to be capitalized"
)
|> Form.required
)
|> Form.with
@ -412,7 +420,7 @@ page =
update _ _ _ _ msg model =
case msg of
FormMsg formMsg ->
( { model | form = model.form |> Form.update formMsg }, Cmd.none )
( { model | form = model.form |> Form.update (form defaultUser) formMsg }, Cmd.none )
init _ _ static =

View File

@ -7,6 +7,7 @@ import Html exposing (Html)
import Html.Attributes as Attr
import Html.Events
import Json.Encode as Encode
import List.Extra
import List.NonEmpty
import Server.Request as Request exposing (Request)
@ -102,8 +103,40 @@ type alias Model =
Dict String { raw : Maybe String, errors : List String }
update : Msg -> Model -> Model
update msg model =
runValidation : Form value view -> { name : String, value : String } -> List String
runValidation (Form fields decoder serverValidations modelToValue) newInput =
let
matchingDecoder : Maybe (FieldInfoSimple view)
matchingDecoder =
fields
|> List.Extra.findMap
(\( fields_, _ ) ->
List.Extra.findMap
(\field ->
if field.name == newInput.name then
Just field
else
Nothing
)
fields_
)
in
case matchingDecoder of
Just decoder_ ->
case decoder_.clientValidations (Just newInput.value) of
Ok () ->
[]
Err error ->
[ error ]
Nothing ->
[]
update : Form value view -> Msg -> Model -> Model
update form msg model =
case msg of
OnFieldInput { name, value } ->
-- TODO run client-side validations
@ -113,7 +146,7 @@ update msg model =
case entry of
Just { raw, errors } ->
-- TODO calculate errors here?
Just { raw = Just value, errors = errors }
Just { raw = Just value, errors = runValidation form { name = name, value = value } }
Nothing ->
-- TODO calculate errors here?
@ -661,6 +694,24 @@ withServerValidation serverValidation (Field field) =
}
withClientValidation : (value -> Result String mapped) -> Field value view -> Field mapped view
withClientValidation mapFn (Field field) =
Field
{ name = field.name
, initialValue = field.initialValue
, type_ = field.type_
, required = field.required
, serverValidation = field.serverValidation
, toHtml = field.toHtml
, decode =
\value ->
value
|> field.decode
|> Result.andThen mapFn
, properties = field.properties
}
with : Field value view -> Form (value -> form) view -> Form form view
with (Field field) (Form fields decoder serverValidations modelToValue) =
let

View File

@ -40,6 +40,29 @@ all =
)
|> Expect.equal
(Err [ "Expected a date in ISO 8601 format" ])
, test "custom client validation" <|
\() ->
Form.succeed identity
|> Form.with
(Form.text "first" toInput
|> Form.withClientValidation
(\first ->
if first |> String.toList |> List.head |> Maybe.withDefault 'a' |> Char.isUpper then
Ok first
else
Err "Needs to be capitalized"
)
)
|> Form.runClientValidations
(Dict.fromList
[ ( "first"
, { raw = Just "jane", errors = [] }
)
]
)
|> Expect.equal
(Err [ "Needs to be capitalized" ])
]