Campos de texto
Vamos a crear una simple aplicación que escribe al revés lo que ingreses en un campo de texto.
Abre este programa en el editor online, y fíjate en el tip que aparece cuando pones el cursor sobre la palabra type
. ¡Apreta el botón azul!
import Browser
import Html exposing (Attribute, Html, div, input, text)
import Html.Attributes exposing (..)
import Html.Events exposing (onInput)
-- MAIN
main =
Browser.sandbox { init = init, update = update, view = view }
-- MODEL
type alias Model =
{ content : String
}
init : Model
init =
{ content = "" }
-- UPDATE
type Msg
= Change String
update : Msg -> Model -> Model
update msg model =
case msg of
Change newContent ->
{ model | content = newContent }
-- VIEW
view : Model -> Html Msg
view model =
div []
[ input [ placeholder "Text to reverse", value model.content, onInput Change ] []
, div [] [ text (String.reverse model.content) ]
]
Este código es una ligera variación del ejemplo anterior. Configuramos un modelo, definimos unos mensajes, decimos cómo actualizar el modelo con update
, y definimos la vista en view
. La diferencia está sólo en cómo completamos este esqueleto. Veamos parte por parte.
Modelo
Yo siempre comienzo tratando de imaginar cómo tiene que ser mi Model
. De partida sabemos que necesitamos llevar cuenta de lo que el usuario haya escrito en el campo de texto, porque necesitamos esa información para saber cómo mostrar el texto al revés. Así que probamos con esto:
type alias Model =
{ content : String
}
Esta vez decidí representar el modelo como un registro. El registro alberga el texto ingresado por el usuario en el campo content
.
Nota: Tal vez te surja la duda de por qué usar un registro con un sólo campo. ¿No podríamos usar
String
directamente? Claro que sí. Pero si empezamos con un registro, se hace más fácil después añadir más campos a medida que nuestra aplicación se haga más compleja. Cuando llegue el momento en que necesitemos dos campos de texto, tendremos que hacer mucho menos trabajo.
Vista
Ya teniendo el modelo, lo que normalmente hago después es crear la función view
:
view : Model -> Html Msg
view model =
div []
[ input [ placeholder "Text to reverse", value model.content, onInput Change ] []
, div [] [ text (String.reverse model.content) ]
]
Creamos un <div>
con dos hijos. El hijo que más nos interesa es el nodo <input>
, que tiene tres atributos:
placeholder
es el texto que se muestra cuando no hay contenido.value
es el contenido actual de este<input>
.onInput
produce mensajes cuando el usuario escribe algo en este nodo<input>
.
Si escribes “sala” vas a producir cuatro mensajes:
Change "s"
Change "sa"
Change "sal"
Change "sala"
Estos serán ingresados a nuestra función update
.
Actualización
Solo hay un tipo de mensaje en este programa, así que nuestro update
sólo tiene que tomar en cuenta un caso:
type Msg
= Change String
update : Msg -> Model -> Model
update msg model =
case msg of
Change newContent ->
{ model | content = newContent }
Cuando recibimos un mensaje indicando que hubo un cambio en nuestro <input>
, actualizamos el campo content
del modelo. Así que si escribimos “sala”, los mensajes resultantes producirían estos modelos:
{ content = "s" }
{ content = "sa" }
{ content = "sal" }
{ content = "sala" }
Necesitamos llevar cuenta de esta información en el modelo en forma explícita. Si no, no tendríamos cómo mostrar el texto al revés en nuestra función view
.
Ejercicio: Abre el ejemplo en el editor online aquí, y pon la cantidad de caracteres que tiene el campo
content
en tu funciónview
. Usa la funciónString.length
para lograrlo.Nota: Si quieres más información sobre exactamente cómo funcionan los valores
Change
en este programa, revisa las secciones posteriores sobre tipos personalizados y búsqueda de patrones.