Reputation: 559
How can I make two independent action inside one function in Elm? Is there any pattern or explicit function?
Generally speaking I'm not sure how to implement ajax data loading inside Elm Architecture.
For example I'd like to make Http.get
and return modified argument function like this
fetchCustomers model =
Http.get parseCustomers "/customers" `andThen` setCustomers
{ model | fetchingCustomers <- True }
Upvotes: 3
Views: 665
Reputation: 5958
You do so by returning both in a tuple. Then you split the signal from your update in foldp
, put the model part in the view function and put the tasks in a port to execute. This is alluded to in the Architecture post at the end under One Last Pattern.
Since you link to the Elm Architecture, let me link to that too, but in particular the last part: One Last Pattern.
What you want to do here is part of the "update" of your program, where you not only update your model but also do something else on the side. Therefore you do not just return the new model, but also the extra thing you want to do (in this case an Http request):
fetchCustomers model =
( { model | fetchingCustomers <- True }
, Http.get parseCustomers "/customers" `andThen` setCustomers
)
Instead of using StartApp like the architecture page does, you can paste in the start
function from the package. Now you have access to the mailbox where the actions are coming from, so you can pass it to your update so you can send your Http
results there too. And you can split the tuple that you're returning from the update function to actually execute the tasks:
start app =
let
actions =
Signal.mailbox Nothing
address =
Signal.forwardTo actions.address Just
model =
Signal.foldp
(\(Just action) (model,_) -> app.update actions action model)
-- ignore task: ^ ^^^ ^^^^^^^^:add mailbox
app.model
actions.signal
in
(Signal.map (fst >> app.view address) model, Signal.map snd model)
-- ^ ^^^^^^^ :split model: ^^^^^^^^^^^^^^^^^^^^^^^
fetchCustomers actions model =
( { model | fetchingCustomers <- True }
, Http.get parseCustomers "/customers"
`andThen` (SetCustomers >> Signal.send actions.address)
-- use mailbox to send Http results as an input action again
)
-- larger update function you probably have
update actions action model = case action of
-- ...
SetCustomers cust -> setCustomers cust
-- ...
-- fetchCustomers actions model
(output, tasks) = start { model: model, view: view, update: update }
-- task execution:
port httpGets = tasks
-- output your view
main = output
You can find more examples of doing Http
on the website under "tasks".
Upvotes: 3