kayne
kayne

Reputation: 349

Elm - Get JSON List Data

I'm trying to get the JSON data list from this URL : https://raw.githubusercontent.com/raywenderlich/recipes/master/Recipes.json

I couldn't understand what to do in this situation

...
main =
  App.program
  { init = init
  , view = view
  , update = update
  , subscriptions = \_ -> Sub.none
  }

-- MODEL

type alias Model =
  { name : String
  , imageURL: String
  }

init =
  (Model "" "", Cmd.none)

-- UPDATE

type Msg
  = Recipes
  | FetchSucceed (List Model)
  | FetchFail Http.Error

update msg model =
  case msg of
    Recipes ->
      (model, fetchRecipes)

    FetchSucceed recipe ->
      (recipe, Cmd.none)

    FetchFail _ ->
      (model, Cmd.none)


-- VIEW

view model =
  div []
    [ ul [] (List.map getItem model)
  ]


getItem item =
  li [] [ text item.name ]

-- HTTP

fetchRecipes =
  let
    url =
      "https://raw.githubusercontent.com/raywenderlich/recipes/master/Recipes.json"
  in
    Task.perform FetchFail FetchSucceed (Http.get decodeListRecipes url)


decodeRecipes =
  Json.object2 Model
    ("name" := Json.string)
    ("imageURL" := Json.string)

decodeListRecipes =
  Json.list decodeRecipes

But I keep getting this error :

Function `program` is expecting the argument to be:
    { ...,
      update :
        Msg
          -> { imageURL : String, name : String }
          -> ( { imageURL : String, name : String }, Cmd Msg ) ,
        view : { imageURL : String, name : String } -> Html Msg
    }

But it is: 
   { ...
   , update : Msg -> List Model -> ( List Model, Cmd Msg )
   , view : List { a | name : String } -> Html b
   }

Upvotes: 1

Views: 276

Answers (1)

Chad Gilbert
Chad Gilbert

Reputation: 36375

Your FetchSucceed tag is defined as having a list of models (FetchSucceed (List Model)), but in your update function you are treating it as if it is a single model rather than a list. If I change the value to plural, it should emphasize the problem area:

FetchSucceed recipes ->
    (recipes, Cmd.none)

Without knowing exactly what you are trying to achieve, I can only offer a hint at a potential solution, such as, if you merely wanted to take the first element of the list and fall back on the current model if no recipes are returned, you could do something like this:

FetchSucceed recipes ->
    let recipe =
        case List.head recipes of
            Just r -> r
            Nothing -> model
    in
        (recipe, Cmd.none)

Upvotes: 1

Related Questions