From 24804883cc87c83483f3ac77e8a4089f6b158de7 Mon Sep 17 00:00:00 2001 From: MichaelWest22 Date: Wed, 9 Jul 2025 00:47:36 +1200 Subject: [PATCH] Cancel button with inner content form submit properly --- src/htmx.js | 4 +++- test/core/regressions.js | 22 ++++++++++++++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/src/htmx.js b/src/htmx.js index 4c8203ef2..5026d60a7 100644 --- a/src/htmx.js +++ b/src/htmx.js @@ -2430,9 +2430,11 @@ var htmx = (function() { if (elt.tagName === 'FORM') { return true } + // find button wrapping the event elt + const btn = elt.closest('input[type="submit"], button') // @ts-ignore Do not cancel on buttons that 1) don't have a related form or 2) have a type attribute of 'reset'/'button'. // The properties will resolve to undefined for elements that don't define 'type' or 'form', which is fine - if (elt.form && elt.type === 'submit') { + if (btn && btn.form && btn.type === 'submit') { return true } elt = elt.closest('a') diff --git a/test/core/regressions.js b/test/core/regressions.js index 91a35a0ee..0765b3361 100644 --- a/test/core/regressions.js +++ b/test/core/regressions.js @@ -333,4 +333,26 @@ describe('Core htmx Regression Tests', function() { button.click() }) + + it('a htmx enabled button containing sub elements will prevent the button submitting a form', function(done) { + var defaultPrevented = 'unset' + var form = make('
') + var button = form.firstChild + var span = button.firstChild + + htmx.on(button, 'click', function(evt) { + // we need to wait so the state of the evt is finalized + setTimeout(() => { + defaultPrevented = evt.defaultPrevented + try { + defaultPrevented.should.equal(true) + done() + } catch (err) { + done(err) + } + }, 0) + }) + + span.click() + }) })