I recently asked How would you add a conditional checkbox to a (stream) table?
The solution was to use CSS to toggle the column, but now I’m trying to do a similar task with a more complex element, it gives me a bad trade off. @garrison warned me at some point I’ll probably be pushing the boundaries of when using a stream is …convenient…, and I fear im at that point, but thought i’d gather some opinions on my solutions (see below) just in case
I want to show a ‘mini-table’ when a value in my table is clicked.
Taking the above image, the ‘button’ 2
in the Dogs
column was clicked, for Jeff
, revealing the names of the 2 dogs Jeff owns in a ‘mini table’ to the right of the ‘2’ I clicked on.
So CSS can position the ‘mini-table’, the HTML for it is in the button
of the value 2
. This means I can do absolute bottom-0 left-[calc(100%+10px)]
to position the mini-table
def render(assigns) do
~H"""
<.table id="pet-owner-table" rows={@streams.rows}>
<:col :let={{_, row}} label="Name">{row.name}</:col>
<:col :let={{_, row}} label="Dogs">
<.tooltip_button
row_id={row.id}
column="dogs"
show_tooltip?={@active_tooltip_row_id == row.id and @active_tooltip_column == "dogs"}
tooltip_rows={@tooltip_rows}
>
{row.dogs}
</.tooltip_button>
</:col>
...
</.table>
"""
end
...
def tooltip_button(assigns) do
~H"""
<.button phx-click="open_tooltip" phx-value-row_id={@row_id} phx-value-column={@column}>
{render_slot(@inner_block)}
<div
:if={@show_tooltip?}
class="card bg-base-100 shadow-sm absolute bottom-0 left-[calc(100%+10px)] z-10"
>
<.table id="tooltip-table" rows={@tooltip_rows}>
<:col :let={row} label="Dog Name">{row.name}</:col>
</.table>
</div>
</.button>
"""
end
As the table is using a stream, and the ‘mini-table’ is within the table, when the conditional logic @show_tooltip?
changes, a render will not be triggered.
Ideally I would also would want to update the tooltip_rows
aswell when the button is clicked.
Solution | Trade Off |
---|---|
I could render all ‘mini-tables’ with a class of hidden , and use JS.toggle_class on the specific ‘mini-tooltip’ table to show/hide it |
Lots of HTML. I would need a ‘mini-table’ for every column and every row that has this functionality. 100 rows * 2 columns with this functionality = an additional 200 tables, with all the rows pre-filled. |
Move the ‘mini-table’ to outside the stream, and use some JavaScript to calculate the position of where the ‘mini-table’ should be | I don’t wanna do some nasty JS ![]() |
Move the ‘mini-table’ to outside the stream, and use the css property position-anchor | position-anchor is not supported on all browsers ![]() |
Stop using a stream | I’m currently making use of infinite scrolling as I have thousands of rows and I lose the ability to cleanly stream_insert and stream_delete, which I’d rather keep |
So TLDR;
Solution 1 seems untenable, as I assume the sheer amount of extra elements on the DOM would quickly lead to the browser being overwhelmed. Also considering id need to pre-fill all the ‘mini-tables’ with rows too, adding additional elements.
With solution 4, keeping thousands (assuming the user has scrolled) of rows (with preloads) in the assigns doesn’t seem like a great idea either.
I guess i’m running out of excuses to not do a couple lines of JS? And when widely available swap to position-anchor…