phx-change and phx-submit together: poor practice?

I’m maintaining a LiveView application and recently ran into this problem: A text input has a debounce on it, after which phx-change fires a “submit” event, so we get some quasi-real-time search results from our API. The issue is that people are used to hitting “Enter”, but that keydown is being caught by a different handler elsewhere in the app, and causing unintended behavior. I can overwrite it by adding phx-submit to the same form, so I have some code that looks like:

<.form
  # some attributes
  phx-change="submit"
  phx-submit="submit"
>

… But it felt icky. Is it icky?

It’s technically fine, but it’s a bizaare scenario. Submissions on change typically don’t need a submit, because there’s no point.

Is phx-target={@myself} included in your excluded form attributes?

If your form has the target set to itself, it shouldn’t be firing events outside of itself at all unless you have some kind of hook that triggers on the Enter key.

That being said, you can always just disable the Enter key when the form is focused using a JS hook. Below prevents the Enter key triggering submit and only allows submissions by a submit button.

      editableElement.addEventListener('keydown', (event) => {
        if (event.key === 'Enter') {
          event.preventDefault();

          const submitButton = document.querySelector('[data-messenger-submit]');
          if (submitButton) {
            submitButton.click();
          }
        }
      });

You could do similar by using JS to set a true/false flag whenever the input field is focused to disable the Enter key.

1 Like

I’ve been using phx-submit={%JS{}} to make phx-submit do nothing… but might also be regarded as a bit icky?

A hidden disabled button also doesn’t submit when you press enter.

<.button class="hidden" name="submit" value="disabled" disabled />

1 Like

Another option is to define an explicit “no-op” event.

<.form … phx-submit="noop">
  …


def handle_event("noop", _, socket), do: {:noreply, socket}