diff --git a/src/htmx.js b/src/htmx.js index 83caa151e..6fefab83a 100644 --- a/src/htmx.js +++ b/src/htmx.js @@ -1161,6 +1161,7 @@ var htmx = (() => { let targetSelector = this.__attr(templateElt, 'hx-target') || (templateElt.id ? '#' + CSS.escape(templateElt.id) : null); if (targetSelector) { this.__processScripts(templateElt.content); + tasks.push(...this.__processOOB(templateElt.content, ctx.sourceElement)); let swapSpec = this.__parseSwapSpec(this.__attr(templateElt, 'hx-swap') || this.config.defaultSwap); if (swapSpec.ignoreTitle) ctx.title = null; let targets = this.__findAllExt(ctx.sourceElement, targetSelector); diff --git a/test/tests/attributes/hx-swap-oob.js b/test/tests/attributes/hx-swap-oob.js index 9c7dd818b..dcbe158e1 100644 --- a/test/tests/attributes/hx-swap-oob.js +++ b/test/tests/attributes/hx-swap-oob.js @@ -24,6 +24,16 @@ describe('hx-swap-oob', function() { assertTextContentIs('#oob2', 'New Inner') }) + it('swaps an oob element out of an hx-partial', async function () { + mockResponse('GET', '/test', '

New content

New status
') + createProcessedHTML('
Old content
Old status
') + find('[hx-get]').click() + await forRequest() + assertTextContentIs('#content p', 'New content') + assertTextContentIs('#content + #status', 'New status') + assert.equal(playground().querySelectorAll('#status').length, 1) + }) + it('swaps oob element with custom selector', async function () { mockResponse('GET', '/test', '
Main
OOB Target
') createProcessedHTML('
Click
Original Target
'); diff --git a/www/src/content/reference/06-tags/01-hx-partial.md b/www/src/content/reference/06-tags/01-hx-partial.md index 33621d67b..cb0ecb32a 100644 --- a/www/src/content/reference/06-tags/01-hx-partial.md +++ b/www/src/content/reference/06-tags/01-hx-partial.md @@ -26,6 +26,8 @@ The `` tag lets you update multiple elements from a single response, Either `hx-target` or `id` is required. If both are present, `hx-target` takes precedence. +Elements marked with [`hx-swap-oob`](/reference/attributes/hx-swap-oob) inside an `` update their own targets. The remaining content goes to the partial's target. + ## Relative Targeting `hx-target` supports the full htmx extended selector vocabulary — `closest`, `next`, `previous`, `find`, `findAll` — resolved relative to the element that triggered the request. This lets the server express structural intent without requiring stable IDs: