Update Session inside liveview

Hello everybody, did someone know how to update session inside liveview?

Thanks! :smiley:

At least for the default cookie based session thatā€™s not possible. With server side session handling it may be possible.

You have to make a HTTP request to a controller to mutate the session cookie. It is possible to do without navigating away from your live view, but YMMV and youā€™ll have to decide if this works for your use case.

In my case, I want to update certain user settings in the session. It is possible to target a form submission to a hidden iframe, so you can submit a form through the iframe without reloading your page. Thereā€™s a little extra setup, but you can use this with live view.

I place the iframe at the bottom of my live layout:

<!-- This iframe provides a target for hidden form submissions and HTTP requests -->
<!-- that mutate the session state. -->
<iframe hidden name="hidden_iframe" src={Routes.iframe_path(@socket, :index)} height="0" width="0">
</iframe>

It needs a src so I have an /iframe route with a simple controller action that just returns html(conn, "ok"). Of course this means itā€™s making an extra HTTP request to your server every time you load a page that contains this iframe. Then create your form targeting the hidden_iframe

<.form
  let={f}
  for={:settings}
  action={Routes.settings_path(@socket, :update)}
  method="put"
  target="hidden_iframe"
>

In my case, my SettingsController does as little as possible, it validates the input with an embedded changeset, updates the session, and returns html(conn, "ok") or html(conn, "error: #{errors}")

1 Like

LV also supports phx-trigger-action to submit a form via http:

https://hexdocs.pm/phoenix_live_view/0.17.10/form-bindings.html#submitting-the-form-action-over-http

Once phx-trigger-action is true, LiveView disconnects and then submits the form.

My understanding is that by default it still navigates away from the LiveView?

Given the places needing to modify the session are usually rather rare I donā€™t think thatā€™s to bad. It can redirect back to a LV page.

Yeah, I agree that in most cases that is true and I would navigate away. Like, I would not log in a user with this method, though since it is using CSRF tokens in the form and put request, Iā€™m not sure it would be bad to do so?

In my particular case, I want to persist accessibility display settings and things like ā€œhard modeā€ in a game, and have the browser remember those settings when the player returns. There are no registered users or player data persisted in a db to store this state. Those settings are toggled on and off with a switch. So each toggle switch is a submit button to its own form, which sends the HTTP request to mutate the session without tearing down the UI.

For this case I found a solution that works, but it may not be the best for every use case.

If itā€™s for preferences (non personal data) a separate cookie (non http-only) could be used with push_event to customize from JS.

1 Like

Yes definitely. The settings are also used by the server in game logic, so with JS I think I would need hooks to send the settings from the client to the server on mount. The way Iā€™m doing it, I am performing changeset validations and storing the whole struct in the session. When one setting is changed the struct is pulled from the session, changed, validated and put back. Then the settings struct can be fetched in a plug on initial page load and checked that it is still valid according to the current version, or else replaced with a new one, and passed directly to the live view in live_render

LocalStorage is easier to use than a cookie from javascript. You can still perform changset validation with push_event

@derek-zhou @LostKobrakai thanks for your advice! I will look into the implementations of these suggestions. Are there reasons I should consider these as better options than the way Iā€™m doing it?