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-clickbinding containing aJS.push/2. -
JS.push/2simplifies 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!