Skip to content

Commit

Permalink
Attach hx-on handlers before processing node
Browse files Browse the repository at this point in the history
  • Loading branch information
rkilpadi committed Jan 16, 2025
1 parent 9fcb5c5 commit 324bfd6
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 35 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

* Using `<button hx-verb="/endpoint" type="reset">` will now reset the associated form (after submitting to `/endpoint`)
* Using `<button formmethod="dialog">` will no longer submit its associated form
* Fixed a bug that prevented `hx-on*` from firing when triggered immediately by `load` or `revealed`

## [2.0.4] - 2024-12-13

Expand Down
77 changes: 42 additions & 35 deletions src/htmx.js
Original file line number Diff line number Diff line change
Expand Up @@ -2902,44 +2902,32 @@ var htmx = (function() {
* @param {Element|HTMLInputElement} elt
*/
function initNode(elt) {
if (closest(elt, htmx.config.disableSelector)) {
cleanUpElement(elt)
return
}
triggerEvent(elt, 'htmx:beforeProcessNode')

const nodeData = getInternalData(elt)
const attrHash = attributeHash(elt)
if (nodeData.initHash !== attrHash) {
// clean up any previously processed info
deInitNode(elt)

nodeData.initHash = attrHash

triggerEvent(elt, 'htmx:beforeProcessNode')

const triggerSpecs = getTriggerSpecs(elt)
const hasExplicitHttpAction = processVerbs(elt, nodeData, triggerSpecs)

if (!hasExplicitHttpAction) {
if (getClosestAttributeValue(elt, 'hx-boost') === 'true') {
boostElement(elt, nodeData, triggerSpecs)
} else if (hasAttribute(elt, 'hx-trigger')) {
triggerSpecs.forEach(function(triggerSpec) {
// For "naked" triggers, don't do anything at all
addTriggerHandler(elt, triggerSpec, nodeData, function() {
})
})
}
}
const triggerSpecs = getTriggerSpecs(elt)
const hasExplicitHttpAction = processVerbs(elt, nodeData, triggerSpecs)

// Handle submit buttons/inputs that have the form attribute set
// see https://developer.mozilla.org/docs/Web/HTML/Element/button
if (elt.tagName === 'FORM' || (getRawAttribute(elt, 'type') === 'submit' && hasAttribute(elt, 'form'))) {
initButtonTracking(elt)
if (!hasExplicitHttpAction) {
if (getClosestAttributeValue(elt, 'hx-boost') === 'true') {
boostElement(elt, nodeData, triggerSpecs)
} else if (hasAttribute(elt, 'hx-trigger')) {
triggerSpecs.forEach(function(triggerSpec) {
// For "naked" triggers, don't do anything at all
addTriggerHandler(elt, triggerSpec, nodeData, function() {
})
})
}
}

nodeData.firstInitCompleted = true
triggerEvent(elt, 'htmx:afterProcessNode')
// Handle submit buttons/inputs that have the form attribute set
// see https://developer.mozilla.org/docs/Web/HTML/Element/button
if (elt.tagName === 'FORM' || (getRawAttribute(elt, 'type') === 'submit' && hasAttribute(elt, 'form'))) {
initButtonTracking(elt)
}

nodeData.firstInitCompleted = true
triggerEvent(elt, 'htmx:afterProcessNode')
}

/**
Expand All @@ -2955,9 +2943,28 @@ var htmx = (function() {
cleanUpElement(elt)
return
}
initNode(elt)
forEach(findElementsToProcess(elt), function(child) { initNode(child) })

const elementsToInit = []

function maybeDeInit(e) {
if (closest(e, htmx.config.disableSelector)) {
cleanUpElement(e)
return
}
const nodeData = getInternalData(e)
const hash = attributeHash(e)
if (nodeData.initHash !== hash) {
deInitNode(e)
nodeData.initHash = hash
elementsToInit.push(e)
}
}

maybeDeInit(elt)
forEach(findElementsToProcess(elt), maybeDeInit)

forEach(findHxOnWildcardElements(elt), processHxOnWildcard)
forEach(elementsToInit, initNode)
}

//= ===================================================================
Expand Down
14 changes: 14 additions & 0 deletions test/attributes/hx-on-wildcard.js
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,20 @@ describe('hx-on:* attribute', function() {
delete window.foo
})

it('should fire when triggered by load', function() {
this.server.respondWith('POST', '/test', 'test')
make("<div hx-trigger='load' hx-post='/test' hx-on:htmx:config-request='foo = true'></div>")
window.foo.should.equal(true)
delete window.foo
})

it('should fire when triggered by revealed', function() {
this.server.respondWith('POST', '/test', 'test')
make("<div hx-trigger='revealed' hx-post='/test' hx-on:htmx:config-request='foo = true'></div>")
window.foo.should.equal(true)
delete window.foo
})

it('de-initializes hx-on-* content properly', function() {
window.tempCount = 0
this.server.respondWith('POST', '/test', function(xhr) {
Expand Down

0 comments on commit 324bfd6

Please sign in to comment.