A button outside a form can still submit that form's data: point kj-include at it. kj-vals takes a JSON object and adds each key as a parameter — ideal for IDs, page numbers and flags that don't belong in a visible field.
Because the server can return new markup with new kj-vals, you can build small stateful interactions with a stateless backend — like the like-button below, which carries its own count.
The like button posts its count; like.php returns a new button carrying count + 1. No database, no JavaScript.
View the source for this demo
<form id="flt" class="grid g3" style="gap:12px">
<div class="field"><label for="flt-cat">Category</label><input id="flt-cat" name="category" type="text" value="cables"></div>
<div class="field"><label for="flt-sort">Sort</label><select id="flt-sort" name="sort"><option>newest</option><option>popular</option><option>price</option></select></div>
<label style="align-self:end;padding-bottom:10px"><input type="checkbox" name="in_stock" value="1" checked> In stock only</label>
</form>
<div class="row" style="margin-top:12px">
<button type="button" kj-post="/api/echo.php" kj-include="#flt" kj-vals='{"page": 2, "source": "demo"}' kj-target="#flt-out">Apply filters (page 2)</button>
<span id="like-slot"><button type="button" kj-post="/api/like.php" kj-vals='{"count": 41}' kj-swap="outerHTML" aria-label="Like (41 likes)">♥ 41</button></span>
</div>
<div id="flt-out" aria-live="polite" style="margin-top:12px"></div>// Enter in the text field shouldn't submit the form the normal way
$('#flt').on('submit', e => e.preventDefault());More examples
Markup
<form id="search-filters">…</form>
<button kj-get="/products" kj-include="#search-filters" kj-vals='{"page": 3}' kj-target="#grid">Page 3</button>API
Send extra data: the fields of another form, and/or literal JSON values.
Reference: kj-include / kj-vals →Migrating
hx-include and hx-vals. hx-vals="js:…" (computed values) and hx-params filtering 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 →CoreForms & serialization
Turn forms into query strings or plain objects with serialize() and serializeObject(), then submit them with $.post — or declaratively with kj-post..
Open →HyperTargets & swaps
Control exactly where server HTML lands with kj-target and how it is inserted with kj-swap — innerHTML, outerHTML, beforebegin, afterbegin, beforeend, afterend, textContent or none..
Open →