2
\$\begingroup\$

I struggled to figure out how to clear a textbox after submitting it's contents via a button control.

I would like to know if my solution is an accepted practice for initializing a control after an action has been made by a user.

Is embedding event data (i.e. SendRequested) within a model an accepted practice for updating UI within Elm?

module Main exposing (..)

import Html exposing (..)
import Html.Attributes exposing (..)
import Html.Events exposing (..)
import WebSocket


main =
    program
        { init = init
        , update = update
        , view = view
        , subscriptions = subscriptions
        }



-- MODEL


type alias Model =
    { input : String
    , messages : List String
    , sendRequested : Bool
    }


init : ( Model, Cmd Msg )
init =
    ( Model "" [] False, Cmd.none )



-- UPDATE


type Msg
    = Input String
    | Send
    | NewMessage String


update : Msg -> Model -> ( Model, Cmd Msg )
update msg { input, messages, sendRequested } =
    case msg of
        Input newInput ->
            ( Model newInput messages False, Cmd.none )

        Send ->
            ( Model "" messages True, WebSocket.send "ws://echo.websocket.org" input )

        NewMessage message ->
            ( Model input (message :: messages) False, Cmd.none )



-- SUBSCRIPTIONS


subscriptions : Model -> Sub Msg
subscriptions model =
    WebSocket.listen "ws://echo.websocket.org" NewMessage



-- VIEW


view : Model -> Html Msg
view model =
    let
        inputElement =
            if not model.sendRequested then
                input [ onInput Input ] []
            else
                input [ onInput Input, value "" ] []
    in
        div []
            [ div [] (List.map viewMessage model.messages)
            , inputElement
            , button [ onClick Send ] [ text "Send" ]
            ]


viewMessage : String -> Html Msg
viewMessage message =
    div [] [ text message ]
\$\endgroup\$
2
\$\begingroup\$

Since you're already keeping track of the <input>'s value in your model, it would be cleaner to use that as the value in your view, too.

view : Model -> Html Msg
view model =
    div []
        [ div [] (List.map viewMessage model.messages)
        , input [ onInput Input, value model.value ] []
        , button [ onClick Send ] [ text "Send" ]
        ]

This way, your view is a pure representation of your model, and your model is kept in sync with user input.

I took the liberty of doing a quick pass over your code, additionally introducing record update syntax in your update function, as opposed to constructing a fresh record from scratch.

Adding or removing a field from a record needn't result in refactoring every single place you happen to modify the values of that record.

\$\endgroup\$
  • \$\begingroup\$ The "record update" is a great piece of feedback! Thanks for pointing that out. \$\endgroup\$ – Scott Nimrod May 8 '17 at 10:59

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.