Lazy Loading & Polling
The <what-fetch> tag declares a region of the page that fills itself from a partial — on render, when scrolled into view, on a timer, or on click. No fetch(), no setInterval, no observers to write.
The three canonical forms
<!-- fetch on page render (the default) -->
<what-fetch url="/w-partial/time"/>
<!-- lazy: fetch the first time it scrolls into view -->
<what-fetch url="/w-partial/comments" when="visible">Loading…</what-fetch>
<!-- live: refresh every 5 seconds -->
<what-fetch url="/w-partial/stats" poll="5s">
<include src="partials/stats"/>
</what-fetch>
Children are the region's initial content — server-render the first state with an <include> so the page is complete before any fetch happens, or use a lightweight placeholder for lazy regions.
Attributes
| Attribute | Default | Meaning |
|---|---|---|
url | required | What to fetch — usually a /w-partial/… path. #var# interpolates. |
when | load | load (on render), visible (first scroll into view), click |
poll | — | Refresh interval: 500ms, 5s, 2m, 1h, or bare seconds. Combines with when. |
method | get | get or post |
target | itself | CSS selector to inject into, if not the region itself |
swap | innerHTML | innerHTML, outerHTML, prepend, append, before, after, none |
as | div | Wrapper element, e.g. as="tbody" inside a table |
params, include, loading, confirm | — | Pass through to w-params, w-include, w-loading, w-confirm |
Anything else (class, id, style, aria-*…) is copied onto the wrapper verbatim.
The raw attribute form
<what-fetch> is sugar: the server expands it to the w-* attributes, which you can also write directly on any element. These are equivalent:
<what-fetch url="/w-partial/stats" poll="5s">…</what-fetch>
<div class="w-fetch" w-get="/w-partial/stats" w-trigger="load, poll 5s">…</div>
w-trigger for w-get/w-post elements accepts load, revealed, poll <interval>, and click, comma-combinable. Without w-target the element injects into itself. The framework manages every timer and observer: they're cancelled when the element leaves the DOM, paused while the tab is hidden, and a slow response never stacks requests.
Polling vs. Wired State
Polling is pull: the browser asks on a schedule. It's right for data the server doesn't know changed — external APIs, aggregations, anything without an event. For shared app state that your server mutates, prefer Wired State: it's push — one WebSocket message updates every client instantly, with no wasted requests. A useful pairing: w-watch re-fetches a partial when a wired variable changes.
Events
The region fires w:load after each successful swap and w:error (plus a w-fetch-error class) on failure. A failed poll tick keeps the last good content — the region never degrades to an error message on a transient blip.
Things to know
- Be kind to your server. Every polling region on every open tab is a request stream. Prefer intervals in seconds, not milliseconds; prefer Wired State when you control the mutation.
- Don't self-destruct.
when="load"withswap="outerHTML"and notargetreplaces the region with the response, which re-arms and fetches again — an infinite loop. The dev console warns about this combination. - Static builds have no server. On a
run-what buildexport there is no/w-partial/*endpoint — regions keep their initial children. Design the fallback content accordingly.