Hey folks, I have the unique problem that I need to ignore all “change” and “input” events for one specific input element in a LiveView Form because these events are handled by a 3rd party JS library. That library (QuillJS) adds its own eventListener to the input field which creates a race condition with LiveView’s eventListener.
An example:
<.form for={@form} phx-change="validate">
# Changes to this input should send the "validate" event.
<.input form={@form[:name]} type="text" />
# Changes to this input should be ignored and not send the "validate" event.
<select contenteditable="false">
<option value="foo">Foo</option>
<option value="bar">Bar</option>
</select>
</.form>
I tried these solutions, but none of them worked:
Put phx-update="ignore" on the select input.
The phx-update flag only ignores changes coming from the server, not from the client to the server.
Put a custom phx-change="ignore" attribute on the select input.
This still sends an “ignore” event to the server which sends back an update which breaks my 3rd party library (quill editor calling highlight.js for syntax highlighting)
Put onchange and oninput attributes with an event.stopPropagation() or event.preventDefaults() call on the select input.
These don’t seem to have an effect. I guess because LiveView puts an form.on("change", fn) listener on the form.
Add a custom eventListener to the select-input which calls event.stopPropagation() or event.preventDefaults().
Had no effect. The “validate” event was still sent to the server.
Remove the `phx-change=“validate” from the form altogether.
That worked, but now I can’t validate the form before it’s submitted.
Ideally, LiveView would respect an phx-update="ignore" attribute and ignore any “change” and “input” events from that input, which means not sending a “validate” event back to the server.
That’s not quite the problem I’m facing. The problem is with the new “language” select of the code syntax highlighter. That one adds a select dropdown and listens for changes. However, these changes also propagate to LiveView which then validates the form and sends a response, all before Quill could update the code data-language attributes and re-highlight the code.
That’s not what phx-update is about though. phx-update defines the behaviour how changes (DOM updates) coming from the server are applied locally. That’s a completely separate thing to event listeners.
Sounds like LV should ignore input events from inputs without names. Their values won’t make it to the server anyways, because inputs without names don’t send data within a form.
That’d be solution indeed! I’m just concerned that this might lead to “bugs” where a field isn’t sent because somebody forgot the name attribute. I mean, it’s an error for sure, but maybe something explicit would be better? For example another attribute like:
<select phx-change-ignore={true}>
That’d be 100% explicit and a small change that only affects this specific use-case.
All LiveView events sit on window, so you should able to intercept any event and stopPropagation/stopImmediatePropagation to prevent it bubbling to LiveView. Sounds like your previous attempts at doing this weren’t wired up properly. Keep in mind the "input" event is what is typically triggered for standard inputs, while "change" is for selects, checkboxes, radios. That said some input types dispatch both events depending on the scenario, so you will likely need to handle both types. I don’t think LV needs any special feature here since it should be easy to prevent the bubbling up as we sit all the way at the top on window.