bigskysoftware / htmx

</> htmx - high power tools for HTML
https://htmx.org
Other
36.78k stars 1.24k forks source link

multi-swap extension cannot find element #2279

Open felzix opened 6 months ago

felzix commented 6 months ago

Error

multi-swap.js:37 HTMX multi-swap: selector '#world' not found in source content.

Code

<!DOCTYPE html>
<html lang="en">
  <head>
    <script src="https://unpkg.com/htmx.org"></script>
    <script src="https://unpkg.com/htmx.org/dist/ext/multi-swap.js"></script>
  </head>
  <body hx-ext="multi-swap">
    <button hx-get="/api/world" hx-swap="multi:#world">press me</button>
    <div id="world"></div>
  </body>
</html>

Affects the two browsers I tried, Chrome and Brave: Chrome:Version 120.0.6099.224 (Official Build) (64-bit) Brave: Version 1.61.120 Chromium: 120.0.6099.234 (Official Build) (64-bit)

santoclemenzi commented 5 months ago

Same for me, any news about this?

Prouk commented 5 months ago

temporary fix for me was to modify the js as following : `(function () {

/** @type {import("../htmx").HtmxInternalApi} */
var api;

htmx.defineExtension('multi-swap', {
    init: function (apiRef) {
        api = apiRef;
    },
    isInlineSwap: function (swapStyle) {
        return swapStyle.indexOf('multi:') === 0;
    },
    handleSwap: function (swapStyle, target, fragment, settleInfo) {
        if (swapStyle.indexOf('multi:') === 0) {
            var selectorToSwapStyle = {};
            var elements = swapStyle.replace(/^multi\s*:\s*/, '').split(/\s*,\s*/);

            elements.map(function (element) {
                var split = element.split(/\s*:\s*/);
                var elementSelector = split[0];
                var elementSwapStyle = typeof (split[1]) !== "undefined" ? split[1] : "innerHTML";

                if (elementSelector.charAt(0) !== '#') {
                    console.error("HTMX multi-swap: unsupported selector '" + elementSelector + "'. Only ID selectors starting with '#' are supported.");
                    return;
                }

                selectorToSwapStyle[elementSelector] = elementSwapStyle;
            });

            for (var selector in selectorToSwapStyle) {
                try {
                    let el = document.getElementById(selector.slice(1, selector.length))
                    switch (selectorToSwapStyle[selector]) {
                        case 'innerHTML':
                            el.innerHTML = fragment.innerHTML;
                            break;
                        case 'outerHTML':
                            el.outerHTML = fragment.innerHTML;
                            break;
                        case 'afterbegin':
                            el.innerHTML = fragment.innerHTML + el.innerHTML;
                            break
                        case 'beforeend':
                            el.innerHTML += fragment.innerHTML;
                            break
                       // Add your case and replacement logic here
                    }
                } catch (err) {
                    console.warn(err)
                }
            }

            return true;
        }
    }
});

})();`

This is far from optimal or even the correct way to use the lib, but I it needed to work

minhquana3 commented 4 months ago

It is working fine for me. I ran into this issue before. I fixed it by returning HTML contains the same id. Hence, the return of <button hx-get="/api/world" hx-swap="multi:#world:outerHTML">press me</button> should contain the element with id "world". For example, the endpoint /api/world should return<div id="world">Hello World</div>.