I’m thinking of using Phoenix Liveview to implement a tree explorer where one can drill down on parts of the tree which is collapsed by default. You can click on a node to expand it, revealing its children if it has any: (think of the file directory browser in the left pane of vscode).
The tree might be quite large (many elements and arbitrary depth) so I don’t want to have all of it sitting in the genserver memory so I was thinking of using temporary assigns so the data is passed and rendered on the client and then cleared from the genserver. In fact at first I want to pull in the first level (root’s) children only to begin with. And when one of those children is expanded by clicking on it, only then do I query it’s children and add them to the DOM, and so forth, lazily loading small portions at a time when each node is clicked and expanded.
My schema can be a simple adjacency list, something like:
has_many :children, Entity, foreign_key: :parent_id
The view would need to be able to handle nesting of entities (nested lists) of any depth so I was thinking of writing some recursive function using content_tag, that would recurse into a nested :ul if a node is preloaded with children (the idea being, we only populate the children attribute on the node if it was expanded).
For each entity that can be expanded, render a [+] icon with a phx-click that sends the id of the entity we want to expand. Then in the liveview handler, query the children of that id, and with that data… eh… do what?
Here’s where I get stuck. How do I update the socket assigns and put the expanded children into the tree at the right place, if using temporary assigns? I have no data retained in the genserver in order to find the nested sub node to update it’s children attribute.
can I just do socket assign and send down the expanded entity with children and hope that liveview can update the correct element simply because the replacement data shares the same DOM ID, no matter how nested down in the tree that element might be? All the examples I’ve read regarding use of temporary assigns operate on a flat list, so I don’t know if this will work on deeply nested DOM elements.
Hopefully I’ve explained what I have doubts about in a clear enough way…
I wanted to vet this idea and get some clarity, opinions or advice on this before I get too far. thanks!