10

I'm pretty new to Elm, but slowly getting familiar with it. I'm doing some simple Http Requests, which are successful in every aspect (I get the data to display, etc.)

For the moment I can only get my fetchData to trigger onClick, I would like to initialize this on init, but I'm having trouble wrapping my head around this.

....here is my fetchData function:

fetchData : Cmd Msg
fetchData =
  Http.get repoInfoListDecoder "http://example/api"
    |> Task.mapError toString
    |> Task.perform ErrorOccurred DataFetched

Which is currently trigger in the view by a onClick event:

.....
, button [ onClick FetchData ] [ text "Load Data" ]
.....

I want to avoid requesting the data by a button, instead I want the data to load when the app is initialized. Here is my init:

init =
  let
    model =
      { message = "Welcome", repos = [] }
  in
    model ! []

And my update (kind of stripped...for example's sakes):

update : Msg -> Model -> (Model, Cmd Msg)
update msg model =
  case msg of
    NoOp ->
      model ! []
    ...........
    FetchData ->
      { model | message="hi" } ! [fetchData]
    ...........
    DataFetched repos ->
      { model | repos = repos, message = "The data has been fetched!" } ! []

Does this makes sense? I'm just having difficulty initializing fetchData when the app loads, so I can display my data without having to hit a button to fetch it.

Thanks in advance!

Zimm i48
  • 2,901
  • 17
  • 26
mmmaceo
  • 151
  • 1
  • 9

3 Answers3

15

When you use Html.program, your init function returns the initial data for your Model and Command to be executed.

Commands are side-effects, like HTTP requests.

Try changing init so it runs a Command right away:

init: (Model, Cmd Msg)
init =
  let
    model =
      { message = "Welcome", repos = [] }
  in
    model ! [ fetchData ]
rofrol
  • 14,438
  • 7
  • 79
  • 77
halfzebra
  • 6,771
  • 4
  • 32
  • 47
1

Here is the type signature of Html.App.program. init accepts Cmd, you simply give your Cmd here.

program
    :  { init : (model, Cmd msg), update : msg -> model -> (model, Cmd msg), subscriptions : model -> Sub msg, view : model -> Html msg }
    -> Program Never
Tosh
  • 35,955
  • 11
  • 65
  • 55
1

Another way is to use Task, which hasn't been mentioned yet. You could try something like

initWithFlags : Flags -> ( Model, Cmd Msg)
initWithFlags flags =
    ( { user = flags.user }, (Task.perform fetchData) )
Joseph Cho
  • 4,033
  • 4
  • 26
  • 33