mirror of
https://github.com/dillonkearns/elm-pages-v3-beta.git
synced 2024-11-28 06:05:31 +03:00
Add way to provide default values from DataSource.
This commit is contained in:
parent
68cfe7019f
commit
156c843926
@ -6,6 +6,7 @@ import DataSource exposing (DataSource)
|
||||
import Dict exposing (Dict)
|
||||
import Effect exposing (Effect)
|
||||
import ErrorPage exposing (ErrorPage)
|
||||
import Form.Value
|
||||
import Head
|
||||
import Head.Seo as Seo
|
||||
import Html exposing (Html)
|
||||
@ -62,18 +63,7 @@ init :
|
||||
-> ( Model, Effect Msg )
|
||||
init maybePageUrl sharedModel static =
|
||||
( {}
|
||||
, Effect.batch
|
||||
[ Effect.SetField
|
||||
{ formId = "test"
|
||||
, name = "username"
|
||||
, value = static.data.user.username
|
||||
}
|
||||
, Effect.SetField
|
||||
{ formId = "test"
|
||||
, name = "name"
|
||||
, value = static.data.user.name
|
||||
}
|
||||
]
|
||||
, Effect.none
|
||||
)
|
||||
|
||||
|
||||
@ -127,12 +117,8 @@ type alias Action =
|
||||
}
|
||||
|
||||
|
||||
newDecoder :
|
||||
FormParser.CombinedParser
|
||||
String
|
||||
{ username : String, name : String }
|
||||
(FormParser.Context String -> ( List (Html.Attribute msg), List (Html msg) ))
|
||||
newDecoder =
|
||||
formParser : FormParser.HtmlForm String { username : String, name : String } Data msg
|
||||
formParser =
|
||||
FormParser.andThenNew
|
||||
(\username name ->
|
||||
FormParser.ok
|
||||
@ -186,10 +172,12 @@ newDecoder =
|
||||
(Field.text
|
||||
|> Field.required "Username is required"
|
||||
|> Field.withClientValidation validateUsername
|
||||
|> Field.withInitialValue (\{ user } -> Form.Value.string user.username)
|
||||
)
|
||||
|> FormParser.field "name"
|
||||
(Field.text
|
||||
|> Field.required "Name is required"
|
||||
|> Field.withInitialValue (\{ user } -> Form.Value.string user.name)
|
||||
)
|
||||
|
||||
|
||||
@ -205,7 +193,7 @@ validateUsername rawUsername =
|
||||
action : RouteParams -> Request.Parser (DataSource (Response ActionData ErrorPage))
|
||||
action routeParams =
|
||||
Request.map2 Tuple.pair
|
||||
(Request.formParserResultNew newDecoder)
|
||||
(Request.formParserResultNew formParser)
|
||||
Request.requestTime
|
||||
|> MySession.expectSessionDataOrRedirect (Session.get "userId" >> Maybe.map Uuid)
|
||||
(\userId ( parsedAction, requestTime ) session ->
|
||||
@ -264,6 +252,6 @@ view maybeUrl sharedModel model app =
|
||||
]
|
||||
[ Html.button [ Attr.name "kind", Attr.value "signout" ] [ Html.text "Sign out" ] ]
|
||||
]
|
||||
, FormParser.renderHtml app newDecoder
|
||||
, FormParser.renderHtml app formParser
|
||||
]
|
||||
}
|
||||
|
@ -1,20 +1,19 @@
|
||||
module Pages.Field exposing (..)
|
||||
|
||||
import DataSource exposing (DataSource)
|
||||
import Form.Value
|
||||
import Json.Encode as Encode
|
||||
|
||||
|
||||
type Field error parsed constraints
|
||||
= Field (FieldInfo error parsed)
|
||||
type Field error parsed data constraints
|
||||
= Field (FieldInfo error parsed data)
|
||||
|
||||
|
||||
type alias FieldInfo error parsed =
|
||||
{ --, initialValue : Maybe String
|
||||
type_ : String
|
||||
type alias FieldInfo error parsed data =
|
||||
{ initialValue : Maybe (data -> String)
|
||||
, type_ : String
|
||||
, required : Bool
|
||||
, serverValidation : Maybe String -> DataSource (List error)
|
||||
|
||||
--, decode : String -> Form.FormState -> ( Maybe parsed, List error )
|
||||
, decode : Maybe String -> ( Maybe parsed, List error )
|
||||
, properties : List ( String, Encode.Value )
|
||||
}
|
||||
@ -37,14 +36,16 @@ required :
|
||||
Field
|
||||
error
|
||||
(Maybe parsed)
|
||||
data
|
||||
{ constraints
|
||||
| required : ()
|
||||
, wasMapped : No
|
||||
}
|
||||
-> Field error parsed { constraints | wasMapped : No }
|
||||
-> Field error parsed data { constraints | wasMapped : No }
|
||||
required missingError (Field field) =
|
||||
Field
|
||||
{ type_ = field.type_
|
||||
{ initialValue = field.initialValue
|
||||
, type_ = field.type_
|
||||
, required = True
|
||||
, serverValidation = field.serverValidation
|
||||
, decode =
|
||||
@ -64,6 +65,7 @@ text :
|
||||
Field
|
||||
error
|
||||
(Maybe String)
|
||||
data
|
||||
{ required : ()
|
||||
, plainText : ()
|
||||
, wasMapped : No
|
||||
@ -71,7 +73,8 @@ text :
|
||||
}
|
||||
text =
|
||||
Field
|
||||
{ type_ = "text"
|
||||
{ initialValue = Nothing
|
||||
, type_ = "text"
|
||||
, required = False
|
||||
, serverValidation = \_ -> DataSource.succeed []
|
||||
, decode =
|
||||
@ -92,11 +95,13 @@ checkbox :
|
||||
Field
|
||||
error
|
||||
Bool
|
||||
data
|
||||
{ required : ()
|
||||
}
|
||||
checkbox =
|
||||
Field
|
||||
{ type_ = "checkbox"
|
||||
{ initialValue = Nothing
|
||||
, type_ = "checkbox"
|
||||
, required = False
|
||||
, serverValidation = \_ -> DataSource.succeed []
|
||||
, decode =
|
||||
@ -116,6 +121,7 @@ int :
|
||||
Field
|
||||
error
|
||||
(Maybe Int)
|
||||
data
|
||||
{ min : Int
|
||||
, max : Int
|
||||
, required : ()
|
||||
@ -124,7 +130,8 @@ int :
|
||||
}
|
||||
int toError =
|
||||
Field
|
||||
{ type_ = "number"
|
||||
{ initialValue = Nothing
|
||||
, type_ = "number"
|
||||
, required = False
|
||||
, serverValidation = \_ -> DataSource.succeed []
|
||||
, decode =
|
||||
@ -148,10 +155,11 @@ int toError =
|
||||
|
||||
|
||||
{-| -}
|
||||
withClientValidation : (parsed -> ( Maybe mapped, List error )) -> Field error parsed constraints -> Field error mapped { constraints | wasMapped : Yes }
|
||||
withClientValidation : (parsed -> ( Maybe mapped, List error )) -> Field error parsed data constraints -> Field error mapped data { constraints | wasMapped : Yes }
|
||||
withClientValidation mapFn (Field field) =
|
||||
Field
|
||||
{ type_ = field.type_
|
||||
{ initialValue = field.initialValue
|
||||
, type_ = field.type_
|
||||
, required = field.required
|
||||
, serverValidation = field.serverValidation
|
||||
, decode =
|
||||
@ -171,3 +179,13 @@ withClientValidation mapFn (Field field) =
|
||||
)
|
||||
, properties = field.properties
|
||||
}
|
||||
|
||||
|
||||
{-| -}
|
||||
withInitialValue : (data -> Form.Value.Value valueType) -> Field error value data { constraints | initial : valueType } -> Field error value data constraints
|
||||
withInitialValue toInitialValue (Field field) =
|
||||
Field
|
||||
{ field
|
||||
| initialValue =
|
||||
Just (toInitialValue >> Form.Value.toString)
|
||||
}
|
||||
|
@ -25,7 +25,8 @@ type Event
|
||||
|
||||
|
||||
type alias FieldEvent =
|
||||
{ formId : String
|
||||
{ value : String
|
||||
, formId : String
|
||||
, name : String
|
||||
, event : Event
|
||||
}
|
||||
@ -33,7 +34,8 @@ type alias FieldEvent =
|
||||
|
||||
fieldEventDecoder : Decoder FieldEvent
|
||||
fieldEventDecoder =
|
||||
Decode.map3 FieldEvent
|
||||
Decode.map4 FieldEvent
|
||||
(Decode.at [ "target", "value" ] Decode.string)
|
||||
(Decode.at [ "currentTarget", "id" ] Decode.string)
|
||||
(Decode.at [ "target", "name" ] Decode.string)
|
||||
fieldDecoder
|
||||
@ -125,7 +127,7 @@ updateForm fieldEvent formState =
|
||||
previousValue : FieldState
|
||||
previousValue =
|
||||
previousValue_
|
||||
|> Maybe.withDefault { value = "", status = NotVisited }
|
||||
|> Maybe.withDefault { value = fieldEvent.value, status = NotVisited }
|
||||
in
|
||||
(case fieldEvent.event of
|
||||
InputEvent newValue ->
|
||||
|
@ -40,7 +40,7 @@ type alias Context error =
|
||||
}
|
||||
|
||||
|
||||
andThenNew : combined -> (Context String -> viewFn) -> CombinedParser String combined (Context String -> viewFn)
|
||||
andThenNew : combined -> (Context String -> viewFn) -> CombinedParser String combined data (Context String -> viewFn)
|
||||
andThenNew fn viewFn =
|
||||
CombinedParser []
|
||||
(\formState ->
|
||||
@ -48,14 +48,15 @@ andThenNew fn viewFn =
|
||||
, view = viewFn
|
||||
}
|
||||
)
|
||||
(\_ -> [])
|
||||
|
||||
|
||||
field :
|
||||
String
|
||||
-> Field error parsed constraints
|
||||
-> CombinedParser error (ParsedField error parsed -> combined) (Context error -> (RawField -> combinedView))
|
||||
-> CombinedParser error combined (Context error -> combinedView)
|
||||
field name (Field fieldParser) (CombinedParser definitions parseFn) =
|
||||
-> Field error parsed data constraints
|
||||
-> CombinedParser error (ParsedField error parsed -> combined) data (Context error -> (RawField -> combinedView))
|
||||
-> CombinedParser error combined data (Context error -> combinedView)
|
||||
field name (Field fieldParser) (CombinedParser definitions parseFn toInitialValues) =
|
||||
CombinedParser
|
||||
(( name, FieldDefinition )
|
||||
:: definitions
|
||||
@ -132,6 +133,15 @@ field name (Field fieldParser) (CombinedParser definitions parseFn) =
|
||||
|> parseFn
|
||||
|> myFn
|
||||
)
|
||||
(\data ->
|
||||
case fieldParser.initialValue of
|
||||
Just toInitialValue ->
|
||||
( name, toInitialValue data )
|
||||
:: toInitialValues data
|
||||
|
||||
Nothing ->
|
||||
toInitialValues data
|
||||
)
|
||||
|
||||
|
||||
type ParsingResult a
|
||||
@ -157,7 +167,7 @@ type alias FieldErrors error =
|
||||
Dict String (List error)
|
||||
|
||||
|
||||
type alias AppContext app =
|
||||
type alias AppContext app data =
|
||||
{ app
|
||||
| --, sharedData : Shared.Data
|
||||
--, routeParams : routeParams
|
||||
@ -169,17 +179,18 @@ type alias AppContext app =
|
||||
transition : Maybe Pages.Transition.Transition
|
||||
, fetchers : List Pages.Transition.FetcherState
|
||||
, pageFormState : Form.PageFormState
|
||||
, data : data
|
||||
}
|
||||
|
||||
|
||||
runNew :
|
||||
Form.FormState
|
||||
-> CombinedParser error parsed (Context error -> view)
|
||||
-> CombinedParser error parsed data (Context error -> view)
|
||||
->
|
||||
{ result : ( Maybe parsed, FieldErrors error )
|
||||
, view : view
|
||||
}
|
||||
runNew formState (CombinedParser fieldDefinitions parser) =
|
||||
runNew formState (CombinedParser fieldDefinitions parser _) =
|
||||
-- TODO Get transition context from `app` so you can check if the current form is being submitted
|
||||
-- TODO either as a transition or a fetcher? Should be easy enough to check for the `id` on either of those?
|
||||
let
|
||||
@ -202,11 +213,12 @@ runNew formState (CombinedParser fieldDefinitions parser) =
|
||||
|
||||
|
||||
renderHtml :
|
||||
AppContext app
|
||||
AppContext app data
|
||||
->
|
||||
CombinedParser
|
||||
error
|
||||
parsed
|
||||
data
|
||||
(Context error
|
||||
-> ( List (Html.Attribute (Pages.Msg.Msg msg)), List (Html (Pages.Msg.Msg msg)) )
|
||||
)
|
||||
@ -216,16 +228,17 @@ renderHtml formState_ combinedParser =
|
||||
|
||||
|
||||
renderHelper :
|
||||
AppContext app
|
||||
AppContext app data
|
||||
->
|
||||
CombinedParser
|
||||
error
|
||||
parsed
|
||||
data
|
||||
(Context error
|
||||
-> ( List (Html.Attribute (Pages.Msg.Msg msg)), List (Html (Pages.Msg.Msg msg)) )
|
||||
)
|
||||
-> Html (Pages.Msg.Msg msg)
|
||||
renderHelper formState (CombinedParser fieldDefinitions parser) =
|
||||
renderHelper formState (CombinedParser fieldDefinitions parser toInitialValues) =
|
||||
-- TODO Get transition context from `app` so you can check if the current form is being submitted
|
||||
-- TODO either as a transition or a fetcher? Should be easy enough to check for the `id` on either of those?
|
||||
let
|
||||
@ -234,16 +247,29 @@ renderHelper formState (CombinedParser fieldDefinitions parser) =
|
||||
-- TODO remove hardcoding
|
||||
"test"
|
||||
|
||||
initialValues : Dict String Form.FieldState
|
||||
initialValues =
|
||||
toInitialValues formState.data
|
||||
|> List.map (Tuple.mapSecond (\value -> { value = value, status = Form.NotVisited }))
|
||||
|> Dict.fromList
|
||||
|
||||
part2 : Dict String Form.FieldState
|
||||
part2 =
|
||||
formState.pageFormState
|
||||
|> Dict.get formId
|
||||
|> Maybe.withDefault Dict.empty
|
||||
|
||||
fullFormState : Dict String Form.FieldState
|
||||
fullFormState =
|
||||
initialValues
|
||||
|> Dict.union part2
|
||||
|
||||
parsed :
|
||||
{ result : ( Maybe parsed, Dict String (List error) )
|
||||
, view : Context error -> ( List (Html.Attribute (Pages.Msg.Msg msg)), List (Html (Pages.Msg.Msg msg)) )
|
||||
}
|
||||
parsed =
|
||||
parser
|
||||
(formState.pageFormState
|
||||
|> Dict.get formId
|
||||
|> Maybe.withDefault Dict.empty
|
||||
)
|
||||
parser fullFormState
|
||||
|
||||
context =
|
||||
{ errors =
|
||||
@ -275,10 +301,10 @@ renderHelper formState (CombinedParser fieldDefinitions parser) =
|
||||
|
||||
|
||||
render :
|
||||
AppContext app
|
||||
-> CombinedParser error parsed (Context error -> view)
|
||||
AppContext app data
|
||||
-> CombinedParser error parsed data (Context error -> view)
|
||||
-> view
|
||||
render formState (CombinedParser fieldDefinitions parser) =
|
||||
render formState (CombinedParser fieldDefinitions parser toInitialValues) =
|
||||
-- TODO Get transition context from `app` so you can check if the current form is being submitted
|
||||
-- TODO either as a transition or a fetcher? Should be easy enough to check for the `id` on either of those?
|
||||
let
|
||||
@ -317,7 +343,15 @@ render formState (CombinedParser fieldDefinitions parser) =
|
||||
parsed.view context
|
||||
|
||||
|
||||
type CombinedParser error parsed view
|
||||
type alias HtmlForm error parsed data msg =
|
||||
CombinedParser
|
||||
error
|
||||
parsed
|
||||
data
|
||||
(Context error -> ( List (Html.Attribute (Pages.Msg.Msg msg)), List (Html (Pages.Msg.Msg msg)) ))
|
||||
|
||||
|
||||
type CombinedParser error parsed data view
|
||||
= CombinedParser
|
||||
(List ( String, FieldDefinition ))
|
||||
(Form.FormState
|
||||
@ -329,6 +363,7 @@ type CombinedParser error parsed view
|
||||
, view : view
|
||||
}
|
||||
)
|
||||
(data -> List ( String, String ))
|
||||
|
||||
|
||||
type FieldDefinition
|
||||
|
@ -968,7 +968,7 @@ formParserResult formParser_ =
|
||||
|
||||
{-| -}
|
||||
formParserResultNew :
|
||||
Pages.FormParser.CombinedParser error combined (Pages.FormParser.Context error -> viewFn)
|
||||
Pages.FormParser.CombinedParser error combined data (Pages.FormParser.Context error -> viewFn)
|
||||
-> Parser (Result { fields : List ( String, String ), errors : Dict String (List error) } combined)
|
||||
formParserResultNew formParser_ =
|
||||
formData
|
||||
|
Loading…
Reference in New Issue
Block a user