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?