phoenixframework / phoenix_live_view

Rich, real-time user experiences with server-rendered HTML
https://hex.pm/packages/phoenix_live_view
MIT License
6.22k stars 933 forks source link

put/get session data in handle_event #501

Closed brachialix closed 4 years ago

brachialix commented 4 years ago

Hi, I am currently trying find a solution to the following problem:

The problem: I want to persist the selected item so that it is still selected after a reload. My approach would be to store the item ID in the session and retrieve it on the next mount. However i cannot find any possibility to use put_session() in handle_event().

Does anyone have any suggestions? Thanks in advance! :)

jamilabreu commented 4 years ago

@brachialix One option is to update the params on that page using live_link or live_redirect - essentially storing the selected items in the URL.

You can then use handle_params - pattern matching on the params, and re-assigning values to the LiveView session on reload

speeddragon commented 4 years ago

You can use put_flash/3, and them use a custom Plug to store in the session.

brachialix commented 4 years ago

@speeddragon Thx, but that sounds like a big ugly hack to me, i would rather not misuse flash for that.

brachialix commented 4 years ago

@jamilabreu Thx, i will try that, however a build in liveview solution would be great for such a feature. keeping fingers crossed ;)

brachialix commented 4 years ago

You can then use handle_params - pattern matching on the params, and re-assigning values to the LiveView session on reload

@jamilabreu how is that supposed to work? when using live_redirect, i have no way to access the session in handle_paramseither. on reload the mount function does not get the params parsed by handle_params, so no luck there as well to alter the session.

am i missing something?

jamilabreu commented 4 years ago

@brachialix You'll need to pass the current session state as params in the live_redirect call.

For example: if you have an element that has the phx-value-* attribute:

<div phx-click="select_option" phx-value-option1="true">select option 1</div>

You can pass it into live_redirect like this:

def handle_event("select_option", %{"option1" => "true"}, socket) do
{:noreply,
     live_redirect(socket,
       to: Routes.live_path(socket, ExampleWeb.CurrentLiveView, %{option1: true})
     )}
end

Then pattern match in handle_params like this:

  def handle_params(%{"option1" => option1}, _uri, socket) do
    {:noreply, assign(socket, :option1, option1}
  end

Hope that helps!

FYI - right now the best place ask questions like this (Github is generally more for bug reports) would be the Slack community: http://elixir-lang.slack.com/

brachialix commented 4 years ago

@jamilabreu

thx for the help and the slack info, will do next time. :)

however, maybe i had not explained my problem enough, your solution does not solve my problem fully, because when the user hits reload in the browser, the assigns are gone (but the params are saved in the URL - that part of your solution is correct, but that does not help when the user e.g. goes and comes back again with the same session).

what i want to do is do store the params with Plug.Conn.put_session, that however seems to be impossible when using live view. :(

jamilabreu commented 4 years ago

@brachialix If needed, you can create a plug that pattern matches on the params:

defmodule AppWeb.Plugs.LiveView do
  import Plug.Conn

  def init(opts), do: opts

  def call(%Plug.Conn{params: %{"option1" => option1}} = conn, _opts) do
      put_session(conn, :option1, option1)
 end

  def call(conn, _opts), do: delete_session(conn, :option1)
end

with plug AppWeb.Plugs.LiveView in your router :browser pipeline

brachialix commented 4 years ago

@jamilabreu yes i had the same idea, but the plug is not called by phx-click, so this does not work either.

chrismccord commented 4 years ago

You cannot put session data via web sockets, but you can persist the user's selections elsewhere, say the DB, then read them back on next visit.

brachialix commented 4 years ago

thx for the suggestion.