kj-target takes any CSS selector (default: the element itself). kj-swap picks the insertion strategy:
| kj-swap | Effect | Typical use |
|---|---|---|
innerHTML | Replace the target's content (default) | Panels, results |
outerHTML | Replace the target itself | Edit-in-place rows, delete (empty response) |
beforeend | Append inside | Feeds, chat, "load more" |
afterbegin | Prepend inside | Newest-first lists |
beforebegin / afterend | Insert as a sibling | Inline forms, notices |
textContent | Insert as plain text | Counters, untrusted text |
none | Make the request, change nothing | Fire-and-forget, analytics |
View the source for this demo
<div class="row">
<button type="button" kj-get="/api/swaps/innerHTML.html" kj-target="#swap-anchor" kj-swap="innerHTML">innerHTML</button>
<button type="button" kj-get="/api/swaps/beforebegin.html" kj-target="#swap-anchor" kj-swap="beforebegin">beforebegin</button>
<button type="button" kj-get="/api/swaps/afterbegin.html" kj-target="#swap-anchor" kj-swap="afterbegin">afterbegin</button>
<button type="button" kj-get="/api/swaps/beforeend.html" kj-target="#swap-anchor" kj-swap="beforeend">beforeend</button>
<button type="button" kj-get="/api/swaps/afterend.html" kj-target="#swap-anchor" kj-swap="afterend">afterend</button>
<button type="button" kj-get="/api/swaps/innerHTML.html" kj-target="#swap-anchor" kj-swap="textContent">textContent</button>
<button type="button" kj-get="/api/swaps/outerHTML.html" kj-target="#swap-anchor" kj-swap="outerHTML">outerHTML</button>
<button type="button" id="swap-reset">Reset</button>
</div>
<div id="swap-zone" aria-live="polite" style="margin-top:14px">
<div class="sb" id="swap-anchor">■ target — watch where each response lands</div>
</div>$('#swap-reset').on('click', () =>
$('#swap-zone').html('<div class="sb" id="swap-anchor">■ target — watch where each response lands</div>'));More examples
Patterns
<!-- Chat: append each new message -->
<form kj-post="/chat/send" kj-target="#messages" kj-swap="beforeend">…</form>
<!-- Delete a row: server returns an empty body, the row disappears -->
<button kj-delete="/rows/9" kj-target="#row-9" kj-swap="outerHTML">Delete</button>
<!-- Track a click without touching the page -->
<a href="/pricing" kj-post="/track?e=pricing" kj-swap="none">Pricing</a>API
Where the response HTML goes (default: the element itself).
Reference: kj-target →How the response is inserted into the target. outerHTML replaces the target entirely; the four position values insert adjacent to it; none makes the request without touching the DOM.
Migrating
swap:1s, settle, scroll:top, show), hx-select and out-of-band swaps (hx-swap-oob) are not included.Related features
Declarative requests
Make GET, POST, PUT, PATCH and DELETE requests straight from HTML with kj-get, kj-post and friends — htmx-style hypermedia with zero JavaScript.
Open →HyperLazy loading & infinite scroll
Load content when it scrolls into view with kj-trigger="revealed", or immediately with kj-trigger="load".
Open →CoreLoading HTML fragments
Fetch a page and insert only the fragment you need with $(el).load("/page.html #section") — the classic jQuery partial-loading pattern on fetch..
Open →