I’m currently exploring Phoenix with LiveView and struggling to find a good reference or tutorial on handling data and navigation between two screens.
My app consists of:
A sidebar (mainly for navigation, not the focus here).
A data grid displaying full entries from a database table, including SVG data.
A complex editor for modifying database entries (with many fields and an SVG editor).
Potentially more screens in the future (not a current requirement).
What would be the best way to pass all column data (basically the contents of one row) to the editor view when clicking the “Edit” button for a row? Would LiveComponents be a good fit, even if they represent a full “screen” and aren’t needed for reuse? Or is there a better approach?
Sharing some code/pseudo-code would help give an answer that’s more tailored to your specific situation, but it sounds like regular Phoenix Components or Phoenix Live Components fit your use case.
There’s a few discussions on when to use one over the other in the forum (e.g., here)
Both approaches would have you pass the data in the assigns map.
You can also pass the id of the row to be edited as a parameter to a separate editor liveview and reload it from there. If it’s in a database it’s going to be plenty fast enough in normal circumstances.
If you use a live component it will need to be “hosted” within the liveview with the data grid, which either means careful thinking about screen real estate, or a modal. The modal approach is well illustrated using the default generators in Phoenix (phx.gen.live). You’ll need to remember to refresh your data grid to show the changes when you save them if you use this approach. I find the code generated a bit tricky to follow as it uses “actions” in the router to show & hide the edit screen. Rather than use the actions / id approach in the generator approach, you can also set an internal assign on the socket with the data you are editing and pass that to the live component.
My preference would usually to build a separate liveview and navigate to it unless you really want an editor in the same view as the data grid. You can configure your router so this all happens in the same web socket connection, so it feels really slick to the end user.
kudos for the great explanation, i would have struggled to do as good a job without pasting some pseudo-code
@MostLee just a thought, we might be falling victim to the XY problem here.
if you’re focused on “pass[ing] all column data (basically the contents of one row)”, then i think using assigns is the standard approach. But if you’re working on a page to edit/update your ‘row’, and you don’t need to pass all that data, i’d recommend you go with the approach the Phoenix generators follow - you’ll be able to find more references examples if you stick with those.
A LiveComponent can be a good tool for scoping state and events. If your editor is “complex” as you say it will probably contain its own state and events, so this is a perfectly valid solution (even if you don’t reuse it).
The best way to pass the data down is highly dependent on your use case. For example, you may just want to pass the (already loaded) row information directly to the editor component.
However, it is not hard to imagine a use case where the version loaded in the “table view” is a stripped-down version which is missing fields needed for the editor. As a simple example, a social media feed might contain only titles, but once clicked you must also show the post content.
In this latter case it may be simpler to pass only a database id down to the editor component and let it load its own data from the database on the first update/2 call.
Reloading can be especially nice approach when it comes to shared resources that multiple users might attempt to read/write at the same time.
In these cases, you’ll also want to look at pubsub to broadcast those in progress edits and successful updates. Then subscribe to those broadcasts to potentially add indicators/signifiers/locks to the data grid and editor screens.