elm-pages-v3-beta/examples/pokedex/src/Page/Form.elm

277 lines
7.7 KiB
Elm
Raw Normal View History

2022-01-01 23:50:03 +03:00
module Page.Form exposing (Data, Model, Msg, page)
import DataSource exposing (DataSource)
2022-01-04 08:17:07 +03:00
import Date exposing (Date)
2022-01-02 20:52:04 +03:00
import Dict exposing (Dict)
2022-01-01 23:50:03 +03:00
import Form exposing (Form)
import Form.Value
2022-01-01 23:50:03 +03:00
import Head
import Head.Seo as Seo
2022-01-03 21:07:06 +03:00
import Html exposing (Html)
import Html.Attributes as Attr
2022-01-01 23:50:03 +03:00
import Page exposing (Page, PageWithState, StaticPayload)
import PageServerResponse exposing (PageServerResponse)
import Pages.PageUrl exposing (PageUrl)
import Pages.Url
import Server.Request as Request exposing (Request)
import Shared
2022-01-04 08:17:07 +03:00
import Time
2022-01-01 23:50:03 +03:00
import View exposing (View)
type alias Model =
{}
type alias Msg =
()
2022-01-01 23:50:03 +03:00
type alias RouteParams =
{}
type alias User =
{ first : String
, last : String
, username : String
, email : String
2022-01-04 08:17:07 +03:00
, birthDay : Date
2022-01-04 22:47:57 +03:00
, checkbox : Bool
2022-01-01 23:50:03 +03:00
}
defaultUser : User
defaultUser =
2022-01-02 05:35:36 +03:00
{ first = "Jane"
, last = "Doe"
, username = "janedoe"
, email = "janedoe@example.com"
2022-01-04 08:17:07 +03:00
, birthDay = Date.fromCalendarDate 1969 Time.Jul 20
2022-01-04 22:47:57 +03:00
, checkbox = False
2022-01-01 23:50:03 +03:00
}
errorsView : List String -> Html msg
2022-01-03 19:43:00 +03:00
errorsView errors =
case errors of
first :: rest ->
Html.div []
[ Html.ul
[ Attr.style "border" "solid red"
]
(List.map
(\error ->
Html.li []
[ Html.text error
2022-01-03 19:43:00 +03:00
]
)
(first :: rest)
)
]
[] ->
Html.div [] []
form : User -> Form String User (Html Form.Msg)
2022-01-01 23:50:03 +03:00
form user =
Form.succeed User
2022-01-05 22:21:43 +03:00
|> Form.with
2022-01-05 22:23:39 +03:00
(Form.text
2022-01-03 18:40:45 +03:00
"first"
2022-01-03 19:43:00 +03:00
(\{ toInput, toLabel, errors } ->
2022-01-03 18:40:45 +03:00
Html.div []
2022-01-03 19:43:00 +03:00
[ errorsView errors
2022-01-03 21:07:06 +03:00
, Html.label toLabel
2022-01-03 18:40:45 +03:00
[ Html.text "First"
]
2022-01-03 21:07:06 +03:00
, Html.input toInput []
2022-01-03 18:40:45 +03:00
]
)
|> Form.required "Required"
|> Form.withInitialValue (user.first |> Form.Value.string)
2022-01-01 23:50:03 +03:00
)
2022-01-05 22:21:43 +03:00
|> Form.with
2022-01-05 22:23:39 +03:00
(Form.text
2022-01-03 18:40:45 +03:00
"last"
2022-01-03 19:43:00 +03:00
(\{ toInput, toLabel, errors } ->
2022-01-03 18:40:45 +03:00
Html.div []
2022-01-03 19:43:00 +03:00
[ errorsView errors
2022-01-03 21:07:06 +03:00
, Html.label toLabel
2022-01-03 18:40:45 +03:00
[ Html.text "Last"
]
2022-01-03 21:07:06 +03:00
, Html.input toInput []
2022-01-03 18:40:45 +03:00
]
)
|> Form.required "Required"
|> Form.withInitialValue (user.last |> Form.Value.string)
2022-01-01 23:50:03 +03:00
)
2022-01-05 22:21:43 +03:00
|> Form.with
2022-01-05 22:23:39 +03:00
(Form.text
2022-01-03 18:40:45 +03:00
"username"
2022-01-03 21:07:06 +03:00
(\{ toInput, toLabel, errors } ->
Html.div []
[ errorsView errors
, Html.label toLabel
[ Html.text "Username"
]
, Html.input toInput []
]
2022-01-03 18:40:45 +03:00
)
|> Form.required "Required"
|> Form.withInitialValue (user.username |> Form.Value.string)
2022-01-02 20:52:04 +03:00
|> Form.withServerValidation
(\username ->
if username == "asdf" then
DataSource.succeed [ "username is taken" ]
else
DataSource.succeed []
)
2022-01-01 23:50:03 +03:00
)
2022-01-05 22:21:43 +03:00
|> Form.with
2022-01-05 22:23:39 +03:00
(Form.text
2022-01-03 18:40:45 +03:00
"email"
2022-01-03 19:43:00 +03:00
(\{ toInput, toLabel, errors } ->
2022-01-03 18:40:45 +03:00
Html.div []
2022-01-03 19:43:00 +03:00
[ errorsView errors
2022-01-03 21:07:06 +03:00
, Html.label toLabel
2022-01-03 18:40:45 +03:00
[ Html.text "Email"
]
2022-01-03 21:07:06 +03:00
, Html.input toInput []
2022-01-03 18:40:45 +03:00
]
)
|> Form.required "Required"
|> Form.withInitialValue (user.email |> Form.Value.string)
2022-01-01 23:50:03 +03:00
)
2022-01-05 22:21:43 +03:00
|> Form.with
(Form.date
2022-01-03 18:40:45 +03:00
"dob"
{ invalid = \_ -> "Invalid date"
}
2022-01-03 19:43:00 +03:00
(\{ toInput, toLabel, errors } ->
2022-01-03 18:40:45 +03:00
Html.div []
2022-01-03 19:43:00 +03:00
[ errorsView errors
2022-01-03 21:07:06 +03:00
, Html.label toLabel
2022-01-03 18:40:45 +03:00
[ Html.text "Date of Birth"
]
2022-01-03 21:07:06 +03:00
, Html.input toInput []
2022-01-03 18:40:45 +03:00
]
)
|> Form.required "Required"
|> Form.withInitialValue (user.birthDay |> Form.Value.date)
|> Form.withMin (Date.fromCalendarDate 1900 Time.Jan 1 |> Form.Value.date)
|> Form.withMax (Date.fromCalendarDate 2022 Time.Jan 1 |> Form.Value.date)
2022-01-01 23:50:03 +03:00
)
2022-01-05 22:21:43 +03:00
|> Form.with
2022-01-04 22:47:57 +03:00
(Form.checkbox
"checkbox"
user.checkbox
2022-01-04 22:47:57 +03:00
(\{ toInput, toLabel, errors } ->
Html.div []
[ errorsView errors
, Html.label toLabel
[ Html.text "Checkbox"
]
, Html.input toInput []
]
)
)
|> Form.append
(Form.submit
(\{ attrs } ->
2022-01-03 21:07:06 +03:00
Html.input attrs []
)
)
2022-01-01 23:50:03 +03:00
page : Page RouteParams Data
page =
Page.serverRender
{ head = head
, data = data
}
|> Page.buildNoState { view = view }
type alias Data =
{ user : Maybe User
, errors : Form.Model
2022-01-01 23:50:03 +03:00
}
data : RouteParams -> Request (DataSource (PageServerResponse Data))
data routeParams =
Request.oneOf
[ Form.submitHandlers
(form defaultUser)
(\model decoded ->
DataSource.succeed
{ user = Result.toMaybe decoded
, errors = model
}
)
, { user = Nothing
, errors = Form.init (form defaultUser)
}
|> PageServerResponse.render
2022-01-01 23:50:03 +03:00
|> DataSource.succeed
|> Request.succeed
]
head :
StaticPayload Data RouteParams
-> List Head.Tag
head static =
Seo.summary
{ canonicalUrlOverride = Nothing
, siteName = "elm-pages"
, image =
{ url = Pages.Url.external "TODO"
, alt = "elm-pages logo"
, dimensions = Nothing
, mimeType = Nothing
}
, description = "TODO"
, locale = Nothing
, title = "TODO title" -- metadata.title -- TODO
}
|> Seo.website
view :
Maybe PageUrl
-> Shared.Model
-> StaticPayload Data RouteParams
-> View Msg
view maybeUrl sharedModel static =
let
user : User
2022-01-01 23:50:03 +03:00
user =
static.data.user
|> Maybe.withDefault defaultUser
2022-01-01 23:50:03 +03:00
in
{ title = "Form Example"
, body =
2022-01-03 21:07:06 +03:00
[ static.data.user
|> Maybe.map
(\user_ ->
Html.p
[ Attr.style "padding" "10px"
, Attr.style "background-color" "#a3fba3"
]
[ Html.text <| "Successfully received user " ++ user_.first ++ " " ++ user_.last
]
2022-01-03 21:07:06 +03:00
)
|> Maybe.withDefault (Html.p [] [])
2022-01-03 21:07:06 +03:00
, Html.h1
[]
[ Html.text <| "Edit profile " ++ user.first ++ " " ++ user.last ]
, form user
|> Form.toHtml { pageReloadSubmit = True } Html.form static.data.errors
|> Html.map (\_ -> ())
2022-01-01 23:50:03 +03:00
]
}