Directive reference
All 68 dj-* directives, generated from the framework.
On this page
Every dj-* directive djust understands, generated from
djust.schema.get_surface_manifest() in the pinned framework.
68 directives across 13 categories. This page is generated — if a directive is missing here it is missing from the framework, not from the docs.
Categories
- Events — 18
- Two-way binding — 2
- Loading states — 9
- DOM manipulation — 7
- Animation & transitions — 5
- Navigation — 3
- Streaming — 4
- Uploads — 4
- Performance — 5
- Recovery — 1
- Modifiers — 8
- Hooks — 1
- Client — 1
Events
dj-blur
Send event when element loses focus
Value: handler_name
<input dj-blur="validate_field" name="email">
dj-change
Send event on input change (fires on blur for text, immediately for checkboxes/selects)
Value: handler_name
<select dj-change="filter_by"><option>All</option></select>
dj-click
Send event to server on click
Value: handler_name or handler_name('arg1', arg2)
<button dj-click="increment">+1</button>
dj-click-away
Fire a server event when a click occurs outside this element (commonly used to close dropdowns/popovers).
Value: handler_name
<div dj-click-away="close_menu">...</div>
dj-document-*
Bind a keydown/keyup/click/scroll/resize listener scoped to document instead of the element. Supports an optional '.key' modifier suffix for key events.
Value: handler_name
<div dj-document-click="track_page_click">...</div>
dj-focus
Send event when element receives focus
Value: handler_name
<input dj-focus="track_focus" name="search">
dj-input
Send event on every keystroke (auto-debounced 300ms for text, throttled for range/number)
Value: handler_name
<input dj-input="search" name="query">
dj-keydown
Send event on keydown. Supports key modifiers (e.g., dj-keydown.enter).
Value: handler_name or handler_name.enter
<input dj-keydown.enter="submit_search">
dj-keyup
Send event on keyup. Supports key modifiers like dj-keydown.
Value: handler_name or handler_name.escape
<input dj-keyup.escape="clear_search">
dj-mounted
Fire a server event the first time this element enters the DOM after initial page mount (e.g. an element revealed by a later {% if %} patch or a modal that opens later). Fires once per DOM node.
Value: handler_name
<div dj-mounted="chart_ready" data-value-chart-id="{{ id }}">...</div>
dj-mouseenter
Send event when the pointer enters the element. Non-bubbling: entering a child fires neither the parent's dj-mouseleave nor a second dj-mouseenter.
Value: handler_name
<div dj-mouseenter="preview">Hover me</div>
dj-mouseleave
Send event when the pointer leaves the element. Non-bubbling: moving into a child element does not fire it.
Value: handler_name
<div dj-mouseenter="preview" dj-mouseleave="hide_preview">Hover me</div>
dj-mutation
Fire a server event when this element's attributes or children change (bridges third-party widgets — charts, maps, rich-text editors — that mutate the DOM outside djust's control). Observes attribute changes if dj-mutation-attr is set, otherwise observes childList changes.
Value: handler_name
<div dj-mutation="on_change" dj-mutation-attr="class,style">...</div>
Related
dj-mutation-attr— Comma-separated attribute names to observe (default: observe childList instead).dj-mutation-debounce— Coalesce bursts of mutations within N ms into one server event (default: 150).
dj-paste
Fire a server event on paste, with structured payload (text, html, and file metadata from the clipboard). Pasted files flow through the dj-upload pipeline rather than the WebSocket event frame.
Value: handler_name
<div dj-paste="handle_paste" contenteditable>...</div>
Related
dj-paste-suppress— Prevent the browser's default paste behavior after dispatch.
dj-poll
Declarative polling: periodically send event to server. Pauses when tab is hidden.
Value: handler_name
<div dj-poll="refresh_data" dj-poll-interval="5000">...</div>
dj-shortcut
Bind one or more keyboard shortcuts to server events. Comma-separated bindings of the form '[modifier+...]key:handler[:prevent]'. Ignored while a form input has focus unless dj-shortcut-in-input is also present.
Value: 'ctrl+k:open_search,escape:close_modal:prevent'
<body dj-shortcut="ctrl+k:open_search,escape:close_modal:prevent">
Related
dj-shortcut-in-input— Opt-in flag: also fire the shortcut while a form field has focus.
dj-submit
Send form data to server on submit. Calls e.preventDefault() and e.target.reset().
Value: handler_name
<form dj-submit="create_item"><input name="title"><button>Add</button></form>
dj-window-*
Bind a keydown/keyup/click/scroll/resize listener scoped to window instead of the element — for global shortcuts and viewport-level events. Supports an optional '.key' modifier suffix for key events.
Value: handler_name
<div dj-window-keydown.escape="close_modal">...</div>
Two-way binding
dj-force-value
Opt a focused form field into server-authoritative value sync during VDOM patches (by default, focused fields are skipped to preserve what the user is typing).
Value: (no value needed)
<input dj-model="draft" dj-force-value>
dj-model
Two-way data binding between form element and server state. Syncs on 'input' event by default.
Value: field_name
<input type="text" dj-model="search_query">
Loading states
dj-disable-with
Disable the element and swap its text while its triggering event is in flight; original text is restored on response.
Value: loading text
<button dj-click="save" dj-disable-with="Saving...">Save</button>
dj-form-pending
React to an ancestor form's dj-submit being in-flight, without writing a hook. React 19 useFormStatus equivalent.
Value: 'hide' | 'show' | 'disabled'
<form dj-submit="save"><span dj-form-pending="show">Saving...</span></form>
dj-loading
Shorthand form: disable this element while the named event is in flight (equivalent to dj-loading.disable, but scoped to a specific event name rather than the element's own triggering event).
Value: event_name
<button dj-loading="save">Save</button>
dj-loading.class
Add CSS class while event is in flight
Value: class_name
<button dj-click="save" dj-loading.class="opacity-50">Save</button>
dj-loading.disable
Disable element while event is in flight
Value: (no value needed)
<button dj-click="save" dj-loading.disable>Save</button>
dj-loading.for
Explicit form of the dj-loading shorthand: works on any element (not just the one triggering the event) — react while the named event is in flight anywhere on the page.
Value: event_name
<span dj-loading.for="save">Saving...</span>
dj-loading.hide
Hide element while event is in flight
Value: (no value needed)
<div dj-loading.hide>Normal content</div>
dj-loading.show
Show element (set display) while event is in flight
Value: display_value (default: 'block')
<div dj-loading.show="flex" style="display:none">Loading...</div>
dj-lock
Prevent duplicate submissions: locks the element (disables form fields, adds a CSS class otherwise) on first trigger and skips subsequent triggers until the response unlocks it.
Value: (no value needed)
<button dj-click="submit_order" dj-lock>Place Order</button>
DOM manipulation
dj-cloak
Hide this element (display:none via injected CSS) until the LiveView mount completes — prevents a flash of unstyled/un-hydrated content. Removed automatically once mounted.
Value: (no value needed)
<div dj-cloak>Loading skeleton...</div>
dj-dialog
Native <dialog> modal integration. Toggling the value between 'close'/'open' calls showModal()/close() on the element.
Value: 'open' | 'close'
<dialog id="settings" dj-dialog="{{ show_settings|yesno:'open,close' }}">...</dialog>
Related
dj-dialog-close-event— Server event fired when the user closes the dialog client-side (Escape, backdrop click), keeping server state in sync.
dj-ignore-attrs
Mark HTML attributes as client-owned so VDOM SetAttr patches skip them — for browser-native elements (<dialog open>, <details open>) and third-party JS that manages attributes the server doesn't know about.
Value: comma-separated attribute names
<dialog dj-ignore-attrs="open">...</dialog>
dj-scroll-into-view
Automatically scroll this element into view after a DOM update.
Value: (no value needed) | scrollIntoView options string
<div id="latest-message" dj-scroll-into-view></div>
dj-sticky-scroll
Keep a scrollable container pinned to the bottom as new content is appended, backing off (and re-arming) based on user scroll position.
Value: (no value needed)
<div dj-sticky-scroll style="overflow-y: auto; height: 400px">...</div>
dj-target
Scope the server re-render to a specific element (CSS selector)
Value: CSS selector (e.g., #sidebar, .panel)
<button dj-click="refresh_sidebar" dj-target="#sidebar">Refresh</button>
dj-update
Control how server HTML updates are applied to this element
Value: append | prepend | replace | ignore
<ul dj-update="append" id="messages">{% for msg in messages %}<li>{{ msg }}</li>{% endfor %}</ul>
Animation & transitions
dj-flip
FLIP-technique reorder animation: when a child of this element reorders, animate it from its old screen position to its new one.
Value: (no value needed)
<ul dj-flip>{% for item in items %}<li id="item-{{ item.id }}">{{ item.label }}</li>{% endfor %}</ul>
Related
dj-flip-duration— Transition duration in ms (default: 300).dj-flip-easing— CSS easing function for the transform transition.
dj-remove
Declarative CSS exit transition. When a VDOM patch would remove this element, djust delays the removal until the transition completes (or a fallback timeout fires).
Value: 'start active end' | 'class-name'
<li dj-remove="fade-out">Toast</li>
Related
dj-remove-duration— Override the fallback timeout in ms (default: 600, clamped 0-30000).
dj-transition
Declarative CSS enter transition. Three-token form 'start active end' applies each class in a phase; single-token short form applies one class and waits for transitionend.
Value: 'start active end' | 'class-name'
<div dj-transition="opacity-0 transition-opacity-300 opacity-100">Fades in</div>
dj-transition-group
Orchestrate enter/leave animations for a list of children by wiring dj-transition/dj-remove specs onto each child automatically.
Value: (no value, use dj-group-enter/dj-group-leave) | 'enter-spec | leave-spec'
<ul dj-transition-group dj-group-enter="opacity-0 transition-opacity-300 opacity-100" dj-group-leave="opacity-100 transition-opacity-300 opacity-0">...</ul>
Related
dj-group-enter— Enter transition spec applied to newly-added children.dj-group-leave— Leave transition spec applied to removed children.dj-group-appear— Also animate children present on first render (not just later additions).
dj-view-transitions
Opt in to wrapping VDOM patches in the browser's document.startViewTransition() API (cross-fade by default; view-transition-name enables shared-element morphs). Placed on <body>. No-ops gracefully when unsupported (Firefox) or when the user has requested prefers-reduced-motion: reduce.
Value: (no value needed)
<body dj-view-transitions>
Navigation
dj-navigate
Navigate to a different LiveView over the existing WebSocket (no page reload)
Value: URL path
<a dj-navigate="/items/42/">View Item</a>
dj-patch
Update URL params without remounting the view (client-side pushState + server url_change)
Value: URL path or query string
<a dj-patch="?page=2&sort=name">Page 2</a>
dj-patch-reload
Opt-in escape hatch: force a full page navigation for this dj-patch/dj-navigate link instead of an in-place client-side URL update.
Value: (no value needed)
<a dj-patch="?page=2" dj-patch-reload>Page 2</a>
Streaming
dj-stream
Mark element as a stream target for server-pushed DOM operations
Value: stream_name
<ul dj-stream="messages">{% for msg in streams.messages %}<li>{{ msg }}</li>{% endfor %}</ul>
dj-stream-mode
Default insertion mode for streaming text content
Value: append | replace | prepend
<div dj-stream="output" dj-stream-mode="append"></div>
dj-viewport-bottom
Fire a server event once when the last child of this container enters the viewport (bidirectional infinite scroll, forward pagination).
Value: handler_name
<div dj-stream="messages" dj-viewport-bottom="load_newer">...</div>
Related
dj-viewport-threshold— IntersectionObserver threshold, 0-1 (default: 0.1).
dj-viewport-top
Fire a server event once when the first child of this container enters the viewport (bidirectional infinite scroll, backward pagination).
Value: handler_name
<div dj-stream="messages" dj-viewport-top="load_older">...</div>
Related
dj-viewport-threshold— IntersectionObserver threshold, 0-1 (default: 0.1).
Uploads
dj-upload
Bind a file input to an upload slot (binary WebSocket upload)
Value: upload_slot_name
<input type="file" dj-upload="avatar">
dj-upload-drop
Mark element as a drag-and-drop zone for file uploads
Value: upload_slot_name
<div dj-upload-drop="attachments">Drop files here</div>
dj-upload-preview
Container for image upload previews (auto-populated with thumbnails)
Value: upload_slot_name
<div dj-upload-preview="avatar"></div>
dj-upload-progress
INERT — registered as an attribute but no client code reads it; no progress bar is created. Render progress server-side instead.
Value: upload_slot_name
<div dj-upload-progress="attachments"></div>
Performance
dj-key
Stable identity for an item in a list, so the VDOM differ can MOVE a row instead of destroying and rebuilding it when the list reorders. Without it the differ falls back to positional diffing, which discards the DOM node — losing focus, input values, scroll position and any client-side state attached to it. Read by the Rust template parser into VNode.key (crates/djust_vdom/src/parser.rs), where data-key is accepted as an equivalent spelling. Keys must be UNIQUE among siblings: a duplicate is ambiguous, so the differ demotes those siblings to positional diffing and warns DJE-051. Prefer this over an authored dj-id, which the parser ignores (#1253).
Value: unique_value_per_item
{% for item in items %}<li dj-key="{{ item.id }}">{{ item.name }}</li>{% endfor %}
Related
data-key— Equivalent spelling, accepted by the same parser branch. Also the default height-cache key for dj-virtual in variable-height mode (see dj-virtual-key-attr).
dj-lazy
Defer WebSocket connection and LiveView mounting until the element enters the viewport, is clicked, or is hovered — reduces memory/connections for below-fold LiveViews.
Value: 'viewport' (default) | 'click' | 'hover'
<div dj-view="my_view" dj-lazy>...</div>
dj-prefetch
Prefetch a same-origin link's page via the service worker when the user hovers over it. Value 'false' opts a link out.
Value: (no value needed) | 'false'
<a href="/reports/" dj-prefetch>View reports</a>
dj-track-static
Detect stale static assets (script/link) after a WebSocket reconnect and dispatch a dj:stale-assets event, or reload the page automatically when the value is 'reload'.
Value: (no value needed) | 'reload'
<script dj-track-static src="{% static 'js/app.abc123.js' %}"></script>
dj-virtual
Render only the visible slice of a large list (windowed/virtual list with DOM recycling). Value names the context list variable driving the list.
Value: items_var_name
<div dj-virtual="items" dj-virtual-item-height="48">...</div>
Related
dj-virtual-item-height— Fixed pixel height per item.dj-virtual-variable-height— Opt into variable heights, measured via ResizeObserver.dj-virtual-overscan— Rows rendered above/below the viewport (default: 3).dj-virtual-estimated-height— Baseline height for unmeasured items in variable mode (default: 50).dj-virtual-key-attr— Attribute used as the height-cache key in variable mode (default: 'data-key').
Recovery
dj-auto-recover
After a WebSocket reconnect, serialize this container's form field values and data-* attributes and fire the named event so the server can restore client-only state that didn't round-trip through the view.
Value: handler_name
<div dj-auto-recover="restore_draft">...</div>
Related
dj-no-recover— Exclude an individual field within (or outside) an auto-recover container from recovery serialization.
Modifiers
dj-confirm
Show browser confirm() dialog before sending event. Cancels if user declines.
Value: confirmation message
<button dj-click="delete_item" dj-confirm="Are you sure?">Delete</button>
dj-debounce
Debounce a rate-limited event directive (dj-input/dj-change/dj-keydown/dj-keyup) by N milliseconds, or 'blur' to defer until the field loses focus. Takes precedence over the legacy data-debounce attribute.
Value: milliseconds | 'blur'
<input dj-input="search" dj-debounce="500">
dj-no-submit
Swallow Enter-key submits from text inputs in this form (the 'enter' mode); prevents accidental submission on multi-field forms.
Value: 'enter'
<form dj-submit="save" dj-no-submit="enter">...</form>
dj-params
DEPRECATED (0.3.2 -> 0.3.6+ migration): JSON blob of extra params to send with an event. Use dj-value-* attributes instead — data-/dj-value- keys take precedence over dj-params keys with the same name.
Value: '{"key": "value"}' JSON blob
<button dj-click="save" dj-params='{"source": "toolbar"}'>Save</button>
dj-poll-interval
Polling interval in milliseconds for dj-poll (default: 5000)
Value: milliseconds
<div dj-poll="refresh" dj-poll-interval="3000">...</div>
dj-throttle
Throttle a rate-limited event directive to at most once per N milliseconds. Takes precedence over the legacy data-throttle attribute.
Value: milliseconds
<input dj-input="live_search" dj-throttle="200">
dj-trigger-action
Native POST bridge: when the server pushes a trigger-action event, submit this form natively (full page navigation) instead of over the WebSocket — for flows that need a real HTTP redirect (e.g. payment providers).
Value: (no value needed)
<form action="/checkout/" method="post" dj-trigger-action>...</form>
dj-value-*
Pass static context alongside any event directive as typed params (Phoenix LiveView's phx-value-* equivalent). Supports the same ':type' coercion suffixes as data-* attributes.
Value: any string (kebab-case suffix -> snake_case param key)
<button dj-click="delete" dj-value-item-id:int="{{ item.id }}">Delete</button>
Hooks
dj-hook
Attach a client-side JS hook to this element. Hook receives mounted/updated/destroyed callbacks.
Value: HookName (registered in window.djust.hooks)
<canvas dj-hook="MyChart" data-values="{{ chart_data }}"></canvas>
Related
dj-hook-value-*— Typed value exposed to the hook as this.values.<camelCase> (ADR-025). e.g. dj-hook-value-code='"007"' -> this.values.code. Kebab-case attribute suffix maps to camelCase property; read-only from JS.dj-hook-target— Marks a descendant of the hook's element as a named scoped query target, retrieved via this.target(name) / this.targets(name).
Client
dj-copy
Copy attribute value to clipboard on click (client-only, no server event)
Value: text to copy (can use template variables)
<button dj-copy="{{ api_key }}">Copy Key</button>
Related
dj-copy-class— CSS class applied to the button while showing feedback (default: 'dj-copied')dj-copy-event— Server event name to also fire after a successful copydj-copy-feedback— Temporary button text shown after copying (default: 'Copied!')