Add API for combining form parsers into a type without the input type variable.

This commit is contained in:
Dillon Kearns 2022-08-23 11:41:29 -07:00
parent c549f94b8e
commit 7b6dab6c80
4 changed files with 200 additions and 51 deletions

View File

@ -12,7 +12,7 @@ import ErrorPage exposing (ErrorPage)
import Form
import Form.Field as Field
import Form.FieldView
import Form.Validation as Validation exposing (Combined, Field)
import Form.Validation as Validation exposing (Combined, Field, Validation)
import Head
import Head.Seo as Seo
import Html exposing (Html)
@ -100,7 +100,7 @@ type alias EnvVariables =
}
form : Form.DoneForm String (DataSource (Combined String Action)) data (List (Html (Pages.Msg.Msg Msg)))
form : Form.DoneForm String (DataSource (Combined String EmailAddress)) data (List (Html (Pages.Msg.Msg Msg)))
form =
Form.init
(\fieldEmail ->
@ -117,7 +117,7 @@ form =
(\emailSendResult ->
case emailSendResult of
Ok () ->
Validation.succeed (LI email)
Validation.succeed email
Err error ->
Validation.fail "Whoops, something went wrong sending an email to that address. Try again?" Validation.global
@ -146,11 +146,11 @@ form =
|> Form.hiddenKind ( "kind", "login" ) "Expected kind"
logoutForm : Form.DoneForm String Action data (List (Html (Pages.Msg.Msg Msg)))
logoutForm : Form.DoneForm String () data (List (Html (Pages.Msg.Msg Msg)))
logoutForm =
Form.init
{ combine =
Validation.succeed Logout
Validation.succeed ()
, view =
\info ->
[ Html.button []
@ -297,15 +297,20 @@ data routeParams =
)
allForms : Form.ServerForms String (DataSource (Combined String Action))
allForms =
logoutForm
|> Form.toServerForm
|> Form.initCombinedServer (\_ -> Logout)
|> Form.combineServer LI form
action : RouteParams -> Request.Parser (DataSource (Response ActionData ErrorPage))
action routeParams =
MySession.withSession
(Request.map2 Tuple.pair
(Request.oneOf
[ Request.formDataWithServerValidation
[ logoutForm |> Form.toServerForm
, form
]
[ Request.formDataWithServerValidation allForms
]
)
Request.requestTime

View File

@ -477,14 +477,13 @@ view maybeUrl sharedModel model app =
}
newItemForm : Form.HtmlForm String Action input Msg
newItemForm : Form.HtmlForm String String input Msg
newItemForm =
Form.init
(\description ->
{ combine =
Validation.succeed identity
|> Validation.andMap description
|> Validation.map Add
, view =
\formState ->
[ header
@ -505,9 +504,15 @@ newItemForm =
|> Form.hiddenKind ( "kind", "new-item" ) "Expected kind"
allForms : List (Form.HtmlForm String Action Todo Msg)
allForms : Form.ServerForms String Action
allForms =
[ editItemForm, newItemForm, completeItemForm, deleteItemForm, clearCompletedForm, toggleAllForm ]
editItemForm
|> Form.initCombined UpdateEntry
|> Form.combine Add newItemForm
|> Form.combine Check completeItemForm
|> Form.combine Delete deleteItemForm
|> Form.combine (\_ -> DeleteComplete) clearCompletedForm
|> Form.combine CheckAll toggleAllForm
@ -554,12 +559,12 @@ viewEntries app visibility entries =
]
toggleAllForm : Form.HtmlForm String Action input Msg
toggleAllForm : Form.HtmlForm String Bool input Msg
toggleAllForm =
Form.init
(\toggleTo ->
{ combine =
Validation.succeed CheckAll
Validation.succeed identity
|> Validation.andMap toggleTo
, view =
\formState ->
@ -633,7 +638,7 @@ viewEntry app todo =
]
completeItemForm : Form.HtmlForm String Action Todo Msg
completeItemForm : Form.HtmlForm String ( Bool, String ) Todo Msg
completeItemForm =
Form.init
(\todoId complete ->
@ -641,7 +646,6 @@ completeItemForm =
Validation.succeed Tuple.pair
|> Validation.andMap complete
|> Validation.andMap todoId
|> Validation.map Check
, view =
\formState ->
[ Html.button [ class "toggle" ]
@ -666,7 +670,7 @@ completeItemForm =
|> Form.hiddenKind ( "kind", "complete" ) "Expected kind"
editItemForm : Form.HtmlForm String Action Todo Msg
editItemForm : Form.HtmlForm String ( String, String ) Todo Msg
editItemForm =
Form.init
(\itemId description ->
@ -674,7 +678,6 @@ editItemForm =
Validation.succeed Tuple.pair
|> Validation.andMap itemId
|> Validation.andMap description
|> Validation.map UpdateEntry
, view =
\formState ->
[ FieldView.input
@ -700,12 +703,12 @@ editItemForm =
|> Form.hiddenKind ( "kind", "edit-item" ) "Expected kind"
deleteItemForm : Form.HtmlForm String Action Todo Msg
deleteItemForm : Form.HtmlForm String String Todo Msg
deleteItemForm =
Form.init
(\todoId ->
{ combine =
Validation.succeed Delete
Validation.succeed identity
|> Validation.andMap todoId
, view =
\formState ->
@ -807,10 +810,10 @@ visibilitySwap visibilityParam visibility actualVisibility =
]
clearCompletedForm : Form.HtmlForm String Action input Msg
clearCompletedForm : Form.HtmlForm String () input Msg
clearCompletedForm =
Form.init
{ combine = Validation.succeed DeleteComplete
{ combine = Validation.succeed ()
, view =
\formState ->
[ button

View File

@ -11,7 +11,13 @@ module Form exposing
, dynamic
, AppContext
, toServerForm, withOnSubmit
-- subGroup
, ServerForms(..)
-- subGroup
, combine
, combineServer
, initCombined
, initCombinedServer
)
{-| One of the core features of elm-pages is helping you manage form data end-to-end, including
@ -854,13 +860,13 @@ insertIfNonempty key values dict =
{-| -}
runServerSide :
List ( String, String )
-> Form error { all | combine : Validation error parsed kind constraints } data
-> Form error (Validation error parsed kind constraints) data
-> ( 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 }
, combineAndView : Validation error parsed kind constraints
}
parsed =
parser Nothing thisFormState
@ -881,7 +887,7 @@ runServerSide rawFormData (Form _ parser _) =
|> Dict.fromList
}
in
{ result = ( parsed.combineAndView.combine, parsed.result )
{ result = ( parsed.combineAndView, parsed.result )
}
|> mergeResults
|> unwrapValidation
@ -895,15 +901,9 @@ unwrapValidation (Pages.Internal.Form.Validation _ _ ( maybeParsed, errors )) =
{-| -}
runOneOfServerSide :
List ( String, String )
->
List
(Form
error
{ all | combine : Validation error parsed kind constraints }
data
)
-> ServerForms error parsed
-> ( Maybe parsed, Dict String (List error) )
runOneOfServerSide rawFormData parsers =
runOneOfServerSide rawFormData (ServerForms parsers) =
case parsers of
firstParser :: remainingParsers ->
let
@ -922,7 +922,7 @@ runOneOfServerSide rawFormData parsers =
( Just parsed, Dict.empty )
_ ->
runOneOfServerSide rawFormData remainingParsers
runOneOfServerSide rawFormData (ServerForms remainingParsers)
[] ->
-- TODO need to pass errors
@ -1422,6 +1422,157 @@ type alias HtmlForm error parsed input msg =
input
{-| -}
type ServerForms error parsed
= ServerForms
(List
(Form
error
(Combined error parsed)
Never
)
)
{-| -}
initCombined :
(parsed -> combined)
->
Form
error
{ combineAndView
| combine : Combined error parsed
}
input
-> ServerForms error combined
initCombined mapFn (Form _ parseFn _) =
ServerForms
[ Form
[]
(\_ formState ->
let
foo :
{ result : Dict String (List error)
, combineAndView : { combineAndView | combine : Combined error parsed }
}
foo =
parseFn Nothing formState
in
{ result = foo.result
, combineAndView = foo.combineAndView.combine |> Validation.map mapFn
}
)
(\_ -> [])
]
{-| -}
combine :
(parsed -> combined)
->
Form
error
{ combineAndView
| combine : Combined error parsed
}
input
-> ServerForms error combined
-> ServerForms error combined
combine mapFn (Form _ parseFn _) (ServerForms serverForms) =
ServerForms
(Form []
(\_ formState ->
let
foo :
{ result : Dict String (List error)
, combineAndView : { combineAndView | combine : Combined error parsed }
}
foo =
parseFn Nothing formState
in
{ result = foo.result
, combineAndView = foo.combineAndView.combine |> Validation.map mapFn
}
)
(\_ -> [])
:: serverForms
)
{-| -}
initCombinedServer :
(parsed -> combined)
->
Form
error
{ combineAndView
| combine : Combined error (DataSource (Validation error parsed kind constraints))
}
input
-> ServerForms error (DataSource (Validation error combined kind constraints))
initCombinedServer mapFn (Form _ parseFn _) =
ServerForms
[ Form
[]
(\_ formState ->
let
--foo :
-- { result : Dict String (List error)
-- , combineAndView : { combineAndView | combine : Combined error parsed }
-- }
foo :
{ result : Dict String (List error)
, combineAndView : { combineAndView | combine : Combined error (DataSource (Validation error parsed kind constraints)) }
}
foo =
parseFn Nothing formState
in
{ result = foo.result
, combineAndView = foo.combineAndView.combine |> Validation.map (DataSource.map (Validation.map mapFn))
}
)
(\_ -> [])
]
{-| -}
combineServer :
(parsed -> combined)
->
Form
error
{ combineAndView
| combine :
Combined error (DataSource (Validation error parsed kind constraints))
}
input
-> ServerForms error (DataSource (Validation error combined kind constraints))
-> ServerForms error (DataSource (Validation error combined kind constraints))
combineServer mapFn (Form _ parseFn _) (ServerForms serverForms) =
ServerForms
(Form []
(\_ formState ->
let
--foo :
-- { result : Dict String (List error)
-- , combineAndView : { combineAndView | combine : Combined error parsed }
-- }
foo :
{ result : Dict String (List error)
, combineAndView : { combineAndView | combine : Combined error (DataSource (Validation error parsed kind constraints)) }
}
foo =
parseFn Nothing formState
in
{ result = foo.result
, combineAndView = foo.combineAndView.combine |> Validation.map (DataSource.map (Validation.map mapFn))
}
)
(\_ -> [])
:: serverForms
)
{-| -}
type alias StyledHtmlForm error parsed data msg =
Form
@ -1451,17 +1602,17 @@ type FormInternal error parsed data view
{-| -}
type Form error combineAndView data
type Form error combineAndView input
= Form
(List ( String, FieldDefinition ))
(Maybe data
(Maybe input
-> FormState
->
{ result : Dict String (List error)
, combineAndView : combineAndView
}
)
(data -> List ( String, String ))
(input -> List ( String, String ))
type alias RenderOptions userMsg =

View File

@ -885,12 +885,7 @@ fileField_ name =
{-| -}
formDataWithServerValidation :
List
(Form.Form
error
{ all | combine : Validation error (DataSource (Validation error combined kind constraints)) kind constraints }
data
)
Form.ServerForms error (DataSource (Validation error combined kind constraints))
-> Parser (DataSource (Result (Form.Response error) ( Form.Response error, combined )))
formDataWithServerValidation formParsers =
rawFormData
@ -950,12 +945,7 @@ formDataWithServerValidation formParsers =
{-| -}
formData :
List
(Form.Form
error
{ all | combine : Validation error combined kind constraints }
data
)
Form.ServerForms error combined
-> Parser (Result { fields : List ( String, String ), errors : Dict String (List error) } combined)
formData formParsers =
rawFormData