How to handle debouncing different events on one element differently?

Hi there!

I have a LiveView that includes a type-ahead style search box with results. The markup is roughly this:

<form phx-change="search" phx-submit="search" phx-click-away={JS.hide(%JS{}, to: "#search-results"}>
  <input type="text" placeholder="Search..." value={@query} phx-focus={JS.show(%JS{}, to: "#search-results")} phx-debounce="200">

  <div id="search-results">
    <%= for result <- @results %>
      ...
    <% end %>
  </div>
</form>

The issue I’m running into is that phx-debounce on the search input also is applying to both the phx-blur event and the form’s phx-change. This makes it so there’s a 200 millisecond delay between clicking within the search bar and revealing results. I’m wondering how best to keep the 200 millisecond debouncing in place for input changes, but not for the focus event.

To get around this, I’ve wrapped the input in a div, and moved the phx-blur to a phx-click on the wrapping div, but I feel this isn’t quite ideal. In a previous project, I used alpine.js to hide and show the results, but with the addition of Phoenix.LiveView.JS commands, I was hoping to eliminate that need.

I tried looking through the Live View issues, and saw a few general references to this problem, but none specifically discussing debouncing different events. On one hand, I feel like it might be nice to specify which events are being debounced, but on the other, I think that might overly complicate things. Really just looking for everyone’s thoughts on a good way to handle this :smile:

Thank you for your time!

1 Like

Running into this atm. An added frustration is that phx-debounce also applies to phx-click/blur/etc even when they’re just emitting client-side JS commands which ends up being a very strange result since I don’t want to debounce stuff that’s not even touching the network.

4 Likes