An Introduction to Elm Series: Solution to ‘HTTP’ example 5


In the http://guide.elm-lang.org/architecture/effects/http.html, we were given a sample that loads random images from a web application on another service thought HTTP requests.

We were asked to print the error message of the request (if any) and update the UI to allow changing the topic (a parameter of the web call) either through an input field or a drop down list.

We wrote a message that accepts as string the new topic, that message is used both in the case of the input and in the case of the select list. Finally, we made sure that the ‘Please Wait’ image is shown while loading the new image from the remote server. The path for the ‘Please Wait’ image was added to a custom function to emulate a public static string value.

import Html exposing (..)
import Html.App as Html
import Html.Attributes exposing (..)
import Html.Events exposing (..)
import Http
import Json.Decode as Json
import Task



main =
  Html.program
    { init = init "cats"
    , view = view
    , update = update
    , subscriptions = subscriptions
    }



-- MODEL


type alias Model =
  { topic : String
  , gifUrl : String
  , error : String
  }

waitingImage : String
waitingImage =
  "5-http/waiting.png"

init : String -> (Model, Cmd Msg)
init topic =
  ( Model topic waitingImage ""
  , getRandomGif topic
  )



-- UPDATE


type Msg
  = MorePlease
  | FetchSucceed String
  | FetchFail Http.Error
  | NewTopic String


update : Msg -> Model -> (Model, Cmd Msg)
update msg model =
  case msg of
    MorePlease ->
      ({ model | gifUrl = waitingImage }, getRandomGif model.topic)

    FetchSucceed newUrl ->
      (Model model.topic newUrl "", Cmd.none)

    FetchFail error ->
      (Model model.topic waitingImage (toString error), Cmd.none)

    NewTopic newTopic ->
      ({ model | topic = newTopic }, Cmd.none)


-- VIEW


view : Model -> Html Msg
view model =
  div []
    [ h2 [] 
    , input [ type' "text", placeholder "Topic", onInput NewTopic ] []
    , select [ onInput NewTopic ]
      [ option [] [ text "Pokemon" ]
      , option [] [ text "SuperCars" ]
      , option [] [ text "Cyprus" ]
      , option [] [ text "Cats" ]
      , option [] [ text "Dogs" ]
      ]
    , button [ onClick MorePlease ] [ text "More Please!" ]
    , br [] []
    , img [src model.gifUrl] []
    , br [] []
    , div [] 
    ]



-- SUBSCRIPTIONS


subscriptions : Model -> Sub Msg
subscriptions model =
  Sub.none



-- HTTP


getRandomGif : String -> Cmd Msg
getRandomGif topic =
  let
    url =
      "//api.giphy.com/v1/gifs/random?api_key=dc6zaTOxFJmzC&tag=" ++ topic
  in
    Task.perform FetchFail FetchSucceed (Http.get decodeGifUrl url)


decodeGifUrl : Json.Decoder String
decodeGifUrl =
  Json.at ["data", "image_url"] Json.string

You can download the solution from here 5-http (compressed) (127 downloads)


Leave a Reply

5 thoughts on “An Introduction to Elm Series: Solution to ‘HTTP’ example

  • dskecse

    You don’t actually provide any commands in the `NewTopic` branch inside the `update` function. And seems like you don’t display errors, either.

    • xeirwn

      Hi,

      In order for you to use the ‘NewTopic’ feature, you have to type in the ‘Topic’ input the keyword of interest.
      While typing, the h2 title right above will change as you type.
      Once you picked your theme, click the ‘More Please’ button.
      That will give you the gif result using the custom input.

      About the errors:
      Change the code at the part where the url is defined to something irrelevant.
      e.g from “//api.giphy.com/v1/gifs/random?api_key=dc6zaTOxFJmzC&tag=” make it into “//api.bytefreaks.net/v1/gifs/random?api_key=dc6zaTOxFJmzC&tag=”.
      You will see that right below the image placeholder the error message reported by elm will appear and the image placeholder will show the default waiting image.
      The following image shows the result of this experiment.
      http://bytefreaks.net/elm-http-network-error