2

我有一个Menu使用 3 Live Component CategoriesProductsVariants

phx-click对每个类别、产品进行设置,因此当点击类别时,handle_event 将返回assign(socket, :products, products)ProductsComponent将产品为点击的类别,然后点击产品,将显示变体。

并且handle_events 在菜单视图内

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>

我的问题是,点击产品后,显示变体,然后我返回单击另一个类别,它会显示新产品,但旧变体仍然存在。所以我尝试assign(socket, :variants, [])在类别中处理事件,但它在控制台中引发错误no component for CID 2,并且旧的 Products 和 Variants 组件保持不变。

在此处输入图像描述

任何人都知道如何解决此问题,或者每次单击类别时清除 VariantsComponent 的解决方法?

谢谢!

4

1 回答 1

0

在玩弄它之后,我通过设置selected_product_id为 nil 来隐藏变体,并if在 Variants live 组件周围放置一个语句

<%= 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 %>

和菜单里面

{:noreply,
 socket
 |> assign(:products, get_products(location, category_id))
 |> assign(:selected_product_id, nil)
 |> assign(:selected_category_id, category_id)}

我猜这样,当实时视图将更改推送到视图时,它会检查是否应该渲染实时组件,最终在selected_product_id为 nil时隐藏变体组件

于 2020-05-20T19:14:15.910 回答