Scenario
• I have an interface where I want to toggle between list view and table view.
• I also want to keep track on whether the user is in list vs table view in a cookie/session
as a preference. This way when they come back I can load up the their default_view
The Setup
• From the Controller, I am able to set the initial default_view by using put_session(conn, :default_view, "list")
• From LiveView, I have a <button phx-click="toggle_view">
that fires def handle_event("toggle_view", _value, socket)
which then toggles between the values list_view
and table_view
and renders the correct template.
Where I’m stuck
From LiveView, I cannot figure out how to bubble up or delegate from the def handle_event("toggle_view", _value, socket) do
to my controller so that it can then update the session with the new default_view
.
Here is my current solution:
# Controller
defmodule LiveFooWeb.PageController do
use LiveFooWeb, :controller
def index(conn, _params) do
users = [1,2,3,4,5]
conn = put_session(conn, :default_view, "list") # This is the default setting
default_view = get_session(conn, :default_view)
render(conn, "index.html", users: users, default_view: default_view)
end
def show(conn, _params) do
users = [6,7,8,9,10]
default_view = get_session(conn, :default_view)
render(conn, "show.html", users: users, default_view: default_view)
end
end
Here is the tableview
defmodule LiveFooWeb.TableViewLive do
use Phoenix.LiveView
def render(assigns) do
case assigns.type_of_view do
"list" -> list_view(assigns)
"table" -> table_view(assigns)
end
end
def table_view(assigns) do
~L"""
<%= Phoenix.View.render(LiveFooWeb.ComponentsView, "table.html", users: assigns.users, type_of_view: assigns.type_of_view) %>
<button phx-click="toggle_view"><%= @btn_label %></button>
"""
end
def list_view(assigns) do
~L"""
<%= Phoenix.View.render(LiveFooWeb.ComponentsView, "list.html", users: assigns.users, type_of_view: assigns.type_of_view) %>
<button phx-click="toggle_view"><%= @btn_label %></button>
"""
end
def mount(_params, %{"users" => users, "type_of_view" => type}, socket) do
{:ok, assign(socket, users: users, type_of_view: type, btn_label: "change to table")}
end
def handle_event("toggle_view", _value, socket) do
case socket.assigns.type_of_view do
"list" ->
# Need to tell the controller to update the session with the new :default_view
# I know this won't work because no access to conn
# Plug.Conn.put_session(conn, :default_view, "table")
#
{:noreply, assign(socket, type_of_view: "table", btn_label: "change to list")}
"table" ->
# Need to tell the controller to update the session with the new :default_view
# I know this won't work because no access to conn
# Plug.Conn.put_session(conn, :default_view, "table")
#
{:noreply, assign(socket, type_of_view: "list", btn_label: "change to table")}
end
end
end
Research
I was searching the forum and I found this article. It sounds relatable but I don’t follow on how the solution works.