Events
JS.push/1
Read time: 5 minutes
In the previous lesson we learned how to use the phx-value-*
binding to pass values into an event. To recap:
Mix.install([
{:liveview_playground, "~> 0.1.1"}
])
defmodule PageLive do
use LiveviewPlaygroundWeb, :live_view
def mount(_params, _session, socket) do
socket = assign(socket, temperature_celsius: 30)
{:ok, socket}
end
def render(assigns) do
~H"""
<div>
Current temperature: <%= @temperature_celsius %>C
</div>
<div>
<%= cond do %>
<% @temperature_celsius > 40 -> %>
<p>🔥 Impossible to live 🔥</p>
<% @temperature_celsius > 30 -> %>
<p>Its hot</p>
<% @temperature_celsius > 20 -> %>
<p>Kinda cool</p>
<% @temperature_celsius > 10 -> %>
<p>Chill</p>
<% @temperature_celsius > 0 -> %>
<p>Chill</p>
<% true -> %>
<p>❄️⛄️</p>
<% end %>
</div>
<input type="button" value="+5" phx-click="add" phx-value-amount={+5} />
<input type="button" value="+10" phx-click="add" phx-value-amount={+10} />
<input type="button" value="-5" phx-click="add" phx-value-amount={-5} />
<input type="button" value="-10" phx-click="add" phx-value-amount={-10} />
"""
end
def handle_event("add", %{"amount" => amount}, socket) do
amount = String.to_integer(amount)
socket = assign(socket, temperature_celsius: socket.assigns.temperature_celsius + amount)
{:noreply, socket}
end
end
LiveviewPlayground.start()
However, we talked about how values will be sent strictly as a strings. LiveView also has an alternative way to push events called JS.push/2
which is part of the so-called JS Commands. Write and run the js_push.exs
file:
Mix.install([
{:liveview_playground, "~> 0.1.1"}
])
defmodule PageLive do
use LiveviewPlaygroundWeb, :live_view
def mount(_params, _session, socket) do
socket = assign(socket, temperature_celsius: 30)
{:ok, socket}
end
def render(assigns) do
~H"""
<div>
Current temperature: <%= @temperature_celsius %>C
</div>
<div>
<%= cond do %>
<% @temperature_celsius > 40 -> %>
<p>🔥 Impossible to live 🔥</p>
<% @temperature_celsius > 30 -> %>
<p>Its hot</p>
<% @temperature_celsius > 20 -> %>
<p>Kinda cool</p>
<% @temperature_celsius > 10 -> %>
<p>Chill</p>
<% @temperature_celsius > 0 -> %>
<p>Chill</p>
<% true -> %>
<p>❄️⛄️</p>
<% end %>
</div>
<input type="button" value="+5" phx-click={JS.push("add", value: %{amount: +5})} />
<input type="button" value="+10" phx-click={JS.push("add", value: %{amount: +10})} />
<input type="button" value="-5" phx-click={JS.push("add", value: %{amount: -5})} />
<input type="button" value="-10" phx-click={JS.push("add", value: %{amount: -10})} />
"""
end
def handle_event("add", %{"amount" => amount}, socket) do
socket = assign(socket, temperature_celsius: socket.assigns.temperature_celsius + amount)
{:noreply, socket}
end
end
LiveviewPlayground.start()
We simplified our LiveView by using JS.push/2
directly in the phx-click
binding and defining that we are pushing the "add"
event and the value will be %{amount: INTEGER}
. This phx-click
will be serialized as JSON so that when the button is clicked the amount
will be an integer as expected.
#Extra tip: using loops to prevent duplicated code
We could avoid some code duplication by using a simple :for
:
Mix.install([
{:liveview_playground, "~> 0.1.1"}
])
defmodule PageLive do
use LiveviewPlaygroundWeb, :live_view
def mount(_params, _session, socket) do
socket = assign(socket, temperature_celsius: 30)
{:ok, socket}
end
def render(assigns) do
~H"""
<div>
Current temperature: <%= @temperature_celsius %>C
</div>
<div>
<%= cond do %>
<% @temperature_celsius > 40 -> %>
<p>🔥 Impossible to live 🔥</p>
<% @temperature_celsius > 30 -> %>
<p>Its hot</p>
<% @temperature_celsius > 20 -> %>
<p>Kinda cool</p>
<% @temperature_celsius > 10 -> %>
<p>Chill</p>
<% @temperature_celsius > 0 -> %>
<p>Chill</p>
<% true -> %>
<p>❄️⛄️</p>
<% end %>
</div>
<input :for={value <- [5, 10, -5, -10]} type="button" value={"Add #{value}"} phx-click={JS.push("add", value: %{amount: value})} />
"""
end
def handle_event("add", %{"amount" => amount}, socket) do
socket = assign(socket, temperature_celsius: socket.assigns.temperature_celsius + amount)
{:noreply, socket}
end
end
LiveviewPlayground.start()
This tip also works for the previous class with phx-value-amount
. Take it as a home assignment to try out how to do this with the previous lesson code.
#Recap!
-
Using JS Commands we can switch from a combo of
phx-click
+phx-value-*
bindings for just onephx-click
binding containing aJS.push/2
. -
JS.push/2
simplifies the serialization of data that is not strings in values because integers are part of what JSON supports so the pushed data will be an integer as expected.
Feedback
Got any feedback about this page? Let us know!