I’ve been using chatGPT and looking for articles to explain this simply and everything is either wrong, outdated or too complicated for me to understand. In React I understand how to move state up/down and between sibling components. In Phoenix I do not.
I want to know the most generic way applicable to any app. I’ve read some forum posts but I think my example below is more generic and easier to apply elsewhere.
Below I have a parent live view named PageLive and two sibling components (Heading and Content). If I want to write code so that when a user clicks a Heading item it affects the Content, what is the thought process to make this happen? Maybe as a simple example, when a user clicks a Heading item the result is a string is appended to the “content”.
I understand how to set event handlers but I intentionally left that code out because in this case, whatever I write will probably be wrong.
EDIT
My example doesn’t work with state - I was focused on events as a precursor to moving state around. It was a bad example. Sorry
defmodule Heading do
use Phoenix.Component
def head(assigns) do
~H"""
<ul>
<%= for heading <- @headings do %>
<li><%= heading %>!</li>
<% end %>
</ul>
"""
end
end
defmodule Content do
use Phoenix.Component
def content(assigns) do
~H"""
<p>This is content: <%= @content %>!</p>
"""
end
end
defmodule AppWeb.PageLive do
use AppWeb, :live_view
import Heading
import Content
def mount(_params, _session, socket) do
{:ok, socket}
end
def headings do
["one","two","three"]
end
def content() do
"This is some great content here"
end
def render(assigns) do
~H"""
<Heading.head headings={headings()} />
<Content.content content ={content()} />
"""
end
end
EDIT
an AI gave me a working example and I’m playing with it now.
defmodule Heading do
use Phoenix.Component
def head(assigns) do
~H"""
<ul>
<%= for heading <- @headings do %>
<li phx-click="append_content" phx-value-heading={heading}><%= heading %>!</li>
<% end %>
</ul>
"""
end
end
defmodule Content do
use Phoenix.Component
def content(assigns) do
~H"""
<p>This is content: <%= @content %>!</p>
"""
end
end
defmodule AppWeb.PageLive do
use AppWeb, :live_view
import Heading
import Content
def mount(_params, _session, socket) do
{:ok, assign(socket, :content, "This is some great content here")}
end
def headings do
["one", "two", "three"]
end
def render(assigns) do
~H"""
<Heading.head headings={headings()} />
<Content.content content={@content} />
"""
end
def handle_event("append_content", %{"heading" => _heading}, socket) do
updated_content = socket.assigns.content <> " hello there"
{:noreply, assign(socket, :content, updated_content)}
end
end