Live View with a Session and PubSub Based Shopping Cart

Hello everyone,

I have a little project to work on in order to learn phoenix. It’s more or less a simple e commerce platform.

I’m struggling at adding products to a session based shopping cart.

In general, I want to go for the following approach, to manage the cart within a live view:

  1. Plug initializes the cart within the session and adds an id
  2. I wrap views in a live_session and an on_mount hands on the cart from the session to the socket and
  3. subscribes to a pubsub using the id.
  4. The cart is altered through an extra request to a classic controller that changes the cart in the session and…
  5. Triggers an update of the cart component using the pubsub.

I need help at point 2 right now. I don’t really now what I’m doing wrong, if I compare it to similar examples, I feel I’m doing it right but… maybe you can help me to spot the error.

# routers.ex
live_session :add_cart_to_socket, on_mount: {LeihladenWeb.Cart, :add_cart} do
      live "/products", ProductLive.Index, :index
end
# cart.ex
defmodule LeihladenWeb.Cart do
  use LeihladenWeb, :controller

  import Plug.Conn
  alias Phoenix.Component

  def on_mount(:add_cart, _params, %{"cart" => cart}, socket) do
    {:cont, Component.assign(socket, :cart, cart)}
  end
end
# cart_component.ex
defmodule LeihladenWeb.Components.Cart do
  use Phoenix.LiveComponent

  def render(assigns) do
    ~H"""
    <div id="cart">
      <h2>Cart</h2>
      <%= @cart %>
    </div>
    """
  end
end

The on_mount method is called and does not throw an error but somehow I cannot access the cart in component’s template:

key :cart not found in: %{...

Can you tell me, what I’m doing wrong?

Thank you very much :slight_smile:

Mark

Hi, @maqnius :wave: and welcome!
While on_mount hook assigns :cart to the main live_view socket - I see that LeihladenWeb.Components.Cart is a LiveComponent. Do you pass the value of :cart as an assign to Cart when rendering?

I would expect in the render for ProductLive.Index to see something like:

#                                        ↓↓ this ↓↓↓
<.live_component module={Cart} id="cart" cart={@cart} />

@RudManusachi ahh good catch! Thank you very much, that was the missing peace! Makes totally sense :slight_smile: