Parse JSON to fill in elm-UI Template

Hi. I have a bunch of preexisting JSON files. This JSON contains business information that I need to render. For starters I’d like to render services.json and display it in the ‘content’ function in this template here

Here is what I can say about services.json.
There are 7 Services in total each with title, description, bigImgSrc, smallImgSrc, priceFullSet, timeFullSet and pros

services.json (Shortened)

[
  {
    "title": "Classic",
    "description": "Classic lashing is a technique in which a single extension is applied to one isolated natural lash. Classic lashes are perfect for adding length to your natural lash. Classic lashes will give the appearance of wearing mascara.",
    "bigImgSrc": "",
    "smallImgSrc": "/assets/images/lashes/classic/1.jpeg",
    "priceFullSet": "$110",
    "timeFullSet": "1 hour, 45 mins",
    "pros": [ "Can add length to natural lashes", "Gives the appearance of wearing mascara", "Can be a good option for people with thinner, shorter natural lashes"]
  },
  { 
    "title": 'ect...',
  }
]

I’ve tried a lot of different ways of doing this, here is recent iteration/attempt. I’ve tried to make the problem as simple as possible for now. I’m skipping actually querying an API or loading the services.json file from disk and just hard coding in the JSON into a String.

module Main exposing (main)

import Dict exposing (Dict)
import Html exposing (Html)
import Json.Decode as Decode exposing (Decoder)


type alias Services =
    List Service


type alias Service =
    { title : String
    , description : String
    , bigImgSrc : String
    , smallImgSrc : String
    , priceFullSet : String
    , timeFullSet : String
    , pros : Pros
    }

type alias Pros =
    List String

serviceDecoder : Decoder Service
serviceDecoder =
    Decode.map7 Service
        (Decode.field "title" Decode.string )
        (Decode.field "description" Decode.string )
        (Decode.field "bigImgSrc" Decode.string)
        (Decode.field "smallImgSrc" Decode.string)
        (Decode.field "priceFullSet" Decode.string)
        (Decode.field "timeFullSet" Decode.string)
        (Decode.field "pros" Decode.string)


servicesDecoder : Decoder Services
servicesDecoder =
    Decode.list serviceDecoder


main : Html msg
main =
    case Decode.decodeString servicesDecoder json of
        Ok service ->
            Html.div []
                [ Html.text <| "Thing 1"
                , Html.br [] []
                , Html.text <| "ThingTwo"
                ]

        Err error ->
            Html.text ("Error: " ++ Decode.errorToString error)

json : String
json =
    """
[
  {
    "title": "Classic",
    "description": "Classic lashing is a technique in which a single extension is applied to one isolated natural lash. Classic lashes are perfect for adding length to your natural lash. Classic lashes will give the appearance of wearing mascara.",
    "bigImgSrc": "",
    "smallImgSrc": "/assets/images/lashes/classic/1.jpeg",
    "priceFullSet": "$110",
    "timeFullSet": "1 hour, 45 mins",
    "pros": [ "Can add length to natural lashes", "Gives the appearance of wearing mascara", "Can be a good option for people with thinner, shorter natural lashes"]
  },
  {
    "title": "ect...",
  }
]
"""

As you can probably see, it’s far from complete and any help would be appreciated. New to Elm and i’ve spent all night on this (very tired).

I also need to render it kind of like this but with formatting for each service instead of just a dump of text. https://i.gyazo.com/b87f7c1f2730691854b48843f5d17e99.mp4 - Link to a hosted .mp4 demonstration

The code for the video is here.

module HeaderAndFooterLayout exposing (..)

import Element exposing (..)
import Element.Background as Background
import Element.Border as Border
import Element.Font as Font
import Html exposing (Html)


main : Html msg
main =
    layout [ width fill, height fill ] <|
        column [ width fill ]
            [ header
            , content
            , footer
            ]


header : Element msg
header =
    row [ width fill, padding 20, spacing 20 ]
        [ logo
        , el [ alignRight ] <| text "Services"
        , el [ alignRight ] <| text "About"
        , el [ alignRight ] <| text "Contact"
        ]


content : Element msg
content =
    List.range 0 7
        |> List.map
            (\i ->
                el [ centerX, Font.size 10, Font.color <| rgb255 (i * 20) (i * 20) (i * 20) ] <|
                    text json 
            )
        |> column [ width fill, padding 50 ]


footer : Element msg
footer =
    row
        [ width fill
        , padding 10
        , Background.color color.lightBlue
        , Border.widthEach { top = 1, bottom = 0, left = 0, right = 0 }
        , Border.color color.blue
        ]
        [ logo
        , column [ alignRight, spacing 10 ]
            [ el [ alignRight ] <| text "Services"
            , el [ alignRight ] <| text "About"
            , el [ alignRight ] <| text "Contact"
            ]
        ]


logo : Element msg
logo =
    el
        [ width <| px 80
        , height <| px 40
        , Border.width 2
        , Border.rounded 6
        , Border.color color.blue
        ]
        none


color =
    { blue = rgb255 0x72 0x9F 0xCF
    , darkCharcoal = rgb255 0x2E 0x34 0x36
    , lightBlue = rgb255 0xC5 0xE8 0xF7
    , lightGrey = rgb255 0xE0 0xE0 0xE0
    , white = rgb255 0xFF 0xFF 0xFF
    }


json : String
json =
  """
[
  {
    "title": "Classic",
    "description": "Classic lashing is a technique in which a single extension is applied to one isolated natural lash. Classic lashes are perfect for adding length to your natural lash. Classic lashes will give the appearance of wearing mascara.",
    "bigImgSrc": "",
    "smallImgSrc": "/assets/images/lashes/classic/1.jpeg",
    "priceFullSet": "$110",
    "timeFullSet": "1 hour, 45 mins",
    "pros": [ "Can add length to natural lashes", "Gives the appearance of wearing mascara", "Can be a good option for people with thinner, shorter natural lashes"]
  },
  {
    "title": "ect...",
  }
]
"""

You could start by making a rendering function for your Service type with the formatting you need, then map it over the list of services you got when decoding your json.

Example here: https://ellie-app.com/j9fWVmtV8gHa1

Thank you so much for your help! This is exactly what I needed.

In order to get to the point where services is rendered when the services button is pressed. Then the about.json is rendered when I press the about button. I need to define the model view and update correct? Would it be a good idea this point to consider using something like elm-pages?

You could first try using the basic elm-architecture before elm pages.
https://guide.elm-lang.org/architecture/
If at some point you need http requests to get your json, you could replace your main by Browser.element, it should give you the functionality you need.
https://package.elm-lang.org/packages/elm/browser/latest/Browser#element

This topic was automatically closed 10 days after the last reply. New replies are no longer allowed.