Skip to content

Commit 4e0c5a2

Browse files
committed
Add outerHTMLStrip and handle template tag encapsulation
1 parent c091b95 commit 4e0c5a2

3 files changed

Lines changed: 46 additions & 2 deletions

File tree

src/htmx.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1478,8 +1478,11 @@ var htmx = (function() {
14781478
fragment = getDocument().createDocumentFragment()
14791479
fragment.appendChild(oobElementClone)
14801480
if (!isInlineSwap(swapStyle, target)) {
1481-
fragment = asParentNode(oobElementClone) // if this is not an inline swap, we use the content of the node, not the node itself
1481+
// @ts-ignore if elt is template content will be valid so use as inner content
1482+
fragment = oobElementClone.content || asParentNode(oobElementClone) // if this is not an inline swap, we use the content of the node, not the node itself
14821483
}
1484+
// outerHTMLStrip swapStyle will strip wrapping tag above but do outerHTML swap of inner contents
1485+
swapStyle = swapStyle.replace('Strip', '')
14831486

14841487
const beforeSwapDetails = { shouldSwap: true, target, fragment }
14851488
if (!triggerEvent(target, 'htmx:oobBeforeSwap', beforeSwapDetails)) return

test/attributes/hx-swap-oob.js

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,17 @@ describe('hx-swap-oob attribute', function() {
128128
byId('d1').innerHTML.should.equal('Swapped5')
129129
})
130130

131+
it('handles outerHTMLStrip response properly', function() {
132+
this.server.respondWith('GET', '/test', "Clicked<div id='d1' hx-swap-oob='outerHTMLStrip'><div id='d2' foo='bar'>Swapped4.1</div></div>")
133+
var div = make('<div hx-get="/test">click me</div>')
134+
make('<div id="d1"></div>')
135+
div.click()
136+
this.server.respond()
137+
byId('d2').getAttribute('foo').should.equal('bar')
138+
div.innerHTML.should.equal('Clicked')
139+
byId('d2').innerHTML.should.equal('Swapped4.1')
140+
})
141+
131142
it('oob swaps can be nested in content with config {"allowNestedOobSwaps": true}', function() {
132143
htmx.config.allowNestedOobSwaps = true
133144
this.server.respondWith('GET', '/test', "<div>Clicked<div id='d1' foo='bar' hx-swap-oob='innerHTML'>Swapped6</div></div>")
@@ -387,4 +398,13 @@ describe('hx-swap-oob attribute', function() {
387398
element.innerHTML.should.equal('Swapped11')
388399
})
389400
})
401+
402+
it('handles using template as the encapsulating tag of an inner swap', function() {
403+
this.server.respondWith('GET', '/test', '<tbody id="foo" hx-swap-oob="innerHTML"><tr><td>Swapped12</td></tr></tbody>')
404+
var div = make('<div hx-get="/test">click me</div>')
405+
make('<table><tbody id="foo"></tbody></table>')
406+
div.click()
407+
this.server.respond()
408+
byId('foo').innerHTML.should.equal('<tr><td>Swapped12</td></tr>')
409+
})
390410
})

www/content/attributes/hx-swap-oob.md

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ The value of the `hx-swap-oob` can be:
3131

3232
If the value is `true` or `outerHTML` (which are equivalent) the element will be swapped inline.
3333

34-
If a swap value is given, that swap strategy will be used and the encapsulating tag pair will be stripped for all strategies other than `outerHTML`.
34+
If a swap value is given, that swap strategy will be used and the encapsulating tag pair will be stripped for all strategies other than `outerHTML`. There is also an additional swap value `outerHTMLStrip` that still strips the encapsulating tag but allows the replacment the whole target, like `outerHTML`, with all inner content nodes.
3535

3636
If a selector is given, all elements matched by that selector will be swapped. If not, the element with an ID matching the new content will be swapped.
3737

@@ -71,6 +71,27 @@ A `<p>` can be encapsulated in `<div>` or `<span>`:
7171
</span>
7272
```
7373

74+
You can also now use `template` tag as this should work for nearly any tag type:
75+
```html
76+
<template hx-swap-oob="beforeend:#table tbody">
77+
<tr>
78+
...
79+
</tr>
80+
</template>
81+
```
82+
83+
Another new option is the `outerHTMLStrip` swap style that allows you to replace an element with multiple nodes:
84+
```html
85+
<div id="foo" hx-swap-oob="outerHTMLStrip">
86+
<div id="foo2">
87+
Replace original
88+
</div>
89+
<div>
90+
And add something more
91+
</div>
92+
</div>
93+
```
94+
7495
### Troublesome Tables and lists
7596

7697
Note that you can use a `template` tag to encapsulate types of elements that, by the HTML spec, can't stand on their own in the

0 commit comments

Comments
 (0)