How to Create a Basic PubSub Application: Difference between revisions
From ElixirBlocks
No edit summary |
No edit summary |
||
| Line 102: | Line 102: | ||
end | end | ||
</source> | |||
<source> | |||
# lib/app/counter.ex | |||
defmodule Counter do | |||
use Agent | |||
def start_link(initial_value) do | |||
Agent.start_link(fn -> initial_value end, name: __MODULE__) | |||
end | |||
def value do | |||
Agent.get(__MODULE__, & &1) | |||
end | |||
def increment do | |||
Agent.update(__MODULE__, &(&1 + 1)) | |||
end | |||
end | |||
# lib/app_web/live/page_live.ex | |||
defmodule AppWeb.PageLive do | |||
use AppWeb, :live_view | |||
def mount(_params, _session, socket) do | |||
Phoenix.PubSub.subscribe(App.PubSub, "the-topic") | |||
# Get current value from the supervised Counter | |||
data = Counter.value() | |||
{:ok, assign(socket, data: data)} | |||
end | |||
def handle_event("increment", _params, socket) do | |||
Counter.increment() | |||
new_data = Counter.value() | |||
Phoenix.PubSub.broadcast(App.PubSub, "the-topic", new_data) | |||
{:noreply, assign(socket, data: new_data)} | |||
end | |||
def handle_info(new_data_from_broadcast, socket) do # usually set with pattern match like {:data,thedata} | |||
IO.inspect new_data_from_broadcast | |||
{:noreply, assign(socket, data: new_data_from_broadcast)} | |||
end | |||
def render(assigns) do | |||
~H""" | |||
<div> | |||
<.button phx-click="increment">click me </.button> | |||
<div>{@data}</div> | |||
</div> | |||
""" | |||
end | |||
end | |||
</source> | </source> | ||
Latest revision as of 18:31, 1 September 2025
This page is in progress
In LiveView
def mount(_params, _session, socket) do
Testbeds.subscribe()
{:ok, assign(socket, testbeds: Testbeds.list_testbeds())}
end
def handle_info({TestBeds, [:testbed | _], _}, socket) do
{:noreply, assign(socket, testbeds: TestBeds.list_testbeds())}
end
App/test_beds.ex
@topic inspect(__MODULE__)
def subscribe do
Phoenix.PubSub.subscribe(App.PubSub, @topic)
end
defp broadcast_change({:ok, result}, event) do
Phoenix.PubSub.broadcast(App.PubSub, @topic, {__MODULE__, event, result})
{:ok, result}
end
# ....
def create_testbed(attrs \\ %{}) do
%Testbed{}
|> Testbed.changeset(attrs)
|> Repo.insert()
|> broadcast_change([:testbed, :created])
end
Example Without Database
defmodule AppWeb.PageLive do
use AppWeb, :live_view
def mount(_params, _session, socket) do
if connected?(socket) do
AppWeb.Endpoint.subscribe(topic)
end
{:ok, assign(socket, username: username, messages: [])}
end
def handle_info(%{event: "message", payload: message}, socket) do
{:noreply, assign(socket, messages: socket.assigns.messages ++ [message])}
end
def handle_event("send", %{"text" => text}, socket) do
AppWeb.Endpoint.broadcast(topic, "message", %{text: text, name: socket.assigns.username})
{:noreply, socket}
end
defp username do
"User #{:rand.uniform(100)}"
end
defp topic do
"chat"
end
def render(assigns)do
~H"""
<div>
<h1>ChatLive</h1>
<div class="messages" style="border: 1px solid #eee; height: 400px; overflow: scroll; margin-bottom: 8px;">
<%= for m <- @messages do %>
<p style="margin: 2px;"><b><%= m.name %></b>: <%= m.text %></p>
<% end %>
</div>
<form phx-submit="send">
<input type="text" name="text" />
<button type="submit">Send</button>
</form>
</div>
"""
end
end
# lib/app/counter.ex
defmodule Counter do
use Agent
def start_link(initial_value) do
Agent.start_link(fn -> initial_value end, name: __MODULE__)
end
def value do
Agent.get(__MODULE__, & &1)
end
def increment do
Agent.update(__MODULE__, &(&1 + 1))
end
end
# lib/app_web/live/page_live.ex
defmodule AppWeb.PageLive do
use AppWeb, :live_view
def mount(_params, _session, socket) do
Phoenix.PubSub.subscribe(App.PubSub, "the-topic")
# Get current value from the supervised Counter
data = Counter.value()
{:ok, assign(socket, data: data)}
end
def handle_event("increment", _params, socket) do
Counter.increment()
new_data = Counter.value()
Phoenix.PubSub.broadcast(App.PubSub, "the-topic", new_data)
{:noreply, assign(socket, data: new_data)}
end
def handle_info(new_data_from_broadcast, socket) do # usually set with pattern match like {:data,thedata}
IO.inspect new_data_from_broadcast
{:noreply, assign(socket, data: new_data_from_broadcast)}
end
def render(assigns) do
~H"""
<div>
<.button phx-click="increment">click me </.button>
<div>{@data}</div>
</div>
"""
end
end