我需要在累积先前状态的同时渲染 LiveView 流。对于常规集合,我会使用递归:
def mount(_, _, socket) do
{:ok, assign(socket, list: [1, 2, 3])}
end
def render(assigns) do
~H"""
<.list list={@list} prev="first" />
"""
end
defp list(%{list: []} = assigns), do: ~H""
defp list(assigns) do
~H"""
<div>
<%= "cur: #{hd(@list)}, prev: #{@prev}" %>
<.list list={tl(@list)} prev={hd(@list)} />
</div>
"""
end
如果我用 LiveView 流替换
list
可以吗?
你绝对可以用流来做到这一点,甚至还有像
stream/4
、stream_insert/4
和 stream_delete/3
这样的函数专门用于这种用途(这里不需要递归):
def mount(socket) do
{:ok, stream_configure(socket, :songs, dom_id: &("songs-#{&1.id}"))}
end
def render(assigns) do
~H"""
<table>
<tbody id="songs" phx-update="stream">
<tr :for={{dom_id, song} <- @streams.songs} id={dom_id}>
<td><%= song.title %></td>
<td><button phx-click={JS.push("delete", value: %{dom_id: dom_id})}>delete</button></td>
<td><button phx-click={JS.push("update", value: %{song_id: song.id})}>update</button></td>
</tr>
</tbody>
</table>
"""
end
def handle_event("delete", %{"dom_id" => dom_id}, socket) do
{:noreply, stream_delete_by_dom_id(socket, :songs, dom_id)}
end
def handle_event("update", %{"song_id" => song_id}, socket) do
song = get_song!(song_id)
socket
|> stream_delete(:songs, song)
|> stream_insert(:songs, song, at: -1)
end