Remove server-side validation from field in favor of doing it within the combine function.

This commit is contained in:
Dillon Kearns 2022-08-03 09:33:16 +02:00
parent 985e79922c
commit 6a99994eb5
5 changed files with 48 additions and 153 deletions

View File

@ -146,14 +146,6 @@ form =
(Field.text
|> Field.required "Required"
|> Field.withInitialValue (.username >> Form.Value.string)
--|> Form.withServerValidation
-- (\username ->
-- if username == "asdf" then
-- DataSource.succeed [ "username is taken" ]
--
-- else
-- DataSource.succeed []
-- )
)
|> Form.field "email"
(Field.text

View File

@ -119,12 +119,21 @@ type alias Action =
}
formParser : Form.HtmlForm String Action Data msg
formParser : Form.DoneForm String (DataSource (Validation.Combined String Action)) Data (List (Html (Pages.Msg.Msg msg)))
formParser =
Form.init
(\username name ->
{ combine =
Validation.succeed Action
Validation.succeed
(\u n ->
toValidUsername u username
|> DataSource.map
(\vu ->
Validation.succeed Action
|> Validation.andMap vu
|> Validation.andMap (Validation.succeed n)
)
)
|> Validation.andMap username
|> Validation.andMap name
, view =
@ -171,16 +180,6 @@ formParser =
(Field.text
|> Field.required "Username is required"
|> Field.withClientValidation validateUsername
|> Field.withServerValidation
(\username ->
DataSource.succeed
(if username == "dillon123" then
[ "This username is taken" ]
else
[]
)
)
|> Field.withInitialValue (\{ user } -> Form.Value.string user.username)
)
|> Form.field "name"
@ -190,6 +189,17 @@ formParser =
)
toValidUsername : String -> Validation.Field String parsed1 field -> DataSource (Validation.Combined String String)
toValidUsername username usernameField =
DataSource.succeed
(if username == "dillon123" then
Validation.fail "This username is taken" usernameField
else
Validation.succeed username
)
validateUsername : String -> ( Maybe String, List String )
validateUsername rawUsername =
if rawUsername |> String.contains "@" then
@ -201,14 +211,14 @@ validateUsername rawUsername =
action : RouteParams -> Request.Parser (DataSource (Response ActionData ErrorPage))
action routeParams =
Request.formData [ formParser ]
Request.formDataWithServerValidation [ formParser ]
|> MySession.expectSessionDataOrRedirect (Session.get "userId" >> Maybe.map Uuid)
(\userId parsedActionData session ->
parsedActionData
|> DataSource.andThen
(\parsedAction ->
case parsedAction |> Debug.log "parsedAction" of
Ok { name } ->
Ok ( response, { name } ) ->
User.updateUser { userId = userId, name = name |> Debug.log "Updating name mutation" }
|> Request.Hasura.mutationDataSource
|> DataSource.map
@ -217,10 +227,10 @@ action routeParams =
)
|> DataSource.map (Tuple.pair session)
Err errors ->
Err (Form.Response errors) ->
-- TODO need to render errors here?
DataSource.succeed
(Response.render parsedAction)
(Response.render (Err errors))
|> DataSource.map (Tuple.pair session)
)
)

View File

@ -309,7 +309,6 @@ init combineAndView =
(\_ _ ->
{ result = Dict.empty
, combineAndView = combineAndView
, serverValidations = DataSource.succeed []
}
)
(\_ -> [])
@ -350,7 +349,6 @@ dynamic forms formBuilder =
->
{ result : Dict String (List error)
, combineAndView : { combine : Validation error parsed named constraints1, view : subView }
, serverValidations : DataSource (List ( String, List error ))
}
toParser decider =
case forms decider of
@ -361,14 +359,12 @@ dynamic forms formBuilder =
myFn :
{ result : Dict String (List error)
, combineAndView : combineAndView
, serverValidations : DataSource (List ( String, List error ))
}
myFn =
let
newThing :
{ result : Dict String (List error)
, combineAndView : { combine : decider -> Validation error parsed named constraints1, view : decider -> subView } -> combineAndView
, serverValidations : DataSource (List ( String, List error ))
}
newThing =
case formBuilder of
@ -393,7 +389,6 @@ dynamic forms formBuilder =
newThing.result
, combineAndView =
newThing.combineAndView arg
, serverValidations = DataSource.succeed [] -- TODO how do I combine them here?
}
in
myFn
@ -525,20 +520,13 @@ field name (Field fieldParser kind) (Form definitions parseFn toInitialValues) =
myFn :
{ result : Dict String (List error)
, combineAndView : Validation.Field error parsed kind -> combineAndView
, serverValidations : DataSource (List ( String, List error ))
}
->
{ result : Dict String (List error)
, combineAndView : combineAndView
, serverValidations : DataSource (List ( String, List error ))
}
myFn soFar =
let
serverValidationsForField : DataSource ( String, List error )
serverValidationsForField =
fieldParser.serverValidation rawFieldValue
|> DataSource.map (Tuple.pair name)
validationField : Validation.Field error parsed kind
validationField =
parsedField
@ -548,10 +536,6 @@ field name (Field fieldParser kind) (Form definitions parseFn toInitialValues) =
|> addErrorsInternal name errors
, combineAndView =
soFar.combineAndView validationField
, serverValidations =
DataSource.map2 (::)
serverValidationsForField
soFar.serverValidations
}
in
formState
@ -630,20 +614,13 @@ hiddenField name (Field fieldParser _) (Form definitions parseFn toInitialValues
myFn :
{ result : Dict String (List error)
, combineAndView : Validation.Field error parsed Form.FieldView.Hidden -> combineAndView
, serverValidations : DataSource (List ( String, List error ))
}
->
{ result : Dict String (List error)
, combineAndView : combineAndView
, serverValidations : DataSource (List ( String, List error ))
}
myFn soFar =
let
serverValidationsForField : DataSource ( String, List error )
serverValidationsForField =
fieldParser.serverValidation rawFieldValue
|> DataSource.map (Tuple.pair name)
validationField : Validation.Field error parsed Form.FieldView.Hidden
validationField =
parsedField
@ -653,10 +630,6 @@ hiddenField name (Field fieldParser _) (Form definitions parseFn toInitialValues
|> addErrorsInternal name errors
, combineAndView =
soFar.combineAndView validationField
, serverValidations =
DataSource.map2 (::)
serverValidationsForField
soFar.serverValidations
}
in
formState
@ -706,28 +679,16 @@ hiddenKind ( name, value ) error_ (Form definitions parseFn toInitialValues) =
myFn :
{ result : Dict String (List error)
, combineAndView : combineAndView
, serverValidations : DataSource (List ( String, List error ))
}
->
{ result : Dict String (List error)
, combineAndView : combineAndView
, serverValidations : DataSource (List ( String, List error ))
}
myFn soFar =
let
serverValidationsForField : DataSource ( String, List error )
serverValidationsForField =
fieldParser.serverValidation rawFieldValue
|> DataSource.map (Tuple.pair name)
in
{ result =
soFar.result
|> addErrorsInternal name errors
, combineAndView = soFar.combineAndView
, serverValidations =
DataSource.map2 (::)
serverValidationsForField
soFar.serverValidations
}
in
formState
@ -856,7 +817,6 @@ parse formId app data (Form _ parser _) =
parsed :
{ result : Dict String (List error)
, combineAndView : { info | combine : Validation error parsed named constraints }
, serverValidations : DataSource (List ( String, List error ))
}
parsed =
parser (Just data) thisFormState
@ -868,7 +828,6 @@ parse formId app data (Form _ parser _) =
|> Maybe.withDefault initFormState
in
{ result = ( parsed.combineAndView.combine, parsed.result )
, serverValidations = parsed.serverValidations
}
|> mergeResults
|> unwrapValidation
@ -888,13 +847,12 @@ insertIfNonempty key values dict =
runServerSide :
List ( String, String )
-> Form error { all | combine : Validation error parsed kind constraints } data
-> ( Maybe parsed, DataSource (Dict String (List error)) )
-> ( Maybe parsed, Dict String (List error) )
runServerSide rawFormData (Form _ parser _) =
let
parsed :
{ result : Dict String (List error)
, combineAndView : { all | combine : Validation error parsed kind constraints }
, serverValidations : DataSource (List ( String, List error ))
}
parsed =
parser Nothing thisFormState
@ -916,9 +874,9 @@ runServerSide rawFormData (Form _ parser _) =
}
in
{ result = ( parsed.combineAndView.combine, parsed.result )
, serverValidations = parsed.serverValidations
}
|> mergeResultsDataSource
|> mergeResults
|> unwrapValidation
{-| -}
@ -931,7 +889,6 @@ runServerSideWithoutServerValidations rawFormData (Form _ parser _) =
parsed :
{ result : Dict String (List error)
, combineAndView : { all | combine : Validation error parsed kind constraints }
, serverValidations : DataSource (List ( String, List error ))
}
parsed =
parser Nothing thisFormState
@ -953,7 +910,6 @@ runServerSideWithoutServerValidations rawFormData (Form _ parser _) =
}
in
{ result = ( parsed.combineAndView.combine, parsed.result )
, serverValidations = parsed.serverValidations
}
|> mergeResults
|> unwrapValidation
@ -1011,12 +967,12 @@ runOneOfServerSideWithServerValidations :
{ all | combine : Validation error parsed kind constraints }
data
)
-> ( Maybe parsed, DataSource (Dict String (List error)) )
-> ( Maybe parsed, Dict String (List error) )
runOneOfServerSideWithServerValidations rawFormData parsers =
case parsers of
firstParser :: remainingParsers ->
let
thing : ( Maybe parsed, DataSource (Dict String (List error)) )
thing : ( Maybe parsed, Dict String (List error) )
thing =
runServerSide rawFormData firstParser
in
@ -1030,7 +986,7 @@ runOneOfServerSideWithServerValidations rawFormData parsers =
[] ->
-- TODO need to pass errors
( Nothing, DataSource.succeed Dict.empty )
( Nothing, Dict.empty )
{-| -}
@ -1072,7 +1028,6 @@ type FinalForm error parsed data view
, Dict String (List error)
)
, view : view
, serverValidations : DataSource (List ( String, List error ))
}
)
(data -> List ( String, String ))
@ -1111,7 +1066,6 @@ toDynamicFetcher name (Form a b c) =
{ combine : Validation error parsed field constraints
, view : Context error data -> view
}
, serverValidations : DataSource (List ( String, List error ))
}
)
->
@ -1123,7 +1077,6 @@ toDynamicFetcher name (Form a b c) =
, Dict String (List error)
)
, view : Context error data -> view
, serverValidations : DataSource (List ( String, List error ))
}
)
transformB rawB =
@ -1135,14 +1088,12 @@ toDynamicFetcher name (Form a b c) =
{ combine : Validation error parsed field constraints
, view : Context error data -> view
}
, serverValidations : DataSource (List ( String, List error ))
}
foo =
rawB maybeData formState
in
{ result = ( foo.combineAndView.combine, foo.result )
, view = foo.combineAndView.view
, serverValidations = foo.serverValidations
}
in
FinalForm options a (transformB b) c
@ -1181,7 +1132,6 @@ toDynamicTransition name (Form a b c) =
{ combine : Validation error parsed field constraints
, view : Context error data -> view
}
, serverValidations : DataSource (List ( String, List error ))
}
)
->
@ -1193,7 +1143,6 @@ toDynamicTransition name (Form a b c) =
, Dict String (List error)
)
, view : Context error data -> view
, serverValidations : DataSource (List ( String, List error ))
}
)
transformB rawB =
@ -1205,14 +1154,12 @@ toDynamicTransition name (Form a b c) =
{ combine : Validation error parsed field constraints
, view : Context error data -> view
}
, serverValidations : DataSource (List ( String, List error ))
}
foo =
rawB maybeData formState
in
{ result = ( foo.combineAndView.combine, foo.result )
, view = foo.combineAndView.view
, serverValidations = foo.serverValidations
}
in
FinalForm options a (transformB b) c
@ -1387,7 +1334,6 @@ helperValues toHiddenInput maybe options formState data (FormInternal fieldDefin
parsed :
{ result : ( Validation error parsed named constraints, Dict String (List error) )
, view : Context error data -> List view
, serverValidations : DataSource (List ( String, List error ))
}
parsed =
parser (Just data) thisFormState
@ -1541,7 +1487,6 @@ type FormInternal error parsed data view
, Dict String (List error)
)
, view : view
, serverValidations : DataSource (List ( String, List error ))
}
)
(data -> List ( String, String ))
@ -1556,7 +1501,6 @@ type Form error combineAndView data
->
{ result : Dict String (List error)
, combineAndView : combineAndView
, serverValidations : DataSource (List ( String, List error ))
}
)
(data -> List ( String, String ))

View File

@ -6,7 +6,6 @@ module Form.Field exposing
, required, withClientValidation, withInitialValue, map
, email, password, search, telephone, url, textarea
, withMax, withMin, withStep, withMinLength, withMaxLength
, withServerValidation
, No(..), Yes(..)
)
@ -48,18 +47,12 @@ module Form.Field exposing
@docs withMax, withMin, withStep, withMinLength, withMaxLength
## Server Validations
@docs withServerValidation
## Phantom Options
@docs No, Yes
-}
import DataSource exposing (DataSource)
import Date exposing (Date)
import Dict exposing (Dict)
import Form.FieldView as FieldView exposing (Input, Options(..))
@ -75,7 +68,6 @@ type Field error parsed data kind constraints
{-| -}
type alias FieldInfo error parsed data =
{ initialValue : Maybe (data -> String)
, serverValidation : Maybe String -> DataSource (List error)
, decode : Maybe String -> ( Maybe parsed, List error )
, properties : List ( String, Encode.Value )
}
@ -91,32 +83,6 @@ type No
= No Never
{-| -}
withServerValidation : (value -> DataSource (List error)) -> Field error value data kind constraints -> Field error value data kind constraints
withServerValidation serverValidation (Field field kind) =
Field
{ field
| serverValidation =
\value ->
case value |> field.decode of
( Just decoded, [] ) ->
serverValidation decoded
( Just decoded, errors ) ->
DataSource.map2 (++)
(serverValidation decoded)
(DataSource.succeed errors)
( Nothing, _ ) ->
{- We can't decode the form data, which means there were errors previously in the pipeline
we return an empty list, effectively short-circuiting remaining validation and letting
the fatal errors propagate through
-}
DataSource.succeed []
}
kind
{-| -}
required :
error
@ -134,7 +100,6 @@ required :
required missingError (Field field kind) =
Field
{ initialValue = field.initialValue
, serverValidation = field.serverValidation
, decode =
\rawValue ->
let
@ -174,7 +139,6 @@ text :
text =
Field
{ initialValue = Nothing
, serverValidation = \_ -> DataSource.succeed []
, decode =
\rawValue ->
( if rawValue == Just "" then
@ -207,7 +171,6 @@ date :
date toError =
Field
{ initialValue = Nothing
, serverValidation = \_ -> DataSource.succeed []
, decode =
\rawString ->
if (rawString |> Maybe.withDefault "") == "" then
@ -256,7 +219,6 @@ time :
time toError =
Field
{ initialValue = Nothing
, serverValidation = \_ -> DataSource.succeed []
, decode =
\rawString ->
if (rawString |> Maybe.withDefault "") == "" then
@ -317,7 +279,6 @@ select optionsMapping invalidError =
in
Field
{ initialValue = Nothing
, serverValidation = \_ -> DataSource.succeed []
, decode =
\rawValue ->
case rawValue of
@ -367,7 +328,6 @@ exactValue :
exactValue initialValue error =
Field
{ initialValue = Just (\_ -> initialValue)
, serverValidation = \_ -> DataSource.succeed []
, decode =
\rawValue ->
if rawValue == Just initialValue then
@ -392,7 +352,6 @@ checkbox :
checkbox =
Field
{ initialValue = Nothing
, serverValidation = \_ -> DataSource.succeed []
, decode =
\rawString ->
( (rawString == Just "on")
@ -423,7 +382,6 @@ int :
int toError =
Field
{ initialValue = Nothing
, serverValidation = \_ -> DataSource.succeed []
, decode =
\rawString ->
case rawString of
@ -463,7 +421,6 @@ float :
float toError =
Field
{ initialValue = Nothing
, serverValidation = \_ -> DataSource.succeed []
, decode =
\rawString ->
case rawString of
@ -593,7 +550,6 @@ withClientValidation : (parsed -> ( Maybe mapped, List error )) -> Field error p
withClientValidation mapFn (Field field kind) =
Field
{ initialValue = field.initialValue
, serverValidation = field.serverValidation
, decode =
\value ->
value
@ -633,7 +589,6 @@ withMin : Form.Value.Value valueType -> error -> Field error parsed data kind {
withMin min error (Field field kind) =
Field
{ initialValue = field.initialValue
, serverValidation = field.serverValidation
, decode =
\value ->
value
@ -665,7 +620,6 @@ withMinLength : Int -> error -> Field error parsed data kind { constraints | min
withMinLength minLength error (Field field kind) =
Field
{ initialValue = field.initialValue
, serverValidation = field.serverValidation
, decode =
\value ->
value
@ -692,7 +646,6 @@ withMaxLength : Int -> error -> Field error parsed data kind { constraints | max
withMaxLength maxLength error (Field field kind) =
Field
{ initialValue = field.initialValue
, serverValidation = field.serverValidation
, decode =
\value ->
value
@ -724,7 +677,6 @@ withMax : Form.Value.Value valueType -> error -> Field error parsed data kind {
withMax max error (Field field kind) =
Field
{ initialValue = field.initialValue
, serverValidation = field.serverValidation
, decode =
\value ->
value

View File

@ -992,35 +992,32 @@ formData :
{ all | combine : Validation error combined kind constraints }
data
)
-> Parser (DataSource (Result { fields : List ( String, String ), errors : Dict String (List error) } combined))
-> Parser (Result { fields : List ( String, String ), errors : Dict String (List error) } combined)
formData formParsers =
rawFormData
|> andThen
(\rawFormData_ ->
let
( maybeDecoded, errorsDataSource ) =
( maybeDecoded, errors ) =
Form.runOneOfServerSideWithServerValidations
rawFormData_
formParsers
in
errorsDataSource
|> DataSource.map
(\errors ->
case ( maybeDecoded, errors |> Dict.toList |> List.filter (\( _, value ) -> value |> List.isEmpty |> not) |> List.NonEmpty.fromList ) of
( Just decoded, Nothing ) ->
Ok decoded
case ( maybeDecoded, errors |> Dict.toList |> List.filter (\( _, value ) -> value |> List.isEmpty |> not) |> List.NonEmpty.fromList ) of
( Just decoded, Nothing ) ->
Ok decoded
|> succeed
( _, maybeErrors ) ->
Err
{ fields = rawFormData_
, errors =
maybeErrors
|> Maybe.map List.NonEmpty.toList
|> Maybe.withDefault []
|> Dict.fromList
}
)
|> succeed
( _, maybeErrors ) ->
Err
{ fields = rawFormData_
, errors =
maybeErrors
|> Maybe.map List.NonEmpty.toList
|> Maybe.withDefault []
|> Dict.fromList
}
|> succeed
)