Tutorial
Set session values from LiveView
Set session values from LiveView
This tutorial will guide you through the process of setting session values directly from Phoenix LiveView. Despite LiveView’s real-time capabilities, modifying session data traditionally poses a challenge due to its WebSocket-based communication. We’ll solve this by integrating a bit of JavaScript and a custom Phoenix controller, ensuring seamless session updates without compromising your app’s responsiveness.
Setting Up the StoreSession Controller
The StoreSessionController plays a critical role in this solution. It allows us to receive and update session data on the server side. Below is how you can set up this controller within your Phoenix application.
defmodule TutorialWeb.StoreSessionController do
use TutorialWeb, :controller
# Note, you must have defined the atom before.
def create(conn, params) do
updated_conn = Enum.reduce(params, conn, fn {key, value}, acc_conn ->
put_session(acc_conn, String.to_existing_atom(key), value)
end)
send_resp(updated_conn, 200, "")
end
end
Note that for security reasons, we use String.to_existing_atom(key)
. We do that for security reasons, so this means that the atom needs to have been defined before.
Adding the StoreSession Hook to app.html.heex
To integrate our session storage mechanism, we must mount a custom hook in our app’s layout. This hook will make use of LiveView’s powerful client-side capabilities. Let’s see how this is done in the app.html.heex file.
<div id="store-session" phx-hook="StoreSession"></div>
This will make sure that the javascript hook is available on every page view.
Configuring a Route for Session Storage
For our StoreSessionController to work, it needs an endpoint to receive session data. This is done by adding a specific route within our Phoenix router, allowing the controller to handle requests correctly.
scope "/", TutorialWeb do
pipe_through :browser
post "/store-session", StoreSessionController, :create
end
Implementing the JavaScript Hook
The JavaScript hook is the glue that bridges the LiveView and the controller and is responsible in updating session values from the client side. It will listen for events triggered by LiveView and make HTTP POST requests to store session data. Here’s how to implement this hook.
export const StoreSession = {
mounted() {
const token = document.querySelector('meta[name="csrf-token"]').getAttribute('content')
this.handleEvent('store-session', data => {
fetch('/store-session', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRF-Token': token
},
body: JSON.stringify(data)
})
})
}
}
Note that for security reasons, we are required to pass the CSRF-token that, in theory, should ensure that the requests comes from your own site.
LiveView Event Trigger Example
The final piece of the puzzle is triggering the session update from LiveView. By emitting a custom event, we can communicate with our JavaScript hook to initiate the session storage process. Here’s an example of how this is accomplished in LiveView.
{
:noreply,
socket
|> push_event("store-session", %{my_key: "My Value"})
}
Integrating the Components
To make everything work together smoothly, all pieces of the puzzle—LiveView, the custom Phoenix controller, JavaScript hook, and our frontend assets—need to be wired up appropriately. This includes adjusting your project’s asset pipeline to ensure the JavaScript hook is loaded and functional. Ensure the store_session.js
is imported and initialized in your app.js
or equivalent entry point for your JavaScript assets.
Conclusion
By following this guide, you’ve learned how to overcome one of the limitations of Phoenix LiveView regarding session management. Integrating JavaScript with LiveView allows for dynamic session updates, enhancing the user experience without full page reloads. This solution showcases the flexibility of Phoenix and the power of combining Elixir with JavaScript to solve complex web development challenges. Happy coding!