I’ve used (read: stolen) the architecture from elm-spa-example and Elm packages repository for the apps I write at work and it’s worked really well, however I’m trying to introduce some new features that require cross-page data that I’m struggling to understand how to manage. I’d really appreciate some examples or advice on how to structure some global data.
What I’d like to accomplish is fetching some global data that’s shared amongst pages. I see that the Elm packages site manages this by having the individual pages request the data. When the data comes in, they modify the Session with the cached data. A drawback of this approach is that the messages always get routed back to the requesting page. Navigating around quickly means those requests get lost. Without getting into gory details, the app involves fetching long-running jobs, so this is a real risk.
Right now, I follow nested TEA with my “main” Model being a custom type with a case for every page. I have a Session module and type with a small amount of global data and have an exit function that pulls the session out so I can pass it to other pages, but that’s just pulled in from flags - I currently don’t update it anywhere.
I’ve read about global actions and translator, but what I’m missing from that is good architecture around this part:
We might need to send a message back to the module that returned the action. E.g. Open a dialog with selections. In this case our actions might need a message associated with them e.g. Action Msg. We will need a Actions.map to just like Html.map
How do I best keep track of these requests and make sure that the requesting module gets notified of its completion? I can’t just “bind” to the data in the session, I may need to pull in a copy once it’s loaded to do the whole “local modification” thing. Here’s a simplified view of the models:
-- Session.elm
type alias Job =
{ id : Int
-- ...
}
type alias JobResult =
{ id : Int
-- ...
}
type Data = Data
{ jobs : Dict Int Job
, results : Dict Int JobResult
}
-- Main.elm
type Model
= Home Home.Model -- Lists jobs
| Job Job.Model -- Lists job results
| JobResult JobResult.Model -- Shows result details
-- Page/Job.elm
type alias LocalResult =
{ job : Job
, checked : Bool
-- ...
}
type alias Model =
{ session : Session.Data
, results : WebData (List LocalResult)
}
I’d like to support something like
- Submit a job. Navigate to the results. See results pull in live.
- Arriving directly at a job result page via URL. Fetch other results in the background.
- Navigate to a result page. It’s not loaded yet, but the request is already running, so I don’t need to fire a new one, and when complete will populate the page’s model with the results.
Perhaps I’m trying to over-optimize a user experience here, but in any case, it’s a useful thought experiment about state management for a more complex app.
I wish I could share the full code, but unfortunately, it’s company code. I know it’s difficult to think about without actually seeing it, but any advice is always appreciated
.