← Playground index

AjaxSlim — guide

AjaxSlim is a morph-native, multi-container-supporting subset of Wonder's Ajax.framework, without Prototype or Scriptaculous. Dynamic elements live in er.ajax.elements and look and feel similar to the old Ajax elements. For a detailed overview of ported elements and their bindings, see the element reference.

How it works

The big picture

An AjaxSlim update is one HTTP round-trip that refreshes parts of a page in place. The unit of refresh is an AjaxUpdateContainer — a named region of the page. Something triggers an update (a link, a form submit, a timer, a field change, or a server action), the framework re-renders the targeted container(s) on the server, and the client reconciles the fresh HTML into the live DOM by morphing (Idiomorph) rather than replacing — so focus, scroll, selection and unchanged subtrees survive.

The whole flow turns on a single request marker, _u, that carries the target set: the ;-joined ids of the containers to refresh (e.g. _u=detail or _u=boxA;boxB). On a request carrying _u, the page renders as usual but only the targeted containers emit their content to the response. Everything else — who decides the set, how it travels back, how the client applies it — hangs off that one idea.

Server-side API for specifying update targets

Optional use. Elements like AjaxUpdateLink set the target set for you. But when the server should decide which containers refresh (the action picks them, not the client), call AjaxUpdater from your action:

AjaxUpdater.add(containerID, context)   // augment the set the client asked for
AjaxUpdater.set(context, id1, id2, …) // replace it — the server has the final say
AjaxUpdater.clear(context)             // refresh nothing (a valid "nothing changed")

These mutate the request's target set; the normal render pass then emits exactly those containers in the current response — one round-trip, no extra fetches. The contract is a phase one: call them from your action, because the set is read once when rendering begins (after the action returns) and must be final by then. See the server-side targeting scenario.

The other public surface is AjaxUtils — lower-level helpers most apps never touch directly: createResponse, javascriptResponse, header/script append helpers, isAjaxRequest, and the resource-in-head helpers. And AjaxUpdateProtocol is the internal targeting protocol itself (reading/writing _u, the current-container stack, resolving updateContainerID bindings and "_parent") — framework plumbing, not normally called by apps.

Over the wire

The server frames every container's content uniformly. A targeted container emits its HTML wrapped in an inert element tagged with its id:

// _u=cartCount;cartLines;total — three containers refreshed in one round-trip
<ajaxslim-fragment data-id="cartCount">3 items</ajaxslim-fragment>
<ajaxslim-fragment data-id="cartLines">
    <tr><td>Coffee</td><td>2</td></tr>
    <tr><td>Filters</td><td>1</td></tr>
</ajaxslim-fragment>
<ajaxslim-fragment data-id="total">$24.00</ajaxslim-fragment>

One rule: content destined for an update container is a fragment — whether one container or many, whether the target set came from the client (updateContainerID="a;b;c") or the server (AjaxUpdater.set). No single-vs-multi, no client-vs-server special case. A multi-update response is simply several <ajaxslim-fragment>s back to back, as above — the client morphs each into its own container independently.

On the client, ajaxslim.js fetches the URL and acts on what the response IS, not on what it asked for:

HTTP errors are never morphed — a 500/404 is diverted to an error reporter instead of the server's error page landing in your container. The client API mirrors the elements: AjaxSlim.AUC (update containers), AjaxSlim.AUL (update links), AjaxSlim.ASB (submit buttons), each exposing update/request-style entry points.

This fragment framing is the protocol today; it is evolving toward a more explicit command protocol (the response telling the client what to do, not only what to morph). The shape above is what ships now.

Migrating from the Ajax framework

AjaxSlim is largely a drop-in replacement, so most templates need no change. The things that actually break a port are almost all client-side, because the Prototype/Scriptaculous runtime is gone:

Client side

<id>Update() AjaxSlim.AUC.update('<id>') The per-container global function the old framework generated (via eval) no longer exists. Call the public API to refresh a container from your own JS.
AjaxUpdateContainer
frequency / action / observeFieldID
AjaxSelfUpdatingContainer The container element was split. A container that refreshes itself (on a timer, on a field change, or running its own action) is now AjaxSelfUpdatingContainer; plain AjaxUpdateContainer is passive and only refreshes when something else targets it. An old self-updating container ported as-is will stop refreshing.
AUC. / AUL. / ASB. AjaxSlim.AUC. / AUL. / ASB. The client globals are namespaced now. Any custom JS calling the bare globals needs the AjaxSlim. prefix.
effect / insertion
*Duration / *EffectID
— (dropped) All Scriptaculous effect & insertion bindings are gone (no effects.js). Use CSS transitions instead. onComplete/onSuccess are kept, repurposed as post-morph JS hooks.
onLoading / onFailure
asynchronous / evalScripts
— (dropped) The Prototype Ajax.Request transport options are gone — the transport that consumed them (Prototype) was replaced by fetch.
AjaxPing frequency
(milliseconds)
AjaxPing frequency
(seconds)
Time-bound bindings are now in seconds, everywhere. AjaxPing.frequency changed from milliseconds to seconds to match AjaxSelfUpdatingContainer.frequency, observeDelay, and the rest — so an old frequency="15000" (15 s) becomes frequency="15"; the default went 3000 → 3. A bare number on AjaxBusySpinner.delay/fade is likewise seconds now (was ms).

Also worth knowing: updates now morph the DOM (Idiomorph) by default instead of replacing innerHTML — focus, scroll and selection survive a refresh; bind morph="$false" for the old replace-everything behaviour. And ~40 rarely-used legacy elements (Accordion, Tree, Slider, DatePicker, drag/drop, in-place editors, the Scriptaculous effects, …) were not ported — AjaxSlim is the actually-used core; reach for a platform/native equivalent for those.

Server side

Java code that only binds elements in templates is unaffected. The classic AjaxUpdateContainer was also a grab-bag of static methods; those were tidied off the element and into the core API surface where invokable logic belongs. Code that called them needs these changes:

AjaxUpdateContainer
.updateContainerWithID(id, ctx)
AjaxUpdater.triggerUpdate(id, ctx) The server-side "refresh this container" API moved onto AjaxUpdater (safeUpdateContainerWithIDAjaxUpdater.triggerSafeUpdate). Both are themselves deprecated — prefer the same-pass AjaxUpdater.add/set; see How it works.
AjaxUpdateContainer
.updateContainerID(…), .currentUpdateContainerID(), …
AjaxUpdateProtocol The update-targeting protocol — reading/writing the request's target set, the current-container stack, resolving the updateContainerID binding — moved verbatim (same method names) onto AjaxUpdateProtocol. Rarely called by apps directly.
AjaxUpdateContainer
.expandInsertion(…), .removeDefaultOptions(…)
— (dropped) Scriptaculous insertion/effect-option helpers, gone with the effects runtime.