sreyansjain
I am trying to use the main branch of phoenix liveview to test the new reset feature on streams
In my mix.exs I have
{:phoenix_live_view,
github: "phoenixframework/phoenix_live_view", branch: "main", override: true}
I have created a simple liveview example for a phonebook.
I have a list of names and an index at the top. Clicking on the index should load the contacts that start with the Index letter.
Whenever the index letter is clicked, i load all the relevant contacts, put them in the stream and set the reset flag to true.
This is working fine.
The Problem
Clicking on each contact opens up a modal with the contact details.
This works fine for the first time. Click on the modal, the modal appears.
But whenever the stream gets reset (after clicking a index letter), clicking on the contact brings up the modal, but the stream gets cleared and all contacts disappear.
I am not able to figure out why this is happening.
I tried to replace the stream, with normal assigns and everything works like it should (the modal appears and the contacts do not get cleared).
Can some one please advise as to why is this happening?
Full code is below
defmodule StreamsTestWeb.UserLive.Index do
use StreamsTestWeb, :live_view
@impl true
def render(assigns) do
~H"""
<div class="h-20 flex items-center space-x-12 border-b border-zinc-200 px-4 lg:px-8">
<div class="text-lg font-bold">Users</div>
</div>
<div class="tabs flex items-center gap-2 text-xs font-medium px-r lg:px-8 mt-8">
<.tab :for={tab <- @tabs} tab={tab} selected_tab={@selected_tab} />
</div>
<div :if={@term != ""} class="flex items-center gap-4 text-sm px-4 lg:px-8 mt-6">
<div class="text-zinc-500">Searching <em class="font-bold text-zinc-700"><%= @term %></em></div>
<button
type="button"
class="flex items-center gap-2 text-xs text-zinc-400 hover:text-zinc-600"
phx-click="clear_search"
>
<.icon name="hero-x-circle" class="w-5 h-5" />
</button>
</div>
<div class="px-4 lg:px-8">
<.table
id="users"
rows={@streams.users}
row_click={fn {_id, u} -> JS.push("show_user", value: %{id: u.id}) end}
>
<:col :let={{_id, s}} label="Name">
<%= s.name %>
</:col>
</.table>
</div>
<div id="modal_box">
<.modal :if={@user} id="detail-modal" show on_cancel={JS.push("hide_user")}>
<.header><%= @user.name %></.header>
</.modal>
</div>
"""
end
@impl true
def mount(_params, _session, socket) do
socket =
socket
|> assign(:tabs, get_tabs())
|> assign(:selected_tab, "All")
|> assign(:term, "")
|> assign(:user, nil)
|> stream(:users, get_users)
{:ok, stream(socket, :users, [])}
end
attr(:tab, :string, required: true)
attr(:selected_tab, :string, required: true)
def tab(assigns) do
~H"""
<div
class={[
"w-6 h-6 inline-flex items-center justify-center rounded cursor-pointer",
@tab == @selected_tab && "text-green-700 bg-green-100",
@tab != @selected_tab && "text-zinc-500 bg-transparent hover:text-zinc-700 hover:bg-zinc-100"
]}
phx-click="load_contacts"
phx-value-index={@tab}
>
<%= @tab %>
</div>
"""
end
@impl true
def handle_event("load_contacts", %{"index" => index}, socket) do
users = get_users() |> Enum.filter(fn s -> String.starts_with?(s.name, index) end)
socket =
socket
|> assign(:selected_tab, index)
|> assign(:term, "")
|> assign(:user, nil)
|> stream(:users, users, reset: true)
{:noreply, socket}
end
def handle_event("show_user", %{"id" => id}, socket) do
socket =
assign(
socket,
:user,
Enum.find(get_users, fn u -> u.id == id end)
)
{:noreply, socket}
end
def handle_event("hide_user", _params, socket) do
socket =
assign(
socket,
:user,
nil
)
{:noreply, socket}
end
defp get_tabs() do
[
"A",
"B",
"C",
"D",
"E",
"F",
"G",
"H",
"I",
"J",
"K",
"L",
"M",
"N",
"O",
"P",
"Q",
"R",
"S",
"T",
"U",
"V",
"W",
"X",
"Y",
"Z"
]
end
def get_users() do
[
%{id: 1, name: "A Name"},
%{id: 2, name: "B Name"},
%{id: 3, name: "C Name"},
%{id: 4, name: "D Name"},
%{id: 5, name: "E Name"},
%{id: 6, name: "F Name"},
%{id: 7, name: "G Name"},
%{id: 8, name: "H Name"},
%{id: 9, name: "I Name"},
%{id: 10, name: "J Name"}
]
end
end
Trending in Questions
Other Trending Topics
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #library
- #deployment
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #elixirconf
- #channels
- #exunit
- #discussion
- #code-sync
- #podcasts
- #javascript
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #ai
- #elixirconf-us
- #blog-post
- #elixir-ls
- #phoenix_html
- #iex
- #graphql
- #genstage
- #websockets
- #supervisor
- #advent-of-code
- #distillery
- #processes
- #api
- #forms
- #elixirconf-eu
- #metaprogramming
- #hex










Showing Posts 1 to 9- Show Best Posts
- Show All (oldest first)
- Show All (newest first)
sreyansjain
A video to better understand the issue
sreyansjain
This is happening
sreyansjain
One workaround is to make stream a part of the assigns by doing a delete operation for a non existent item.
Doing this makes the contacts not go away.
But i am still not able to understand why is this happening?
chrismccord
Are you positive the table’s tbody has
phx-update="stream"?sreyansjain
Yes.
cjbottaro
Oh, I think this may be related:
https://github.com/phoenixframework/phoenix_live_view/issues/2623
chrismccord
This is fixed on main. Thank you!
sreyansjain
Thank you so much @chrismccord
More power to you
Alvinkariuki
This aged well, thank you