Text Fields


Clone the code or follow along in the online editor.


We are about to create a simple app that reverses the contents of a text field. This example also introduces some new stuff that will help us out in our next example.

Again this is a pretty short program, so I have included the whole thing here. Skim through to get an idea of how everything fits together. Right after that we will go into much more detail!

  1. import Html exposing (Html, Attribute, div, input, text)
  2. import Html.Attributes exposing (..)
  3. import Html.Events exposing (onInput)
  4. main =
  5. Html.beginnerProgram { model = model, view = view, update = update }
  6. -- MODEL
  7. type alias Model =
  8. { content : String
  9. }
  10. model : Model
  11. model =
  12. { content = "" }
  13. -- UPDATE
  14. type Msg
  15. = Change String
  16. update : Msg -> Model -> Model
  17. update msg model =
  18. case msg of
  19. Change newContent ->
  20. { model | content = newContent }
  21. -- VIEW
  22. view : Model -> Html Msg
  23. view model =
  24. div []
  25. [ input [ placeholder "Text to reverse", onInput Change ] []
  26. , div [] [ text (String.reverse model.content) ]
  27. ]

This code is a slight variant of the counter from the previous section. You set up a model. You define some messages. You say how to update. You make your view. The difference is just in how we filled this skeleton in. Let’s walk through that!

As always, you start by guessing at what your Model should be. In our case, we know we are going to have to keep track of whatever the user has typed into the text field. We need that information so we know how to render the reversed text.

  1. type alias Model =
  2. { content : String
  3. }

This time I chose to represent the model as a record. (You can read more about records here and here.) For now, the record stores the user input in the content field.

Note: You may be wondering, why bother having a record if it only holds one entry? Couldn’t you just use the string directly? Yes, of course! But starting with a record makes it easy to add more fields as our app gets more complicated. When the time comes where we want two text inputs, we will have to do much less fiddling around.

Okay, so we have our model. Now in this app there is only one kind of message really. The user can change the contents of the text field.

  1. type Msg
  2. = Change String

This means our update function just has to handle this one case:

  1. update : Msg -> Model -> Model
  2. update msg model =
  3. case msg of
  4. Change newContent ->
  5. { model | content = newContent }

When we receive new content, we use the record update syntax to update the contents of content.

Finally we need to say how to view our application:

  1. view : Model -> Html Msg
  2. view model =
  3. div []
  4. [ input [ placeholder "Text to reverse", onInput Change ] []
  5. , div [] [ text (String.reverse model.content) ]
  6. ]

We create a <div> with two children.

The interesting child is the <input> node. In addition to the placeholder attribute, it uses onInput to declare what messages should be sent when the user types into this input.

This onInput function is kind of interesting. It takes one argument, in this case the Change function which was created when we declared the Msg type:

  1. Change : String -> Msg

This function is used to tag whatever is currently in the text field. So let’s say the text field currently holds yol and the user types o. This triggers an input event, so we will get the message Change "yolo" in our update function.

So now we have a simple text field that can reverse user input. Neat! Now on to putting a bunch of text fields together into a more traditional form.