Reputation: 1930
I have a liveview called Menu
with 3 Live Component Categories
, Products
, and Variants
phx-click
set up on each category, product, so when click on category, handle_event will
return assign(socket, :products, products) ProductsComponent
will products for the clicked category, and click on product, Variants will show.
And the handle_events are inside the Menu View
defmodule MyAppWeb.Admin.LocationLive.Menu do
use MyAppWeb, :live_view
import MyAppWeb.Admin.LocationLive.Helpers,
only: [
get_categories: 1,
get_products: 2,
get_variants: 2
]
alias MyApp.Manager.Base
@impl true
def mount(%{"id" => location_id}, _session, socket) do
case Base.get_location(location_id) do
nil ->
{:noreply, redirect(socket, Routes.admin_business_path(MyAppWeb.Endpoint, :index))}
location ->
{:ok,
socket
|> assign(:page_title, "Menu")
|> assign(:location, location)
|> assign(:products, [])
|> assign(:variants, [])
|> assign(:selected_category_id, nil)
|> assign(:selected_product_id, nil)
|> assign(:categories, get_categories(location)), temporary_assigns: [categories: []]}
end
end
@impl true
def handle_event(
"show-products",
%{"category" => category_id},
socket
) do
location = get_location(socket)
{:noreply,
socket
|> assign(:products, get_products(location, category_id))
|> assign(:variants, [])
|> assign(:selected_category_id, category_id)}
end
@impl true
def handle_event(
"show-variants",
%{"product" => product_id},
socket
) do
location = get_location(socket)
{:noreply,
socket
|> assign(:variants, get_variants(location, product_id))
|> assign(:selected_product_id, product_id)}
end
defp get_location(socket) do
socket.assigns.location
end
end
menu.html.leex
<div class="row">
<div class="<%= row_parts_class(4) %>">
<div class="align-items-center <%= row_parts_class(12) %>">
<h5 class="h5 font-weight-bold text-default">Categories</h5>
</div>
<%= live_component @socket, MyAppWeb.Admin.LocationLive.CategoriesComponent,
categories: @categories,
location: @location,
id: "categories-component"
%>
</div>
<div class="<%= row_parts_class(4) %>">
<div class="align-items-center <%= row_parts_class(12) %>">
<h5 class="h5 font-weight-bold text-default">Products</h5>
</div>
<%= live_component @socket, MyAppWeb.Admin.LocationLive.ProductsComponent,
products: @products,
location: @location,
category_id: @selected_category_id,
id: "products-component"
%>
</div>
<div class="<%= row_parts_class(4) %>">
<div class="align-items-center <%= row_parts_class(12) %>">
<h5 class="h5 font-weight-bold text-default">Variants</h5>
</div>
<%= live_component @socket, MyAppWeb.Admin.LocationLive.VariantsComponent,
variants: @variants,
location: @location,
product_id: @selected_product_id,
id: "variants-component"
%>
</div>
</div>
My problem is that after clicking on product, and variants are shown, then I go back to click on another category, it will show new products, but the old variants are still there. So I tried to assign(socket, :variants, [])
in category handle_event, but it throws an error in console no component for CID 2
, and the old Products and Variants components remain unchanged.
Anyone has any idea how to fix this or maybe a workaround to clear out the VariantsComponent everytime a category is clicked?
Thanks!
Upvotes: 3
Views: 338
Reputation: 1930
After playing around with it, I got the variants to hide by setting selected_product_id
to nil and put an if
statement around the Variants live component
<%= if @selected_product_id do %>
<%= live_component @socket, MyAppWeb.Admin.LocationLive.VariantsComponent,
variants: @variants,
location: @location,
product_id: @selected_product_id,
id: "variants-component"
%>
<% end %>
and inside of menu
{:noreply,
socket
|> assign(:products, get_products(location, category_id))
|> assign(:selected_product_id, nil)
|> assign(:selected_category_id, category_id)}
I guess this way, when live view pushes change to the view, it will check the if it should render the live component, which ends up hiding the variants component when selected_product_id
is nil
Upvotes: 0