Actually, instead of using the stream (proposed by default when using a generator), I use a classic assign {:ok, assign(socket, :items, list_items())}
as the list is not too large. But it looks a bit frustrating that such a classic task makes so much trouble
Since you are using the classic assign and assuming list_items()
always returns a list, you could conditionally show/hide with something like this:
<.table :if={Enum.any?(@items)} ...>...</.table>
<span :if={Enum.empty?(@items)}>No Articles</span>
Unless something has changed very recently, the generator is coded in a way that works with both a stream or a regular list. Perhaps the with
line at the top of the table
component that is confusing? The case
version would look like this:
assigns =
case assigns do
%{rows: %Phoenix.LiveView.LiveStream{} ->
assign(assigns, row_id: assigns.row_id || fn {id, _item} -> id end)
assigns ->
assigns
end
I was experimenting with a similar setup and I was having the same problem, adding an id to the empty placeholder block (in your case, the .empty
component) fixed the issue
This CSS trick works for my use case.
My try:
<ul phx-update="stream">
<li class="hidden last:block">
No items here.
</li>
<li :for={{dom_id, item} <- @streams.items} id={dom_id}>
...
</li>
</ul>
However, even if it works, my tests fail with:
30) test something (MyApp.MyTest)
test/my_app_web/live/my_liveview_test.exs:32
** (EXIT from #PID<0.1200.0>) an exception was raised:
** (ArgumentError) setting phx-update to "stream" requires setting an ID on each child. No ID was found on:
<li class="hidden last:block">
No items here.
</li>
(phoenix_live_view 0.19.5) lib/phoenix_live_view/test/dom.ex:520: anonymous fn/3 in Phoenix.LiveViewTest.DOM.apply_phx_update_children_id/2
(elixir 1.15.5) lib/enum.ex:2510: Enum."-reduce/3-lists^foldl/2-0-"/3
(phoenix_live_view 0.19.5) lib/phoenix_live_view/test/dom.ex:518: Phoenix.LiveViewTest.DOM.apply_phx_update_children_id/2
(phoenix_live_view 0.19.5) lib/phoenix_live_view/test/dom.ex:397: Phoenix.LiveViewTest.DOM.apply_phx_update/4
(floki 0.34.3) lib/floki/traversal.ex:6: anonymous fn/3 in Floki.Traversal.traverse_and_update/2
(floki 0.34.3) lib/floki/traversal.ex:18: Floki.Traversal.traverse_and_update/3
(floki 0.34.3) lib/floki/traversal.ex:23: Floki.Traversal.traverse_and_update/3
(floki 0.34.3) lib/floki/traversal.ex:37: Floki.Traversal.traverse_and_update/3
(floki 0.34.3) lib/floki/traversal.ex:18: Floki.Traversal.traverse_and_update/3
(floki 0.34.3) lib/floki/traversal.ex:23: Floki.Traversal.traverse_and_update/3
(floki 0.34.3) lib/floki/traversal.ex:37: Floki.Traversal.traverse_and_update/3
(floki 0.34.3) lib/floki/traversal.ex:18: Floki.Traversal.traverse_and_update/3
(floki 0.34.3) lib/floki/traversal.ex:23: Floki.Traversal.traverse_and_update/3
(floki 0.34.3) lib/floki/traversal.ex:37: Floki.Traversal.traverse_and_update/3
(floki 0.34.3) lib/floki/traversal.ex:18: Floki.Traversal.traverse_and_update/3
(floki 0.34.3) lib/floki/traversal.ex:37: Floki.Traversal.traverse_and_update/3
(floki 0.34.3) lib/floki/traversal.ex:18: Floki.Traversal.traverse_and_update/3
(floki 0.34.3) lib/floki/traversal.ex:23: Floki.Traversal.traverse_and_update/3
(floki 0.34.3) lib/floki/traversal.ex:6: Floki.Traversal.traverse_and_update/2
(phoenix_live_view 0.19.5) lib/phoenix_live_view/test/dom.ex:299: Phoenix.LiveViewTest.DOM.patch_id/4
I’m looking for a way to say to my liveview that I have a static (and so without ID) DOM element in my <ul phx-update="stream">
. I didn’t find yet. Maybe it just doesn’t exists for now
I’m surprised nobody already mentions this issue here
This happen after an update from v0.18.18 to v0.19.5 of phoenix_live_view
.
Edit: my workaround for now is using <li class="hidden last:block" id="untracked">
, not sure it’s a good idea
How did the :empty
psuedoselector fail you? Does the code below suit your needs?
<style>
/* Target contains children */
.track-empty > .track-empty__target + .track-empty__message { display: none; }
/* Target contains no children */
.track-empty > .track-empty__target:empty { display: none; }
.track-empty > .track-empty__target:empty + .track-empty__message { display: block; }
</style>
<div class="track-empty">
<ul class="track-empty__target" phx-update="stream">
<li :for={{dom_id, item} <- @streams.items} id={dom_id}>...</li>
</ul>
<div class="track-empty__message">
<p>No items here.</p>
</div>
</div>
I found this to be the most straightforward. I was hitting this error as well I guess the workaround is simply:
<.empty icon="clock-off" class="hidden only:block" id="insert-id-here">
<:title><%= dgettext("events", "No shifts") %></:title>
<:subtitle><%= dgettext("events", "There are no shifts for this event.") %></:subtitle>
</.empty>