Skip to content

Only cancel the native action for the element's request trigger - #4188

Open
paulscan wants to merge 2 commits into
bigskysoftware:four-devfrom
paulscan:fix/hx-on-default-prevention
Open

paulscan wants to merge 2 commits into
bigskysoftware:four-devfrom
paulscan:fix/hx-on-default-prevention

Conversation

@paulscan

@paulscan paulscan commented Nov 2, 2026

Copy link
Copy Markdown

Description

In 4.0.1 an hx-on:submit on a plain form stops the form submitting, an hx-on:click on a plain link stops it navigating, and a cmd/ctrl/shift-click on <a href hx-get> is cancelled with no request sent (#4187). #4062 moved the #shouldCancel check to the first line of the guarded spec.handler in #onTrigger, which hx-on handlers also run through, and ahead of the modifier-key check in #handleTriggerEvent.

#initializeTriggers now passes a fourth argument to #onTrigger, request, and the first line becomes if (request && !this.#isModifierKeyClick(evt) && this.#shouldCancel(evt)) evt.preventDefault();. The check stays first, so a delayed request trigger still cancels the native submit synchronously (#4057), and out-of-scope from:/target: request triggers still cancel. hx-on prevents only through its prevent and halt modifiers, in the filtered form too. Extension triggers registered through api.onTrigger are treated like hx-on; hx-ws already prevents form submits itself.

Fixes #4187

Testing

  • The three modifier-click tests in cancel-behavior.js dispatched
    MouseEvents without cancelable: true. preventDefault() is a no-op on a non-cancelable event and defaultPrevented stays false, so the tests passed whether or not htmx cancelled the click. They now dispatch cancelable: true, as a real click is, and also assert that no request was sent, so a build that lets the browser open the tab but still fires the request fails too. On 4.0.1 they fail with expected true to equal false.
  • One new test in hx-on.js: hx-on:submit without prevent on a plain
    form does not prevent the native submit. It fails on 4.0.1.
  • npm test in Chromium: everything passes except the two scroll restoration on history traversal tests, which fail for me on four-dev without this change too. The suite was also run in WebKit and Firefox through Playwright.

Checklist

  • I have read the contribution guidelines
  • Targeted four-dev (htmx 4 source)
  • Bugfix for a 4.0.1 regression
  • Ran the test suite locally

Disclosure: an AI agent (Claude Code / Fable 5.1) found the regression during a run of my private browser test suite against 4.0.1 and suggested the fix. I accepted and audited the source change + the test, and ran the suite myself.

hx-on handlers no longer prevent a plain form's submit or a link's
navigation; a modifier-key click on an hx-get link opens the new tab.
Make the modifier-click tests dispatch cancelable events.
@paulscan
paulscan force-pushed the fix/hx-on-default-prevention branch from 43f5a5b to 7cc2789 Compare November 5, 2026 18:24
@paulscan

paulscan commented Nov 8, 2026 •

Copy link
Copy Markdown
Author

A side-by-side demo of this one, since it's blocking 4.0.1 for several of my projects:

https://codepen.io/editor/paulscan/pen/01a1b8a5-3bbc-7d52-ba86-520937a15f29?orientation=left&panel=files&show=preview

Left frame loads 4.0.0, right frame loads 4.0.1, same markup in both. Click Save and the docs link in each column, then cmd/ctrl/shift-click the hx-get link.

  • hx-on:submit on a plain form: ✅ 4.0.0 submits, ❌ 4.0.1 cancels the submit.
  • hx-on:click on a plain link: ✅ 4.0.0 navigates, ❌ 4.0.1 cancels the navigation.
  • cmd/ctrl/shift-click on <a href hx-get>: ✅ 4.0.0 opens a new tab, ❌ 4.0.1 cancels the click and sends no request.

None of these handlers use prevent, so per the hx-on docs they shouldn't cancel anything. This PR restores that code and keeps #4062's synchronous cancel for delayed request triggers.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant