Tutorial
View on GithubImproving LiveView UX with Phoenix Channels - Tagging part 3
This post was updated 01 May - 2020
In the previous tutorial I set up the tagging interface. It had however a small issue. If I added a tag, it didnt really refocus on the input so I needed to manually set the mouse there again.
In this tutorial, I will show how I can broadcast a message using Phoenix Channels to be handled by channels javascript and then simply set focus using javascript.
This tutorial also builds upon this turorial where I set up an AppChannel
that uses a channel name that is concatinated like:
"app:#{csrf_token}"
And to pass in the csrf_token
into the session so I can use it in all LiveView components is covered in this tutorial
STEP 1 - LiveView component changes
I basically need to do 3 changes here.
-
In the mount function, extract
csrf_token
from session and add a channel_name to assigns -
Add a
refocus_input/1
function where I actually to the broadcast from -
Call
refocus_input/1
when a tag is added
Start in the mount function. Note that the csrf_token
comes from a plug that I set up in a previous tutorial.
def mount(%{"id" => product_id, "csrf_token" => csrf_token} = _session, socket) do
product = get_product(product_id, connected?(socket))
assigns = [
...
# CHANNEL NAME
channel_name: "app:#{csrf_token}",
...
]
{:ok, assign(socket, assigns)}
end
Next step is to add the function where I do the actual broadcast from. Note that I specify the id of the input field. And the event name is "focus"
. So in theory, I could use the same JS for different focus events that should focus on different dom elements.
defp refocus_input(socket) do
TutorialWeb.Endpoint.broadcast_from(
self(),
socket.assigns.channel_name,
"focus",
%{id: "tagging-form"}
)
socket
end
Last part there is to add refocus_input(socket)
def handle_event("pick", %{"name" => search_phrase}, socket) do
product = socket.assigns.product
taggings = add_tagging_to_product(product, search_phrase)
refocus_input(socket)
...
end
STEP 2 - Frontend changes
I basically just need to do 2 things.
- Add an id to the input field
- Add a channel callback in JS
So open the template and add id="tagging-form"
inside the input.
# lib/tutorial_web/templates/product/product_tagging.html.leex
<%= form_tag "#", [phx_change: :search, phx_submit: :submit] do %>
...
<input
type="text"
id="tagging-form"
class="inline-block text-sm focus:outline-none"
name="search_phrase"
value="<%= @search_phrase %>"
phx-debounce="500"
placeholder="Add tag"
>
...
<% end %>
And open the socket.js
and add
// assets/js/socket.js
channel.on("focus", msg => {
const elm = document.getElementById(msg['id'])
elm.focus()
elm.value = ''
})
Final result
Tag Cloud
Phoenix Bolerplate
Generate a Phoenix Boilerplate and save hours on your next project.
SAAS Starter Kit
Get started and save time and resources by using the SAAS Starter Kit built with Phoenix and LiveView.
Subscribe for $39/mo to geat ahead!
Learn MoreRelated Tutorials
Published 13 Feb - 2020 - Updated 01 May - 2020
Tagging interface with Phoenix LiveView and Tailwind - Tagging part 2
In the previous tutorial, I set up the the backend for being able to add tags to products. I have also written a tutorial about adding a LiveView an..