htmx icon indicating copy to clipboard operation
htmx copied to clipboard

oob-swap losing root element

Open graemetait opened this issue 2 years ago • 6 comments
trafficstars

Discussed in https://github.com/bigskysoftware/htmx/discussions/1997

Originally posted by graemetait November 13, 2023 I think I'm misunderstanding something about how oob-swap works. I would expect the following example to insert the <li> to the end of the <ul>, but the surrounding <li> tag is always removed, inserting just the content.

https://codepen.io/graemetait/pen/gOqxMMK?editors=1010

It's also very similar to solution 2 in this example. https://htmx.org/examples/update-other-content/

What am I doing wrong?

graemetait avatar Nov 14 '23 19:11 graemetait

Btw, see this JSFiddle, with the doc's own example that doesn't work as expected, making me think it's a bug rather than a documentation issue there: The tds are added to the tbody directly, and as the OP reports, ignoring the root element (here, a tr), leading to an invalid HTML ; tbody should only contain tr elements

Permitted content | Zero or more tr elements

Telroshan avatar Nov 16 '23 14:11 Telroshan

@graemetait, since you want to swap the entire <li> element, you need to wrap it in a container. The 'swap' option 'beforeend' uses the inner HTML of the element it's specified on, and therefore, it only swaps the innerHTML of the <li>.

Changing the response body to the following will fix your issue.

<div hx-swap-oob="beforeend:#list">
  <li>next item</li>
</div>

xhaggi avatar Nov 17 '23 09:11 xhaggi

Thanks for the response, @xhaggi. Wrapping it in an element certainly works, but is that the intent with this feature? The example in the docs for beforeend doesn't add a container element, but actually the example doesn't work correctly if you run it.

The docs only say the following.

beforeend - Insert the response after the last child of the target element

Are we saying that the reality is...

beforeend - Insert the inner html of the response after the last child of the target element

graemetait avatar Nov 17 '23 09:11 graemetait

Expanding upon that, the docs do reference that the options are based upon Element.insertAdjacentHTML. If you were to use beforeend with insertAdjacentHTML it wouldn't be using innerHTML and you wouldn't need a container element.

It would be good to get some direction from the owner of this feature if there is one.

graemetait avatar Nov 17 '23 10:11 graemetait

Can anyone shed some light on why this works with a

    to add
  • items but fails completely with a table when trying to add to a table? It will append the "row" but completely strip out all and tags making it useless. If it uses Element.insertAdjacentHTML then it should work since plain JS can be used to add rows to a table that way.

Beartech avatar Dec 27 '23 23:12 Beartech

@Beartech I had to wrestle with this for a while. The answer is similar to @xhaggi 's, except instead of wrapping your <tr> with a <div>, wrap it with a <tbody> instead.

https://github.com/bigskysoftware/htmx/issues/1198#issuecomment-2100852239

parkerbedlan avatar May 26 '24 07:05 parkerbedlan