Using htmx Out‑of‑Band Swaps to Update Multiple UI Fragments with One Request
Learn how htmx’s out‑of‑band swap attribute lets a single AJAX request update multiple unrelated UI fragments—like a comment list, a badge, and a sidebar—without extra round‑trips or custom JavaScript.
11 Feb 2026, 00:26 UTC

Problem: Updating Several UI Pieces After One Action
When a user submits a comment form, the application often needs to refresh the comment list, a badge that shows the total count, and a sidebar that displays recent activity. Doing this with separate Ajax calls creates extra round‑trips and requires coordinating multiple callbacks.
Thesis: htmx’s Out‑of‑Band (OOB) Swap Lets One Response Drive Many Updates
By marking extra HTML fragments with hx-swap-oob, a single server response can tell htmx to place the main payload into its target while silently inserting the marked fragments wherever they belong in the DOM.
Setting Up a Minimal htmx Page
<!DOCTYPE html>
<html>
<head>
<meta charset='UTF-8'>
<title>Comment demo</title>
<script src='https://unpkg.com/htmx.org@1.9.0'></script>
</head>
<body>
<div id='comment-list'>
<!-- existing comments go here -->
</div>
<form id='comment-form'
hx-post='/comments'
hx-target='#comment-list'
hx-swap='afterbegin'>
<textarea name='content' required></textarea>
<button type='submit'>Post</button>
</form>
<div id='badge'>0</div>
<div id='sidebar'></div>
</body>
</html>
Designing the Server Endpoint to Return OOB Fragments
The endpoint must return a fragment that contains:
- The new comment markup (the default target).
- A badge element marked
hx-swap-oob='true'with the updated count. - A sidebar snippet also marked
hx-swap-oob='true'.
Example (pseudo‑code, language‑agnostic):
def comments_post(request):
# 1. store the comment
comment = save_comment(request.POST['content'])
# 2. build fragments
comment_html = f"<li class='comment'>{escape(comment.content)}</li>"
badge_html = f"<span id='badge' hx-swap-oob='true'>{get_total_count()}</span>"
sidebar_html = f"<div id='sidebar' hx-swap-oob='true'>{render_recent_activity()}</div>"
# 3. concatenate
return comment_html + badge_html + sidebar_html
Worked Example: Submitting the Form
- User fills the textarea and clicks Post.
- htmx issues a POST to
/comments(one XHR/fetch). - The server returns the concatenated HTML described above.
- htmx inserts the
<li>comment at the beginning of#comment-listbecause ofhx-swap='afterbegin'. - Because the badge and sidebar elements carry
hx-swap-oob='true', htmx finds the existing elements with matching IDs and replaces their inner HTML, all without issuing another network request. - The UI now shows the new comment, the updated count, and the fresh sidebar snippet.
Trade‑offs and Limitations
- Payload size: The response now carries the comment plus the badge and sidebar markup. If those fragments are large, the single request becomes heavier than several tiny requests.
- Server‑client coupling: The endpoint must know which IDs exist on the page and what OOB updates are appropriate, tying backend rendering logic to frontend layout.
- Caching considerations: Because the response varies with the badge count and sidebar content, caching the whole fragment may be less effective; you may need to conditionally include OOB parts based on request headers (e.g.,
HX-Request) or use fragment caching per component.
Practical Way to Check the Result
- Open the page in a browser with developer tools.
- In the Network tab, filter for XHR/fetch and submit the form.
- Confirm that only one request appears.
- Select that request and preview the response; you should see the comment HTML followed by the
hx-swap-oobmarked badge and sidebar snippets. - After the request finishes, inspect the DOM: the new comment should be inside
#comment-list, the text of#badgeshould reflect the new total, and#sidebarshould contain the fresh snippet.
Next Steps
Try adding hx-swap-oob to a small component in your own project, measure the network round‑trip reduction, and watch payload growth. If the extra size becomes a concern, move the OOB fragments into separate endpoints and include them conditionally, or cache the static parts of the sidebar and badge.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.