javascripthtmx

HTMX Javascript API is missing OOB swap?


Im using JS API of the HTMX library to add contents. for example:

htmx.ajax('GET', url, {
    target: '#js-product-list',
    swap: 'beforeend', // Adding new stuff to already existing content
})
.then(() => {
...

Now lets say I would like to also update filter component on the page. Is it possible using JS API (without hx-* attributes)?

I tried

htmx.ajax('GET', url, {
    target: '#js-product-list',
    swap: 'beforeend',
    swapOptions: {
        swapOOB: '#js-filter-wrapper'
    }
})
.then(() => {
...

Markup details:

htmx.ajax('GET', url, {
        target: '#js-product-list',
        swap: 'beforeend',
        swapOptions: {
            swapOOB: '#js-filter-wrapper'
        }
    })
<div class="container position-relative" id="js-main-content">
    <header>
        <div class="d-flex justify-content-between mx-1 my-3" id="js-filter-wrapper">
            Filter content
        </div>
        <div class="mt-3 ms-1" id="js-main-title-wrapper">
            <h1>Heading</h1>
        </div>
    </header>
    <main class="row" id="js-product-list">
        Product list content
    </main>
</div>

This is what will be returned in response:

<div id="js-filter-wrapper" hx-swap-oob="#js-filter-wrapper">
    Updated filter that will replace current filter
</div>

<div>
   New products that will be appended to current ones using beforeend selector
</div>


Solution

  • To swap the filter OOB way, You will need to update the components, you desire . I have provided an example.

    <div id="js-product-list">
        <!-- Product list content here -->
    </div>
    <div id="js-filter-wrapper" hx-swap-oob="true">
        <!-- Filter component content here -->
    </div>
    
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>HTMX Example</title>
        <script src="https://unpkg.com/htmx.org@1.6.1"></script>
    </head>
    <body>
    
    <div class="container position-relative" id="js-main-content">
        <header>
            <div id="js-filter-wrapper">
                <!-- Initial filter component content -->
            </div>
            <div class="mt-3 ms-1" id="js-main-title-wrapper">
                <h1>Heading</h1>
            </div>
        </header>
        <main class="row" id="js-product-list">
            <!-- Initial product list content -->
        </main>
    </div>
    
    <script>
    function updateComponents(url) {
        htmx.ajax('GET', url, {target: '#js-product-list', swap: 'beforeend'})
            .then((response) => {
                const parser = new DOMParser();
                const doc = parser.parseFromString(response, 'text/html');
    
                // Extract and update the filter component
                const newFilter = doc.querySelector('#js-filter-wrapper');
                if (newFilter) {
                    document.querySelector('#js-filter-wrapper').innerHTML = newFilter.innerHTML;
                }
            })
            .catch((error) => {
                console.error('Error updating components:', error);
            });
    }
    
    // Example usage
    updateComponents('/your-endpoint');
    </script>
    
    </body>
    </html>