mirror of
https://github.com/dillonkearns/elm-pages-v3-beta.git
synced 2024-11-22 11:43:54 +03:00
Add FieldView.valueButton helpers, and rerun loaders when query params are changed to ensure that GET form submissions reload data.
This commit is contained in:
parent
df0489fc38
commit
ba875d789f
11
cypress/e2e/get-forms.cy.ts
Normal file
11
cypress/e2e/get-forms.cy.ts
Normal file
@ -0,0 +1,11 @@
|
||||
context("dev server with base path", () => {
|
||||
it("submits a form to receive ActionData", () => {
|
||||
cy.visit("/get-form");
|
||||
cy.contains("Page 2").click();
|
||||
cy.contains("Current page: 2");
|
||||
cy.contains("Page 1").click();
|
||||
cy.contains("Current page: 1");
|
||||
cy.contains("Page 2").click();
|
||||
cy.contains("Current page: 2");
|
||||
});
|
||||
});
|
143
examples/end-to-end/app/Route/GetForm.elm
Normal file
143
examples/end-to-end/app/Route/GetForm.elm
Normal file
@ -0,0 +1,143 @@
|
||||
module Route.GetForm exposing (ActionData, Data, Model, Msg, route)
|
||||
|
||||
import BackendTask exposing (BackendTask)
|
||||
import ErrorPage exposing (ErrorPage)
|
||||
import FatalError exposing (FatalError)
|
||||
import Form
|
||||
import Form.Field as Field
|
||||
import Form.FieldView
|
||||
import Form.Validation as Validation
|
||||
import Head
|
||||
import Html exposing (Html)
|
||||
import Html.Attributes as Attr
|
||||
import Html.Styled
|
||||
import Pages.Msg
|
||||
import Pages.PageUrl exposing (PageUrl)
|
||||
import RouteBuilder exposing (StatelessRoute, StaticPayload)
|
||||
import Server.Request as Request exposing (Parser)
|
||||
import Server.Response
|
||||
import Shared
|
||||
import View exposing (View)
|
||||
|
||||
|
||||
type alias Model =
|
||||
{}
|
||||
|
||||
|
||||
type alias Msg =
|
||||
()
|
||||
|
||||
|
||||
type alias RouteParams =
|
||||
{}
|
||||
|
||||
|
||||
type alias ActionData =
|
||||
{}
|
||||
|
||||
|
||||
type alias Filters =
|
||||
{ page : Int
|
||||
}
|
||||
|
||||
|
||||
form : Form.HtmlForm String Filters Filters Msg
|
||||
form =
|
||||
Form.init
|
||||
(\page ->
|
||||
{ combine =
|
||||
Validation.succeed Filters
|
||||
|> Validation.andMap page
|
||||
, view =
|
||||
\formState ->
|
||||
[ page
|
||||
|> Form.FieldView.valueButton "1"
|
||||
[]
|
||||
[ Html.text "Page 1" ]
|
||||
, page
|
||||
|> Form.FieldView.valueButton "2"
|
||||
[]
|
||||
[ Html.text "Page 2" ]
|
||||
]
|
||||
}
|
||||
)
|
||||
|> Form.field "page"
|
||||
(Field.int { invalid = \_ -> "" }
|
||||
|> Field.map (Maybe.withDefault 1)
|
||||
--|> Field.withInitialValue (.first >> Form.Value.string)
|
||||
)
|
||||
|
||||
|
||||
route : StatelessRoute RouteParams Data ActionData
|
||||
route =
|
||||
RouteBuilder.serverRender
|
||||
{ head = head
|
||||
, data = data
|
||||
, action = action
|
||||
}
|
||||
|> RouteBuilder.buildNoState { view = view }
|
||||
|
||||
|
||||
type alias Data =
|
||||
{ filters : Filters
|
||||
}
|
||||
|
||||
|
||||
data : RouteParams -> Parser (BackendTask FatalError (Server.Response.Response Data ErrorPage))
|
||||
data routeParams =
|
||||
Request.formData (Form.initCombined identity form)
|
||||
|> Request.map
|
||||
(\( formResponse, formResult ) ->
|
||||
case formResult of
|
||||
Ok filters ->
|
||||
Data filters
|
||||
|> Server.Response.render
|
||||
|> BackendTask.succeed
|
||||
|
||||
Err _ ->
|
||||
Data { page = 1 }
|
||||
|> Server.Response.render
|
||||
|> BackendTask.succeed
|
||||
)
|
||||
|
||||
|
||||
action : RouteParams -> Parser (BackendTask FatalError (Server.Response.Response ActionData ErrorPage))
|
||||
action routeParams =
|
||||
Request.succeed
|
||||
(Server.Response.render {}
|
||||
|> BackendTask.succeed
|
||||
)
|
||||
|
||||
|
||||
head :
|
||||
StaticPayload Data ActionData RouteParams
|
||||
-> List Head.Tag
|
||||
head static =
|
||||
[]
|
||||
|
||||
|
||||
view :
|
||||
Maybe PageUrl
|
||||
-> Shared.Model
|
||||
-> StaticPayload Data ActionData RouteParams
|
||||
-> View (Pages.Msg.Msg Msg)
|
||||
view maybeUrl sharedModel app =
|
||||
{ title = "GET Form Example"
|
||||
, body =
|
||||
[ form
|
||||
|> Form.toDynamicTransition "user-form"
|
||||
|> Form.withGetMethod
|
||||
|> Form.renderHtml
|
||||
[ Attr.style "display" "flex"
|
||||
, Attr.style "flex-direction" "column"
|
||||
, Attr.style "gap" "20px"
|
||||
]
|
||||
(\_ -> Nothing)
|
||||
app
|
||||
app.data.filters
|
||||
, Html.h2 []
|
||||
[ Html.text <| "Current page: " ++ String.fromInt app.data.filters.page
|
||||
]
|
||||
]
|
||||
|> List.map Html.Styled.fromUnstyled
|
||||
}
|
@ -1,16 +1,16 @@
|
||||
module Form.FieldView exposing
|
||||
( Input(..), InputType(..), Options(..), input, inputTypeToString, radio, toHtmlProperties, Hidden(..), select
|
||||
, radioStyled, inputStyled
|
||||
( Input(..), InputType(..), Options(..), input, inputTypeToString, radio, toHtmlProperties, Hidden(..), select, valueButton
|
||||
, radioStyled, inputStyled, valueButtonStyled
|
||||
)
|
||||
|
||||
{-|
|
||||
|
||||
@docs Input, InputType, Options, input, inputTypeToString, radio, toHtmlProperties, Hidden, select
|
||||
@docs Input, InputType, Options, input, inputTypeToString, radio, toHtmlProperties, Hidden, select, valueButton
|
||||
|
||||
|
||||
## Html.Styled Helpers
|
||||
|
||||
@docs radioStyled, inputStyled
|
||||
@docs radioStyled, inputStyled, valueButtonStyled
|
||||
|
||||
-}
|
||||
|
||||
@ -103,6 +103,90 @@ type Options a
|
||||
= Options (String -> Maybe a) (List String)
|
||||
|
||||
|
||||
{-| Gives you a submit button that will submit the form with a specific value for the given Field.
|
||||
-}
|
||||
valueButton :
|
||||
String
|
||||
-> List (Html.Attribute msg)
|
||||
-> List (Html msg)
|
||||
-> Form.Validation.Field error parsed Input
|
||||
-> Html msg
|
||||
valueButton exactValue attrs children (Validation viewField fieldName _) =
|
||||
let
|
||||
justViewField : ViewField Input
|
||||
justViewField =
|
||||
expectViewField viewField
|
||||
|
||||
rawField : { name : String, value : Maybe String, kind : ( Input, List ( String, Encode.Value ) ) }
|
||||
rawField =
|
||||
{ name = fieldName |> Maybe.withDefault ""
|
||||
, value = Just exactValue --justViewField.value
|
||||
, kind = justViewField.kind
|
||||
}
|
||||
in
|
||||
case rawField.kind of
|
||||
( Input inputType, properties ) ->
|
||||
Html.button
|
||||
(attrs
|
||||
++ toHtmlProperties properties
|
||||
++ [ (case inputType of
|
||||
Checkbox ->
|
||||
Attr.checked ((rawField.value |> Maybe.withDefault "") == "on")
|
||||
|
||||
_ ->
|
||||
Attr.value (rawField.value |> Maybe.withDefault "")
|
||||
-- TODO is this an okay default?
|
||||
)
|
||||
, Attr.name rawField.name
|
||||
, inputType |> inputTypeToString |> Attr.type_
|
||||
]
|
||||
)
|
||||
children
|
||||
|
||||
|
||||
{-| Gives you a submit button that will submit the form with a specific value for the given Field.
|
||||
-}
|
||||
valueButtonStyled :
|
||||
String
|
||||
-> List (Html.Styled.Attribute msg)
|
||||
-> List (Html.Styled.Html msg)
|
||||
-> Form.Validation.Field error parsed Input
|
||||
-> Html.Styled.Html msg
|
||||
valueButtonStyled exactValue attrs children (Validation viewField fieldName _) =
|
||||
let
|
||||
justViewField : ViewField Input
|
||||
justViewField =
|
||||
expectViewField viewField
|
||||
|
||||
rawField : { name : String, value : Maybe String, kind : ( Input, List ( String, Encode.Value ) ) }
|
||||
rawField =
|
||||
{ name = fieldName |> Maybe.withDefault ""
|
||||
, value = Just exactValue
|
||||
, kind = justViewField.kind
|
||||
}
|
||||
in
|
||||
case rawField.kind of
|
||||
( Input inputType, properties ) ->
|
||||
Html.Styled.button
|
||||
(attrs
|
||||
++ (toHtmlProperties properties |> List.map StyledAttr.fromUnstyled)
|
||||
++ ([ (case inputType of
|
||||
Checkbox ->
|
||||
Attr.checked ((rawField.value |> Maybe.withDefault "") == "on")
|
||||
|
||||
_ ->
|
||||
Attr.value (rawField.value |> Maybe.withDefault "")
|
||||
-- TODO is this an okay default?
|
||||
)
|
||||
, Attr.name rawField.name
|
||||
, inputType |> inputTypeToString |> Attr.type_
|
||||
]
|
||||
|> List.map StyledAttr.fromUnstyled
|
||||
)
|
||||
)
|
||||
children
|
||||
|
||||
|
||||
{-| -}
|
||||
input :
|
||||
List (Html.Attribute msg)
|
||||
|
@ -414,7 +414,7 @@ update config appMsg model =
|
||||
model
|
||||
|
||||
Nothing ->
|
||||
if model.url.path == url.path then
|
||||
if model.url.path == url.path && model.url.query == url.query then
|
||||
( { model
|
||||
| -- update the URL in case query params or fragment changed
|
||||
url = url
|
||||
|
Loading…
Reference in New Issue
Block a user