Hey all!
I‘m currently learning Phoenix and Elixir. My day job is working on the frontend side of things with React.
For fun, I started building a project management app for craftsmen. Different companies should use it. They‘d have projects, a calendar, overview of the latest changes,…
There’s a nested data structure that I have on the project detail page and I‘d love to get some advice on how to „think“ of this in a Phoenix-Elixir-way.
Each project has phases, each phase has tasks and each task can have appointments. I‘ve got all of these in separate data tables (another thing I never touched - data modeling on the db level ) which seems to be the correct way to do it, quite a few belongs_to
in there as well.
When I think about this from the UI side of things, my hunch is to add a form for „add task“ as a LiveComponent. I could of course do all of this at once in a single LiveView and render some nested data structure with different events for different forms. Or could I? Coming from Remix, I‘m used to thinking in nested routes, but that‘s unfortunately not a thing in Phoenix from what I understood so far.
Since I have almost no experience with all of this besides a few tutorials, I would love to get some feedback on how people handle these scenarios. Nested data structures have to be common scenarios, no?
Appreciate any thoughts and hints on this.
1 Like
Welcome at the forum, @HerrBertling
I am not exactly sure what you are looking for, but I’ll just throw these links in the mix. Maybe they are what you were looking for, maybe not and then we have narrowed down the problem space.
Please let me know if these links helped you.
Are there any Phoenix devs out there who feel the same? I myself haven’t done Phoenix projects were I missed nested routes but maybe there is demand…then I might write a proof of concept plugin for Routex.
Welcome @HerrBertling! Generally speaking, you may read data as nested but most updates happen within the data directly.
For example, if projects has phases, phases has tasks, and task have appointments, and you are showing them all on the same page, then you would likely load all of the data as nested, using Ecto’s preloads. On the other hand, if you only show appointments once you are seeing a task page, which is potentially a separate LiveView, you are likely only loading that particular task and its appointments.
When it comes to adding a new task, you most likely send only the “phase_id” to the server alongside the task parameters. Then when you receive the event, you validate the user can indeed edit and add tasks to that phase, and then you insert the task with its relevant phase_id to the database. The insertion does not need to go through the nesting.
3 Likes
I think that was the general mode of thinking I was looking for. I’m maybe too used to the “a route/subroute determines the data loaded/mutated” by Remix right now
Since all of this stuff should happen within the same view, I feel like a LiveComponent per form is the correct abstraction. I can encapsulate the logic there and handle any events in there as well.
I could have imagined loading everything in the LiveView and passing it down into the components. Handling the different changesets and events in the overall LiveView seems a bit cumbersome and convoluted, though. Anyways. I wasn’t aware of nested preloads until now. That will come in handy at some point!
Is it a "good thing"™ to preload everything, pass the data to the LiveComponent and then update that data from there? How would data revalidation then work? Changing the state of a task might affect the state of the whole phase (finish the last task => phase is completed), so I’d have to somehow revalidate all data to make sure the UI is not out of sync.
Oh, and @BartOtten, if the general idea is to mutate data directly “where you are”, I don’t need nested routes.
I guess I’m trying to carry over too many mental models from working in react-router/Remix that don’t really fit the mental models Phoenix uses. Just takes some time to adjust to that, I guess, and I’m trying to benefit from all of your experience
Thanks for the hints so far!