There must be someone try to add sorting and filtering functions to LiveView streams. Below is my try based on the book, Building Table Views with Phoenix LiveView.
IO.inspect socket
shows products
are sorted as intended, but, streams
are not changed. Screen also DOES NOT reflect the change of products
.
How to reflect the change of products
to streams
?
Below is my code, anyone who have sorted data tables before can easily grasp how the code works.
defmodule MarketWeb.ProductLive.Index do
use MarketWeb, :live_view
# context
alias Market.Catalog
# db schema
alias Market.Catalog.Product
# live component
alias MarketWeb.Forms.SortingForm
def mount(_params, _session, socket) do
# auto generated
{:ok, stream(socket, :products, Catalog.list_products())}
end
def handle_params(params, _url, socket) do
# verity params from live component, SortingComponent.ex, and add the to socket.assigns
socket =
socket
|> parse_params(params)
# auto generated
{:noreply, apply_action(socket, socket.assigns.live_action, params)}
end
defp parse_params(socket, params) do
with {:ok, sorting_opts} <- SortingForm.parse(params) do
assign_sorting(socket, sorting_opts)
else
_error ->
assign_sorting(socket)
end
end
defp assign_sorting(socket, overrides \\ %{}) do
# allocate default values when no params from live component, SortingComponent.ex
opts = Map.merge(SortingForm.default_values(), overrides)
assign(socket, :sorting, opts)
end
defp apply_action(socket, :index, params) do
socket
|> assign(:page_title, "Listing Products")
|> assign(:products, Catalog.list_products(params))
|> IO.inspect # Let's see data table.
end
# receive event from live component, SortingComponent.ex
def handle_info({:update, params}, socket) do
path = ~p"/products/?#{params}"
{:noreply, push_patch(socket, to: path, replace: true)}
end
... unnecessary codes are omitted.
end
Below is the result of IO.inspect socket
in the code above. Sorting order is unit_price
and descending
as shown below.
#Phoenix.LiveView.Socket<
id: "phx-F1Pr9Wrf_AgiPRth",
endpoint: MarketWeb.Endpoint,
view: MarketWeb.ProductLive.Index,
parent_pid: nil,
root_pid: #PID<0.1837.0>,
router: MarketWeb.Router,
assigns: %{
__changed__: %{
current_user: true,
page_title: true,
products: true,
sorting: true,
streams: true
},
current_user: #Market.Accounts.User<
__meta__: #Ecto.Schema.Metadata<:loaded, "users">,
id: 1,
email: "jupeter@jeju.kr",
confirmed_at: nil,
inserted_at: ~N[2023-04-08 07:41:07],
updated_at: ~N[2023-04-08 07:41:07],
...
>,
flash: %{},
live_action: :index,
page_title: "Listing Products",
products: [
%Market.Catalog.Product{
__meta__: #Ecto.Schema.Metadata<:loaded, "products">,
id: 3,
name: "장갑",
unit_price: 59.742,
inserted_at: ~N[2023-04-08 07:40:48],
updated_at: ~N[2023-04-08 07:40:48]
},
%Market.Catalog.Product{
__meta__: #Ecto.Schema.Metadata<:loaded, "products">,
id: 2,
name: "부동산",
unit_price: 50.378,
inserted_at: ~N[2023-04-08 07:40:48],
updated_at: ~N[2023-04-08 07:40:48]
},
%Market.Catalog.Product{
__meta__: #Ecto.Schema.Metadata<:loaded, "products">,
id: 1,
name: "í•śęµ ęµě±„",
unit_price: 23.598,
inserted_at: ~N[2023-04-08 07:40:48],
updated_at: ~N[2023-04-08 07:40:48]
}
],
sorting: %{sort_by: :unit_price, sort_dir: :desc},
streams: %{
__changed__: MapSet.new([:products]),
products: %Phoenix.LiveView.LiveStream{
name: :products,
dom_id: #Function<3.113057034/1 in Phoenix.LiveView.LiveStream.new/3>,
inserts: [
{"products-1", -1,
%Market.Catalog.Product{
__meta__: #Ecto.Schema.Metadata<:loaded, "products">,
id: 1,
name: "í•śęµ ęµě±„",
unit_price: 23.598,
inserted_at: ~N[2023-04-08 07:40:48],
updated_at: ~N[2023-04-08 07:40:48]
}},
{"products-2", -1,
%Market.Catalog.Product{
__meta__: #Ecto.Schema.Metadata<:loaded, "products">,
id: 2,
name: "부동산",
unit_price: 50.378,
inserted_at: ~N[2023-04-08 07:40:48],
updated_at: ~N[2023-04-08 07:40:48]
}},
{"products-3", -1,
%Market.Catalog.Product{
__meta__: #Ecto.Schema.Metadata<:loaded, "products">,
id: 3,
name: "장갑",
unit_price: 59.742,
inserted_at: ~N[2023-04-08 07:40:48],
updated_at: ~N[2023-04-08 07:40:48]
}}
],
deletes: []
}
}
},
transport_pid: #PID<0.1831.0>,
...
>
Screen is reflecting data of streams
, not that of products
above, but sorting changes products
only.