pentacent / phoenix_live_session

Live sessions for Phoenix LiveView and Phoenix Controllers
Apache License 2.0
80 stars 19 forks source link

Useage in components #4

Closed johns10 closed 3 years ago

johns10 commented 3 years ago

How does one use this library in a component? I got everything wired up, and tried to do this in my component:

  def handle_event("browser-opened", params, socket) do
    attrs = %{ browser_session: params["sessionId"] }
    user = update_user(socket.assigns.current_user, attrs)
    {
      :noreply,
      socket
      |> PhoenixLiveSession.put_session("browser_opened", true)
      |> assign(:browser_opened, true)
      |> assign(:current_user, user)
    }
  end

Which resulted in:

(KeyError) key :__live_session_id__ not found in: (assigns contents)

I'm going to try and figure out what and how to pass down the live session id to the component and will post findings.

Looks like this is similar to #3.

Same feedback. Session management has been a huge problem for me when developing in live view, and this library solves it.

johns10 commented 3 years ago

I implemented a test in a live_view instead of a live component, but I still get the same error. I think I've missed something in my setup, or I'm doing something incompatible.

johns10 commented 3 years ago

User error. PhoenixLiveSession.maybe_subscribe(session) is required to set up the socket with __live_session_id__

johns10 commented 3 years ago

I've been able to get this working in the live_view, but I can't call PhoenixLiveSession.put_session(socket, "browser_opened", true) because __live_session_id__ isn't available, and I don't think I can pass it down because it's not accessible in the template.

johns10 commented 3 years ago

I've been able to make this work with a live_component by using the same solution in #3. If I wrap my live_component call in if Phoenix.LiveView.connected?(@socket) and pass it __live_session_id__, it works:

= if Phoenix.LiveView.connected?(@socket) do 
  = live_component(@socket, UserDocsWeb.DrawerLive, 
  [ ...,  __live_session_id__: @__live_session_id__ ])
johns10 commented 3 years ago

I think my initial inclination here is not correct. This should all be handled in the live view, and the appropriate assigns should be passed to the components.

johns10 commented 3 years ago

Yep, solved it like this:

Component

  def handle_event("browser-opened", _params, socket) do
    send(self(), { :update_session, [ { "browser_opened", true } ] })
    { :noreply, socket }
  end

Live View

  def handle_info({ :update_session, params }, socket) do
    socket =
      Enum.reduce(params, socket,
        fn({ k, v }, inner_socket) ->
          PhoenixLiveSession.put_session(inner_socket, k, v)
        end
      )
    { :noreply, socket }
  end

  def handle_info({ :live_session_updated, params }, socket) do
  {
    :noreply,
    socket
    |> maybe_update_user_opened_browser(params["user_opened_browser"])
    |> maybe_update_browser_opened(params["browser_opened"])
  }
  end

  defp maybe_update_user_opened_browser(socket, nil), do: socket
  defp maybe_update_user_opened_browser(socket, user_opened_browser) do
    assign(socket, :user_opened_browser, user_opened_browser)
  end

  defp maybe_update_browser_opened(socket, nil), do: socket
  defp maybe_update_browser_opened(socket, browser_opened) do
    assign(socket, :browser_opened, browser_opened)
  end