Ahora crearemos un formulario básico. Tiene un campo para tu nombre, un campo para tu contraseña y un campo para verificarla. También realizaremos una validación muy sencilla para comprobar si las contraseñas coinciden.
A continuación, incluí el programa completo:
-- Input a user name and password. Make sure the password matches.
--
-- Read how it works:
-- https://guide.elm-lang.org/architecture/forms.html
--
import Browser
import Html exposing (..)
import Html.Attributes exposing (..)
import Html.Events exposing (onInput)
-- MAIN
main =
Browser.sandbox { init = init, update = update, view = view }
-- MODEL
type alias Model =
{ name : String
, password : String
, passwordAgain : String
}
init : Model
init =
Model "" "" ""
-- UPDATE
type Msg
= Name String
| Password String
| PasswordAgain String
update : Msg -> Model -> Model
update msg model =
case msg of
Name name ->
{ model | name = name }
Password password ->
{ model | password = password }
PasswordAgain password ->
{ model | passwordAgain = password }
-- VIEW
view : Model -> Html Msg
view model =
div []
[ viewInput "text" "Name" model.name Name
, viewInput "password" "Password" model.password Password
, viewInput "password" "Re-enter Password" model.passwordAgain PasswordAgain
, viewValidation model
]
viewInput : String -> String -> String -> (String -> msg) -> Html msg
viewInput t p v toMsg =
input [ type_ t, placeholder p, value v, onInput toMsg ] []
viewValidation : Model -> Html msg
viewValidation model =
if model.password == model.passwordAgain then
div [ style "color" "green" ] [ text "OK" ]
else
div [ style "color" "red" ] [ text "Passwords do not match!" ]
Esto es bastante similar a nuestro ejemplo de campo de texto, pero con más campos.
Siempre empiezo calculando el modelo. Sabemos que habrá tres campos de texto, así que sigamos con eso:
type alias Model =
{ name : String
, password : String
, passwordAgain : String
}
Normalmente intento empezar con un modelo mínimo, quizás con un solo campo. Luego intento escribir las funciones de vista y actualización. Esto suele revelar que necesito añadir más elementos a mi modelo. Construir el modelo gradualmente de esta manera significa que puedo tener un programa funcional durante el proceso de desarrollo. Puede que aún no tenga todas las funciones, ¡pero casi las tiene!
A veces se tiene una idea bastante clara de cómo se verá el código básico de actualización. Sabemos que necesitamos poder cambiar nuestros tres campos, por lo que necesitamos mensajes para cada caso.
type Msg
= Name String
| Password String
| PasswordAgain String
Esto significa que nuestra actualización necesita un caso para las tres variantes:
update : Msg -> Model -> Model
update msg model =
case msg of
Name name ->
{ model | name = name }
Password password ->
{ model | password = password }
PasswordAgain password ->
{ model | passwordAgain = password }
Cada caso utiliza la sintaxis de actualización de registros para garantizar que se transforme el campo correspondiente. Esto es similar al ejemplo anterior, pero con más casos.
Esta función de vista utiliza funciones auxiliares para hacer las cosas un poco más organizadas:
view : Model -> Html Msg
view model =
div []
[ viewInput "text" "Name" model.name Name
, viewInput "password" "Password" model.password Password
, viewInput "password" "Re-enter Password" model.passwordAgain PasswordAgain
, viewValidation model
]
En ejemplos anteriores, usábamos input y div directamente. ¿Por qué dejamos de hacerlo?
Lo bueno de HTML en Elm es que input y div son funciones normales. Toman una lista de atributos y una lista de nodos secundarios. Como usamos funciones normales de Elm, ¡tenemos todo el poder de Elm para ayudarnos a crear nuestras vistas! Podemos refactorizar código repetitivo y convertirlo en funciones auxiliares personalizadas. ¡Eso es exactamente lo que estamos haciendo aquí!
Así que nuestra función de vista tiene tres llamadas a viewInput:
viewInput : String -> String -> String -> (String -> msg) -> Html msg
viewInput t p v toMsg =
input [ type_ t, placeholder p, value v, onInput toMsg ] []
Esto significa que escribir viewInput "text" "Name" "Bill" Name en Elm se convertiría en un valor HTML como <input type="text" placeholder="Name" value="Bill"> al mostrarse en pantalla.
La cuarta entrada es más interesante. Es una llamada a viewValidation:
viewValidation : Model -> Html msg
viewValidation model =
if model.password == model.passwordAgain then
div [ style "color" "green" ] [ text "OK" ]
else
div [ style "color" "red" ] [ text "Passwords do not match!" ]
Esta función primero compara las dos contraseñas. Si coinciden, se muestra texto verde y un mensaje positivo. Si no coinciden, se muestra texto rojo y un mensaje útil.
Estas funciones auxiliares empiezan a mostrar las ventajas de que nuestra biblioteca HTML sea código Elm normal. Podríamos incluir todo ese código en nuestra vista, pero crear funciones auxiliares es totalmente normal en Elm, incluso en el código de la vista.