Enhancing Client-Side Navigation in Phoenix Live View

Hey,
Earlier i posted a question, but after some research I think a proposal is due.

Working on a Phoenix Live View app, I needed client-side navigation from a select element without server trips. Initially, i tried phx-click on each option element but it was never triggered.

I was able to wrap the select element on a form, and using the phx-change it was able to send the change to the server, but for a simple navigation, I don’t feel a server trip is the right way to implement it.

I was able to make it work by creating a custom event, and rebuild the encodeJS and call execution on it.

JavaScript:

window.addEventListener("live_view_navigate", event => {
  const path = event.target.value;
  liveSocket.execJS(event.target, `[['patch', {"href": "${path}"}]]`);
});

HTML:

<select phx-change={JS.dispatch("live_view_navigate")}>
  <%= for option <- @options do %>
    <option value={option.path}><%= option.label %></option>
  <% end %>
</select>

This gets the job done but leans on JavaScript, which feels off in a LiveView context.

Proposal

Let’s simplify. How about a built-in Live View solution that receives a new option that points to the attribute in which the actual path is? Like this:

<select phx-change={JS.push(using: "value")}>
  <option value="1">First</option>
  <option value="2">Second</option>
</select>

Choosing the first option here would mimic JS.push(to: "1"). The implementation in phoenix_live_view.js could be somethig like:

exec_patch(eventType, phxEvent, view, sourceEl, el, { href, replace, using = null }) {
  let targetValue = using ? sourceEl.getAttribute(using) : href;
  view.liveSocket.pushHistoryPatch(targetValue, replace ? "replace" : "push", sourceEl);
}

This change aims to streamline client-side navigation without external JavaScript or server interactions. There are a few other changes to be done in the codebase, but I’d be happy to submit a PR.

What do you think?

I think it is a mistake to try and avoid writing JavaScript at all costs when we are developing web pages.

You would need a way for the developer to choose whether it is patch, navigate or href navigation.

How does using a select for navigation affect the the lives of assistive technology users?

It seemed a common navigation strategy not covered in Live View, and I view the interop with JS as door for more complex integration and not plain and simple navigation.

I see this change being applied to all navigation functions, so they all would be able to receive this new option.

As for the navigation via select, this is a fallback for small screens implemented on TailwindUI and although I understand there can be bad implementations of it, it seems very well possible to follow accessibility guidelines using it.

You’re right, people do use select for nav. Personally, I like to keep things simple and expected so generally use nav, li and a. Navigation menus should be pretty :slight_smile: