Open gone opened 1 year ago
I noticed the same thing. the docs say that you can do something like
<table>
<tbody id="contacts-table">
...
</tbody>
</table>
And in the POST response
<tr hx-swap-oob="beforeend:#contacts-table">
<td>Joe Smith</td>
<td>joe@smith.com</td>
</tr>
But what you end up getting is
<tbody id="contacts-table">
<td>Jo Smith</td>
<td>joe@smith.com</td>
</tbody>
with no<tr>
tags at all. So any additional requests just add columns to the table on a single row. The correct (or at least currently functional) way to do it is to add the hx-swap-oob
on the outer element. Like this:
<tbody hx-swap-oob="beforeend:#contacts-table">
<tr>
<td>Joe Smith</td>
<td>joe@smith.com</td>
</tr>
</tbody>
This seems to happen whenever the additional content is wrapped in a <tr>
or <td>
(maybe others too but these two definitely don't work, whereas additional content in a <div>
or <p>
do work).
For example:
<div id="outofbounds">
Some out of bounds content.
</div>
<table>
<tr>
<td>
<div>
A table row to swap out.
</div>
</td>
<td>
<button hx-get="url" hx-target="closest tr">Swap Row</button>
</td>
</tr>
</table>
and responding to the htmx get with:
<tr>
<td>
<div>
Table row was swapped out.
</div>
</td>
<td>
<button hx-get="url" hx-target="closest tr">Swap Row</button>
</td>
</tr>
<div id="outofbounds" hx-swap-oob="true">Out of bounds content swapped</div>
does not work as the tags are getting stripped. The outofbounds swap on its own in the response works and the table row swap on its own also works, but not together.
Have you experimented with the htmx.config.useTemplateFragments
configuration setting?
HTMX works by taking the text http response, turning it into a brand new document, then inspecting it to pull nodes out of the new DOM to place them into the actual DOM of the page. But this strategy doesn't work very well for tables, since tables have a bunch of special rules around when table-related node types are allowed and valid. The useTemplateFragments
changes the strategy to wrap the http response in <template></template>
tags, which has looser rules about table-related nodes.
I believe some people having trouble with table nodes found this setting to be helpful.
See:
function parseHTML()
: https://github.com/bigskysoftware/htmx/blob/master/src/htmx.js#L250function makeFragment()
: https://github.com/bigskysoftware/htmx/blob/master/src/htmx.js#L273Hi @infogulch
I've just tried this and it didn't fix the problem unfortunately. Inserting a row in a table is working fine for me, it's just when out of bounds content is included in the response that the problem occurs. I'd guess that the htmx code that is pulling out the out of bounds part of the response is mangling the other content wrapped in <tr>
tags.
I've just tried this and it didn't fix the problem unfortunately. Inserting a row in a table is working fine for me, it's just when out of bounds content is included in the response that the problem occurs. I'd guess that the htmx code that is pulling out the out of bounds part of the response is mangling the other content wrapped in
<tr>
tags.
I just encountered the same problem. I have a server response containing the regular content (in my case a tbody
) plus an out-of-bounds element (a section
). As a workaround I solved it by wrapping an additional <table>
around the <tbody>
and added hx-select="tbody"
to the triggering element.
Ok, I got around to do some debugging. It seems that even when using template fragments the DOMParser
can't handle some combinations of elements that normally can't be siblings, which can happen when using oob swaps. I only tested with Firefox, but I wouldn't be surprised if it is different from browser to browser.
hx-select
(and possibly hx-select-oob
- I haven't checked that out properly yet) can be used as workaround in some cases, but in cases where HX-Retarget
is used this would require implementation of HX-Reselect
(and maybe HX-Reselect-oob
).
Another thing that could be a solution, could be to supported hx-oob-swap
on non-top-level elements.
However in my opinion, a better solution could be to implement a separator between the elements, for example in form of an HTML comment such as <!--oob-->
, which would allow splitting the fragments before passing them separately to the DOMParser
.
This may be resolved with the release of 2.0 which includes a new config option: set the htmx.config.allowNestedOobSwaps
config option to false
, and template fragments with the hx-swap-oob
attribute will no longer be swallowed.
See also the docs: https://htmx.org/attributes/hx-swap-oob/#nested-oob-swaps
The issue and PR that raises and implements the feature: #1133 #1235
Have a repro at https://github.com/gone/oobtest/commit/8e6c2f31bb90f2b21dcc4759eb8f8eff764621cd
the html
<li hx-swap-oob="beforeend:#messages"><div>message</message></li>
once swapped in only results in<div>message</div>
with the li removed