Created
July 12, 2020 05:23
-
-
Save ryan-haskell/3ce83ec17ed473717e5604c7047e4d2c to your computer and use it in GitHub Desktop.
Used in the "Using APIs" section of in the elm-spa guide
This file contains 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
-- src/Api.elm | |
module Api exposing (Data(..), expectJson) | |
import Http | |
import Json.Decode as Json | |
type Data value | |
= NotAsked | |
| Loading | |
| Failure Http.Error | |
| Success value | |
expectJson : (Data value -> msg) -> Json.Decoder value -> Http.Expect msg | |
expectJson toMsg = | |
Http.expectJson (fromResult >> toMsg) | |
fromResult : Result Http.Error value -> Data value | |
fromResult result = | |
case result of | |
Ok value -> | |
Success value | |
Err reason -> | |
Failure reason |
This file contains 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
-- src/Api/Reddit/Listing.elm | |
module Api.Reddit.Listing exposing | |
( Listing | |
, hot, top, new | |
) | |
{-| | |
@docs Listing | |
@docs hot, top, new | |
-} | |
import Api | |
import Http | |
import Json.Decode as Json | |
type alias Listing = | |
{ title : String | |
, author : String | |
, url : String | |
} | |
decoder : Json.Decoder Listing | |
decoder = | |
Json.map3 Listing | |
(Json.field "title" Json.string) | |
(Json.field "author_fullname" Json.string) | |
(Json.field "url" Json.string) | |
-- ENDPOINTS | |
hot : { onResponse : Api.Data (List Listing) -> msg } -> Cmd msg | |
hot = | |
listings "hot" | |
top : { onResponse : Api.Data (List Listing) -> msg } -> Cmd msg | |
top = | |
listings "top" | |
new : { onResponse : Api.Data (List Listing) -> msg } -> Cmd msg | |
new = | |
listings "new" | |
listings : String -> { onResponse : Api.Data (List Listing) -> msg } -> Cmd msg | |
listings endpoint options = | |
Http.get | |
{ url = "https://api.reddit.com/r/elm/" ++ endpoint | |
, expect = | |
Api.expectJson options.onResponse | |
(Json.at [ "data", "children" ] (Json.list decoder)) | |
} |
This file contains 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
-- src/Pages/Posts.elm | |
module Pages.Posts exposing (Model, Msg, Params, page) | |
import Api | |
import Api.Reddit.Listing exposing (Listing) | |
import Html exposing (..) | |
import Html.Attributes exposing (class, href) | |
import Spa.Document exposing (Document) | |
import Spa.Page as Page exposing (Page) | |
import Spa.Url exposing (Url) | |
page : Page Params Model Msg | |
page = | |
Page.element | |
{ init = init | |
, update = update | |
, view = view | |
, subscriptions = subscriptions | |
} | |
-- INIT | |
type alias Params = | |
() | |
type alias Model = | |
{ listings : Api.Data (List Listing) | |
} | |
init : Url Params -> ( Model, Cmd Msg ) | |
init url = | |
( Model Api.Loading | |
, Api.Reddit.Listing.hot | |
{ onResponse = GotHotListings | |
} | |
) | |
-- UPDATE | |
type Msg | |
= GotHotListings (Api.Data (List Listing)) | |
update : Msg -> Model -> ( Model, Cmd Msg ) | |
update msg model = | |
case msg of | |
GotHotListings data -> | |
( { model | listings = data } | |
, Cmd.none | |
) | |
subscriptions : Model -> Sub Msg | |
subscriptions model = | |
Sub.none | |
-- VIEW | |
view : Model -> Document Msg | |
view model = | |
{ title = "Posts" | |
, body = | |
[ div [ class "page" ] | |
[ viewListings model.listings | |
] | |
] | |
} | |
viewListings : Api.Data (List Listing) -> Html msg | |
viewListings data = | |
case data of | |
Api.NotAsked -> | |
text "Not asked" | |
Api.Loading -> | |
text "Loading..." | |
Api.Failure _ -> | |
text "Something went wrong..." | |
Api.Success listings -> | |
div [ class "listings" ] | |
(List.map viewListing listings) | |
viewListing : Listing -> Html msg | |
viewListing listing = | |
div [ class "listing" ] | |
[ a [ class "title", href listing.url ] | |
[ text listing.title ] | |
, p [ class "author" ] | |
[ text ("Author: " ++ listing.author) ] | |
] |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment