Last active
August 9, 2023 20:32
-
-
Save ultrox/89f188a72b909e3a69c94c446f7e25ea to your computer and use it in GitHub Desktop.
Elm 0.19.1 + RemoteData. How to use RemoteDetails talk from Kris Jenkins - Slaying a UI antypattern
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module Main exposing (..) | |
-- This code needs following dependencies: | |
-- elm/browser 1.0.2 | |
-- elm/html 1.0.0 | |
-- elm/http 2.0.0 | |
-- elm/json 1.1.3 | |
-- elm/random 1.0.0 | |
-- krisajenkins/remotedata 6.0.1 | |
-- NoRedInk/elm-json-decode-pipeline/ 1.0.1 | |
-- Can try it here: https://ellie-app.com/nBCdHpv2jRta1 | |
-- Watch video: https://www.youtube.com/watch?v=NLcRzOyrH08 | |
-- https://github.com/krisajenkins/remotedata/blob/master/src/RemoteData.elm | |
import Browser | |
import Html exposing (Html, br, div, input, text) | |
import Html.Attributes exposing (type_, value) | |
import Html.Events exposing (onClick) | |
import Http exposing (get) | |
import Json.Decode exposing (Decoder, string) | |
import Json.Decode.Pipeline exposing (required) | |
import Random exposing (generate, int) | |
import RemoteData exposing (RemoteData(..), WebData, asCmd, fromTask) | |
import Task exposing (Task, andThen, attempt, perform) | |
type alias Person = | |
{ name : String | |
, gender : String | |
} | |
type alias Starship = | |
{ name : String | |
, model : String | |
} | |
type alias Model = | |
{ person : WebData Person | |
, starship : WebData Starship | |
, counter : Int | |
} | |
type Msg | |
= PersonResponse (WebData Person) | |
| StarshipResponse (WebData Starship) | |
| GenerateRandomNumber | |
| NewNumber Int | |
decodePerson : Decoder Person | |
decodePerson = | |
Json.Decode.succeed Person | |
|> required "name" string | |
|> required "gender" string | |
decodeStarship : Decoder Starship | |
decodeStarship = | |
Json.Decode.succeed Starship | |
|> required "name" string | |
|> required "model" string | |
getPerson : Int -> Cmd Msg | |
getPerson id = | |
Http.get | |
{ url = "https://swapi.dev/api/people/" ++ String.fromInt id | |
, expect = Http.expectJson (RemoteData.fromResult >> PersonResponse) decodePerson | |
} | |
getStarship : Int -> Cmd Msg | |
getStarship id = | |
Http.get | |
{ url = "https://swapi.dev/api/starships/" ++ String.fromInt id | |
, expect = Http.expectJson (RemoteData.fromResult >> StarshipResponse) decodeStarship | |
} | |
randomIdGenerator : Random.Generator Int | |
randomIdGenerator = | |
int 1 100 | |
init : () -> ( Model, Cmd Msg ) | |
init _ = | |
( { person = Loading | |
, starship = NotAsked | |
, counter = 1 | |
} | |
, getPerson 1 | |
) | |
generateRandomNumberCmd : Cmd Msg | |
generateRandomNumberCmd = | |
Task.succeed 1 | |
|> Task.perform NewNumber | |
update : Msg -> Model -> ( Model, Cmd Msg ) | |
update msg model = | |
case msg of | |
NewNumber newNumber -> | |
( { model | |
| counter = newNumber | |
, person = Loading | |
, starship = Loading | |
} | |
, getPerson newNumber | |
) | |
GenerateRandomNumber -> | |
( model, generateRandomNumberCmd ) | |
PersonResponse response -> | |
( { model | |
| person = response | |
, starship = Loading | |
} | |
, getStarship 9 | |
) | |
StarshipResponse response -> | |
( { model | starship = response }, Cmd.none ) | |
view : Model -> Html Msg | |
view model = | |
case model.person of | |
NotAsked -> | |
viewPerson model "Initializing: " | |
Loading -> | |
viewPerson model "Loading: " | |
Failure err -> | |
viewPerson model ("Error: " ++ Debug.toString err) | |
Success news -> | |
viewPerson model "" | |
viewPerson : Model -> String -> Html Msg | |
viewPerson model error = | |
div [] | |
[ text error | |
, text (Debug.toString model.person) | |
, br [] [] | |
, text (Debug.toString model.starship) | |
, Html.p [] | |
[ input | |
[ onClick GenerateRandomNumber | |
, type_ "button" | |
, value "Get Person" | |
] | |
[] | |
] | |
] | |
main = | |
Browser.element | |
{ init = init | |
, update = update | |
, subscriptions = always Sub.none | |
, view = view | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment