Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion src/htmx.js
Original file line number Diff line number Diff line change
Expand Up @@ -1899,8 +1899,10 @@ var htmx = (function() {
*/
function findAndSwapOobElements(fragment, settleInfo, rootNode) {
var oobElts = findAll(fragment, '[hx-swap-oob], [data-hx-swap-oob]')
var hasOobSwaps = false
forEach(oobElts, function(oobElement) {
if (htmx.config.allowNestedOobSwaps || oobElement.parentElement === null) {
hasOobSwaps = true
const oobValue = getAttributeValue(oobElement, 'hx-swap-oob')
if (oobValue != null) {
oobSwap(oobValue, oobElement, settleInfo, rootNode)
Expand All @@ -1910,7 +1912,7 @@ var htmx = (function() {
oobElement.removeAttribute('data-hx-swap-oob')
}
})
return oobElts.length > 0
return hasOobSwaps
}

/**
Expand Down
16 changes: 16 additions & 0 deletions test/attributes/hx-swap-oob.js
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,22 @@ describe('hx-swap-oob attribute', function() {
should.equal(byId('d1').innerHTML, 'Foo')
})

for (const attribute of ['hx-swap-oob', 'data-hx-swap-oob']) {
it('keeps templates containing ignored nested oob swaps with ' + attribute, function() {
htmx.config.allowNestedOobSwaps = false
this.server.respondWith('GET', '/test', '<template id="kept"><div><span ' + attribute + '="innerHTML:#d1">Nested</span></div></template>')
var button = make('<button hx-get="/test">Click</button>')
var target = make('<div id="d1">Original</div>')
button.click()
this.server.respond()
target.innerHTML.should.equal('Original')
var template = button.querySelector('template')
should.not.equal(template, null)
template.content.querySelector('span').textContent.should.equal('Nested')
template.content.querySelector('span').hasAttribute(attribute).should.equal(false)
})
}

it('oob swap keeps templates not used for oob swap encapsulation', function() {
this.server.respondWith('GET', '/test', '' +
'Clicked<template></template>')
Expand Down
1 change: 1 addition & 0 deletions www/content/attributes/hx-swap-oob.md
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ By default, any element with `hx-swap-oob=` attribute anywhere in the response i
This can be problematic when using [template fragments](https://htmx.org/essays/template-fragments/) where a fragment may be reused as an oob-swap target and also as part of a bigger fragment. When the bigger fragment is the main response the inner fragment will still be processed as an oob swap, removing it from the dom.

This behavior can be changed by setting the config `htmx.config.allowNestedOobSwaps` to `false`. If this config option is `false`, OOB swaps are only processed when the element is *adjacent to* the main response element, OOB swaps elsewhere will be ignored and oob-swap-related attributes stripped.
Templates containing only ignored nested OOB elements are retained in the main response; they are not discarded as OOB encapsulation wrappers.

## Notes

Expand Down