2 Sugar
| (require datastar/sugar) | package: datastar-lib |
Provides convenience functions for building Datastar HTML attributes and action expressions.
Attributes (datastar/http/request) —
Functions for generating Datastar data-* attributes as x-expression attribute pairs. Actions (datastar/sugar/attributes) —
Functions for generating Datastar action strings in x-expression templates.
Without sugar:
`(button ((data-on:click__debounce.500ms "@post('/search')") (data-class:active "$enabled") (data-show "$query != ''")))
With sugar:
`(button (,(data-on 'click (post "/search") #:debounce "500ms") ,(data-class 'active "$enabled") ,(data-show "$query != ''")))
value
value
> `(script ((type "module") (src ,datastar-cdn-url)))
'(script
((type "module")
(src
"https://cdn.jsdelivr.net/gh/starfederation/datastar@v1.0.0/bundles/datastar.js")))
value
2.1 Attributes
| (require datastar/sugar/attributes) | package: datastar-lib |
Functions for generating Datastar data-* HTML attributes as x-expression attribute pairs. Helpers return (list 'attr-name "value") and drop directly into x-expression templates via unquote. See the Datastar attribute reference for full details on each attribute’s behavior.
value
> `(button (,(data-attr 'disabled "$loading"))) '(button ((data-attr:disabled "$loading")))
procedure
(data-attr/hash attrs) → list?
attrs : hash?
Hash keys must be symbols or strings. Values may be expression strings, JSON values, or nested hashes with symbol/string keys.
> `(button (,(data-attr/hash (hash "disabled" "$loading" "aria-busy" "$loading")))) '(button ((data-attr "{\"disabled\": $loading, \"aria-busy\": $loading}")))
procedure
(data-bind signal #:case case #:prop prop #:event event) → list? signal : (or/c symbol? string?) case : case-style/c prop : (or/c symbol? string?)
event :
(or/c (or/c symbol? string?) (listof (or/c symbol? string?)))
This SDK uses keyed form only (data-bind:signal).
#:case emits Datastar’s __case.* modifier.
#:prop emits __prop.<property>.
#:event emits __event.<event...> (single event or list).
When multiple modifiers are used, this helper emits them in deterministic order: __case, then __prop, then __event.
> `(input (,(data-bind 'username))) '(input ((data-bind:username "")))
> `(my-toggle (,(data-bind "is-checked" #:prop "checked" #:event "change"))) '(my-toggle ((data-bind:is-checked__prop.checked__event.change "")))
> `(input (,(data-bind "query" #:prop 'value #:event '("input" "change")))) '(input ((data-bind:query__prop.value__event.input.change "")))
procedure
(data-class key expression #:case case) → list?
key : (or/c symbol? string?) expression : string? case : case-style/c
#:case emits Datastar’s __case.* modifier.
> `(button (,(data-class 'active "$selected"))) '(button ((data-class:active "$selected")))
> `(button (,(data-class "my-class" "$selected" #:case 'camel))) '(button ((data-class:my-class__case.camel "$selected")))
procedure
(data-class/hash classes) → list?
classes : hash?
Hash keys must be symbols or strings. Values may be expression strings, JSON values, or nested hashes with symbol/string keys.
> `(div (,(data-class/hash (hash "font-bold" "$important" "text-red" "$error")))) '(div ((data-class "{\"text-red\": $error, \"font-bold\": $important}")))
procedure
(data-computed key expression #:case case) → list?
key : (or/c symbol? string?) expression : string? case : case-style/c
#:case emits Datastar’s __case.* modifier.
> `(div (,(data-computed 'total "$price * $quantity"))) '(div ((data-computed:total "$price * $quantity")))
> `(div (,(data-computed "my-signal" "$price * $quantity" #:case 'camel))) '(div ((data-computed:my-signal__case.camel "$price * $quantity")))
procedure
(data-computed/hash computed) → list?
computed : hash?
Hash keys must be symbols or strings. Values must be callable expression strings.
> `(div (,(data-computed/hash (hash 'total "() => $price * $qty" 'valid "() => $total > 0"))))
'(div
((data-computed
"{\"total\": () => $price * $qty, \"valid\": () => $total > 0}")))
procedure
(data-effect expression) → list?
expression : string?
> `(div (,(data-effect "$total = $price * $quantity"))) '(div ((data-effect "$total = $price * $quantity")))
procedure
(data-ignore [#:self? self?]) → list?
self? : boolean? = #f
When #:self? is #t, only the element itself is ignored; its children are still processed.
> `(div (,(data-ignore)) "Datastar will not process this or its children") '(div ((data-ignore "")) "Datastar will not process this or its children")
> `(div (,(data-ignore #:self? #t)) "Only this element is ignored") '(div ((data-ignore__self "")) "Only this element is ignored")
procedure
> `(div (,(data-ignore-morph)) "This content will not be morphed") '(div ((data-ignore-morph "")) "This content will not be morphed")
procedure
(data-indicator signal #:case case) → list?
signal : (or/c symbol? string?) case : case-style/c
This SDK uses keyed form only (data-indicator:signal).
#:case emits Datastar’s __case.* modifier.
> `(button (,(data-indicator 'loading) ,(data-on "click" (get "/data"))) "Fetch") '(button ((data-indicator:loading "") (data-on:click "@get('/data')")) "Fetch")
> `(div (,(data-show "$loading")) "Loading...") '(div ((data-show "$loading")) "Loading...")
procedure
(data-init expression #:delay delay [ #:viewtransition? viewtransition?]) → list? expression : string? delay : (or/c string? number?) viewtransition? : boolean? = #f
> (data-init (get "/events")) '(data-init "@get('/events')")
procedure
(data-json-signals #:include include #:exclude exclude [ #:terse? terse?]) → list? include : string? exclude : string? terse? : boolean? = #f
> `(pre (,(data-json-signals))) '(pre ((data-json-signals "")))
> `(pre (,(data-json-signals #:include "/^user/" #:terse? #t))) '(pre ((data-json-signals__terse "{\"include\": \"/^user/\"}")))
procedure
(data-on event expression [ #:once? once? #:passive? passive? #:capture? capture?] #:case case [ #:window? window? #:document? document? #:outside? outside? #:prevent? prevent? #:stop? stop?] #:debounce debounce [ #:debounce-leading? debounce-leading? #:debounce-notrailing? debounce-notrailing?] #:throttle throttle [ #:throttle-noleading? throttle-noleading? #:throttle-trailing? throttle-trailing?] #:delay delay [ #:viewtransition? viewtransition?]) → list? event : (or/c symbol? string?) expression : string? once? : boolean? = #f passive? : boolean? = #f capture? : boolean? = #f case : case-style/c window? : boolean? = #f document? : boolean? = #f outside? : boolean? = #f prevent? : boolean? = #f stop? : boolean? = #f debounce : (or/c string? number?) debounce-leading? : boolean? = #f debounce-notrailing? : boolean? = #f throttle : (or/c string? number?) throttle-noleading? : boolean? = #f throttle-trailing? : boolean? = #f delay : (or/c string? number?) viewtransition? : boolean? = #f
Leading/trailing timing modifiers require their base value keyword (for example, #:debounce-leading? requires #:debounce).
> (data-on "click" "$count++") '(data-on:click "$count++")
> (data-on "input" (post "/search") #:debounce "250ms") '(data-on:input__debounce.250ms "@post('/search')")
> (data-on "click" (get "/data") #:once? #t #:prevent? #t) '(data-on:click__once__prevent "@get('/data')")
> (data-on "keydown" "$handleKey(evt)" #:window? #t) '(data-on:keydown__window "$handleKey(evt)")
> (data-on "selectionchange" "doSomething()" #:document? #t) '(data-on:selectionchange__document "doSomething()")
> (data-on 'my-event "fn()" #:case 'camel) '(data-on:my-event__case.camel "fn()")
procedure
(data-on-intersect expression [ #:once? once? #:half? half? #:full? full? #:exit? exit?] #:threshold threshold #:debounce debounce [ #:debounce-leading? debounce-leading? #:debounce-notrailing? debounce-notrailing?] #:throttle throttle [ #:throttle-noleading? throttle-noleading? #:throttle-trailing? throttle-trailing?] #:delay delay [ #:viewtransition? viewtransition?]) → list? expression : string? once? : boolean? = #f half? : boolean? = #f full? : boolean? = #f exit? : boolean? = #f threshold : (or/c string? number?) debounce : (or/c string? number?) debounce-leading? : boolean? = #f debounce-notrailing? : boolean? = #f throttle : (or/c string? number?) throttle-noleading? : boolean? = #f throttle-trailing? : boolean? = #f delay : (or/c string? number?) viewtransition? : boolean? = #f
Leading/trailing timing modifiers require their base value keyword.
> (data-on-intersect (get "/load-more") #:once? #t #:half? #t) '(data-on-intersect__once__half "@get('/load-more')")
procedure
(data-on-interval expression #:duration duration [ #:duration-leading? duration-leading? #:viewtransition? viewtransition?]) → list? expression : string? duration : (or/c string? number?) duration-leading? : boolean? = #f viewtransition? : boolean? = #f
#:duration-leading? requires #:duration.
> (data-on-interval "$count++" #:duration "2s") '(data-on-interval__duration.2s "$count++")
> (data-on-interval (get "/poll") #:duration "5s" #:duration-leading? #t) '(data-on-interval__duration.5s.leading "@get('/poll')")
procedure
(data-on-signal-patch expression #:debounce debounce [ #:debounce-leading? debounce-leading? #:debounce-notrailing? debounce-notrailing?] #:throttle throttle [ #:throttle-noleading? throttle-noleading? #:throttle-trailing? throttle-trailing?] #:delay delay) → list? expression : string? debounce : (or/c string? number?) debounce-leading? : boolean? = #f debounce-notrailing? : boolean? = #f throttle : (or/c string? number?) throttle-noleading? : boolean? = #f throttle-trailing? : boolean? = #f delay : (or/c string? number?)
Leading/trailing timing modifiers require their base value keyword.
Use data-on-signal-patch-filter as a separate helper when you want to apply include/exclude filtering.
> `(div (,(data-on-signal-patch "console.log('patched')"))) '(div ((data-on-signal-patch "console.log('patched')")))
> `(div (,(data-on-signal-patch "console.log('counter changed')" #:debounce "300ms") ,(data-on-signal-patch-filter #:include "/^counter$/")))
'(div
((data-on-signal-patch__debounce.300ms "console.log('counter changed')")
(data-on-signal-patch-filter "{\"include\": \"/^counter$/\"}")))
procedure
(data-on-signal-patch-filter #:include include #:exclude exclude) → list? include : string? exclude : string?
Use this helper when you want to construct the data-on-signal-patch-filter attribute separately from data-on-signal-patch.
> `(div (,(data-on-signal-patch "console.log(patch)") ,(data-on-signal-patch-filter #:include "/^counter$/")))
'(div
((data-on-signal-patch "console.log(patch)")
(data-on-signal-patch-filter "{\"include\": \"/^counter$/\"}")))
attrs can be a single attribute-name string or a list of attribute-name strings.
Preserve open attribute on <details> element:
> `(details (,(data-preserve-attr "open") (open "")) (summary "Title") "Content") '(details ((data-preserve-attr "open") (open "")) (summary "Title") "Content")
Preserve multiple attributes:
> `(details (,(data-preserve-attr '("open" "class")) (open "") (class "custom")) (summary "Title") "Content")
'(details
((data-preserve-attr "open class") (open "") (class "custom"))
(summary "Title")
"Content")
This SDK uses keyed form only (data-ref:signal).
#:case emits Datastar’s __case.* modifier.
> `(div (,(data-ref 'myDiv))) '(div ((data-ref:myDiv "")))
> `(div (,(data-show "$loggedIn")) "Welcome back") '(div ((data-show "$loggedIn")) "Welcome back")
procedure
(data-signals key expression [ #:ifmissing? ifmissing?] #:case case) → list? key : (or/c symbol? string?) expression : string? ifmissing? : boolean? = #f case : case-style/c
When #:ifmissing? is #t, the signal is only set when missing.
#:case emits Datastar’s __case.* modifier.
> `(div (,(data-signals 'count "0"))) '(div ((data-signals:count "0")))
> `(div (,(data-signals 'count "0" #:ifmissing? #t))) '(div ((data-signals:count__ifmissing "0")))
> `(div (,(data-signals "my-signal" "1" #:case 'kebab))) '(div ((data-signals:my-signal__case.kebab "1")))
procedure
(data-signals/hash signals [ #:ifmissing? ifmissing?]) → list? signals : hash? ifmissing? : boolean? = #f
Hash keys must be symbols or strings. Values may be JSON values, expression strings, lists, or nested hashes with symbol/string keys.
Nested hashes produce nested signals.
> `(div (,(data-signals/hash (hash 'count 0 'name "hello")))) '(div ((data-signals "{\"count\":0,\"name\":\"hello\"}")))
> `(div (,(data-signals/hash (hash "theme" "dark")))) '(div ((data-signals "{\"theme\":\"dark\"}")))
> `(div (,(data-signals/hash (hash 'form (hash 'name "" 'email ""))))) '(div ((data-signals "{\"form\":{\"email\":\"\",\"name\":\"\"}}")))
> `(div (,(data-style 'background-color "$dark ? 'black' : 'white'"))) '(div ((data-style:background-color "$dark ? 'black' : 'white'")))
procedure
(data-style/hash styles) → list?
styles : hash?
Hash keys must be symbols or strings. Values may be expression strings, JSON values, or nested hashes with symbol/string keys.
> `(div (,(data-style/hash (hash "display" "$hidden && 'none'" "color" "$error ? 'red' : 'black'"))))
'(div
((data-style
"{\"color\": $error ? 'red' : 'black', \"display\": $hidden && 'none'}")))
> `(span (,(data-text "$count"))) '(span ((data-text "$count")))
2.1.1 Pro Attributes
Use Datastar Pro attribute helpers when your project depends on Pro-only client features.
procedure
(data-animate expression) → list?
expression : string?
procedure
(data-custom-validity expression) → list?
expression : string?
> `(input (,(data-bind "password") ,(data-custom-validity "$password.length < 8 ? 'Must be 8+ characters' : ''")))
'(input
((data-bind:password "")
(data-custom-validity
"$password.length < 8 ? 'Must be 8+ characters' : ''")))
> `(div (,(data-match-media 'is-dark "'prefers-color-scheme: dark'"))) '(div ((data-match-media:is-dark "'prefers-color-scheme: dark'")))
procedure
(data-on-raf expression #:throttle throttle [ #:throttle-noleading? throttle-noleading? #:throttle-trailing? throttle-trailing?]) → list? expression : string? throttle : (or/c string? number?) throttle-noleading? : boolean? = #f throttle-trailing? : boolean? = #f
#:throttle-noleading? and #:throttle-trailing? require #:throttle.
procedure
(data-on-resize expression #:debounce debounce [ #:debounce-leading? debounce-leading? #:debounce-notrailing? debounce-notrailing?] #:throttle throttle [ #:throttle-noleading? throttle-noleading? #:throttle-trailing? throttle-trailing?]) → list? expression : string? debounce : (or/c string? number?) debounce-leading? : boolean? = #f debounce-notrailing? : boolean? = #f throttle : (or/c string? number?) throttle-noleading? : boolean? = #f throttle-trailing? : boolean? = #f
Leading/trailing timing modifiers require their base value keyword.
procedure
(data-persist #:key key #:include include #:exclude exclude [ #:session? session?]) → list? key : (or/c symbol? string?) include : string? exclude : string? session? : boolean? = #f
> `(div (,(data-persist))) '(div ((data-persist "")))
> `(div (,(data-persist #:key 'myapp #:include "/^user\\./" #:session? #t))) '(div ((data-persist:myapp__session "{\"include\": \"/^user\\\\./\"}")))
procedure
(data-query-string #:include include #:exclude exclude [ #:filter? filter? #:history? history?]) → list? include : string? exclude : string? filter? : boolean? = #f history? : boolean? = #f
> `(div (,(data-query-string #:filter? #t #:history? #t))) '(div ((data-query-string__filter__history "")))
procedure
(data-replace-url expression) → list?
expression : string?
> `(div (,(data-replace-url "`/page${page}`"))) '(div ((data-replace-url "`/page${page}`")))
procedure
(data-scroll-into-view [ #:smooth? smooth? #:instant? instant? #:auto? auto? #:hstart? hstart? #:hcenter? hcenter? #:hend? hend? #:hnearest? hnearest? #:vstart? vstart? #:vcenter? vcenter? #:vend? vend? #:vnearest? vnearest? #:focus? focus?]) → list? smooth? : boolean? = #f instant? : boolean? = #f auto? : boolean? = #f hstart? : boolean? = #f hcenter? : boolean? = #f hend? : boolean? = #f hnearest? : boolean? = #f vstart? : boolean? = #f vcenter? : boolean? = #f vend? : boolean? = #f vnearest? : boolean? = #f focus? : boolean? = #f
> (data-scroll-into-view #:smooth? #t #:vcenter? #t) '(data-scroll-into-view__smooth__vcenter "")
procedure
(data-view-transition expression) → list?
expression : string?
> `(div (,(data-view-transition "$transitionName"))) '(div ((data-view-transition "$transitionName")))
2.2 Actions
| (require datastar/sugar/actions) | package: datastar-lib |
Convenience functions for generating Datastar action strings in x-expression templates. These map to the Actions section of the Datastar docs. Also available via (require datastar). If any names conflict with other imports, use (require (prefix-in ds: datastar/sugar/actions)) to prefix just the action helpers.
> (define tid 42)
> `(main ((id "main") ,(data-init (get "/events"))) (form (,(data-on "submit" (post "/todo/create"))) (button (,(data-on "click" (post (format "/todo/delete/~a" tid)))) "Delete")))
'(main
((id "main") (data-init "@get('/events')"))
(form
((data-on:submit "@post('/todo/create')"))
(button ((data-on:click "@post('/todo/delete/42')")) "Delete")))
2.2.1 Signal Actions
Compose action strings that read or update client-side signals.
> (peek "$bar") "@peek($bar)"
> (peek "() => $bar") "@peek(() => $bar)"
procedure
(set-all value #:include include #:exclude exclude) → string? value : string? include : string? exclude : string?
> (set-all "''") "@setAll('')"
> (set-all "''" #:include "/^form\\./") "@setAll('', {include: /^form\\./})"
> (set-all "0" #:include "/.*/" #:exclude "/^_/") "@setAll(0, {include: /.*/, exclude: /^_/})"
procedure
(toggle-all #:include include #:exclude exclude) → string? include : string? exclude : string?
> (toggle-all) "@toggleAll()"
> (toggle-all #:include "/^menu\\./") "@toggleAll({include: /^menu\\./})"
2.2.2 Backend Actions
Send backend requests from the browser and receive Datastar responses. Signals transmit by default.
Handle incoming payloads with HTTP Requests, and return updates with HTTP SSE or HTTP One-Shot Responses. For SSE handlers, configure serve using HTTP Server Setup.
All keyword options are pass-through: explicitly provided values are serialized into the action string, including explicit default-equivalent values.
procedure
(get url #:content-type content-type #:filter-signals-include filter-signals-include #:filter-signals-exclude filter-signals-exclude #:selector selector #:headers headers #:open-when-hidden? open-when-hidden? #:payload payload #:retry retry #:retry-interval retry-interval #:retry-scaler retry-scaler #:retry-max-wait retry-max-wait #:retry-max-count retry-max-count #:request-cancellation request-cancellation) → string? url : string? content-type : (or/c 'json 'form) filter-signals-include : string? filter-signals-exclude : string? selector : string? headers : hash? open-when-hidden? : boolean? payload : string? retry : (or/c 'auto 'error 'always 'never) retry-interval : exact-nonnegative-integer? retry-scaler : number? retry-max-wait : exact-nonnegative-integer? retry-max-count : exact-nonnegative-integer? request-cancellation : (or/c 'auto 'cleanup 'disabled string?)
The #:payload keyword accepts a raw JavaScript expression string. The #:filter-signals-include and #:filter-signals-exclude keywords accept JavaScript regex literal strings (e.g., "/^foo\\./"). For #:request-cancellation, pass one of 'auto, 'cleanup, 'disabled, or a JavaScript expression string that evaluates to an AbortController (e.g., "$controller").
Keyword |
| JS Property |
| Datastar Client Default |
#:content-type |
| contentType |
| 'json |
#:filter-signals-include |
| filterSignals.include |
| /.*/ |
#:filter-signals-exclude |
| filterSignals.exclude |
| /(^_|\._).*/ |
#:selector |
| selector |
| null |
#:headers |
| headers |
| {} |
#:open-when-hidden? |
| openWhenHidden |
| #f for GET, #t for others |
#:payload |
| payload |
| — |
#:retry |
| retry |
| 'auto |
#:retry-interval |
| retryInterval |
| 1000 |
#:retry-scaler |
| retryScaler |
| 2 |
#:retry-max-wait |
| retryMaxWait |
| 30000 |
#:retry-max-count |
| retryMaxCount |
| 10 |
#:request-cancellation |
| requestCancellation |
| 'auto |
> (get "/events") "@get('/events')"
> (get "/events" #:retry 'never) "@get('/events', {retry: 'never'})"
> (get "/endpoint" #:filter-signals-include "/^foo\\./" #:headers (hash "X-Csrf-Token" "mytoken") #:open-when-hidden? #t #:request-cancellation 'disabled) "@get('/endpoint', {filterSignals: {include: /^foo\\./}, headers: {\"X-Csrf-Token\": \"mytoken\"}, openWhenHidden: true, requestCancellation: 'disabled'})"
> (get "/endpoint" #:request-cancellation "$controller") "@get('/endpoint', {requestCancellation: $controller})"
procedure
(post url #:content-type content-type #:filter-signals-include filter-signals-include #:filter-signals-exclude filter-signals-exclude #:selector selector #:headers headers #:open-when-hidden? open-when-hidden? #:payload payload #:retry retry #:retry-interval retry-interval #:retry-scaler retry-scaler #:retry-max-wait retry-max-wait #:retry-max-count retry-max-count #:request-cancellation request-cancellation) → string? url : string? content-type : (or/c 'json 'form) filter-signals-include : string? filter-signals-exclude : string? selector : string? headers : hash? open-when-hidden? : boolean? payload : string? retry : (or/c 'auto 'error 'always 'never) retry-interval : exact-nonnegative-integer? retry-scaler : number? retry-max-wait : exact-nonnegative-integer? retry-max-count : exact-nonnegative-integer? request-cancellation : (or/c 'auto 'cleanup 'disabled string?)
> (post "/submit" #:content-type 'form #:selector "#myForm") "@post('/submit', {contentType: 'form', selector: \"#myForm\"})"
procedure
(put url #:content-type content-type #:filter-signals-include filter-signals-include #:filter-signals-exclude filter-signals-exclude #:selector selector #:headers headers #:open-when-hidden? open-when-hidden? #:payload payload #:retry retry #:retry-interval retry-interval #:retry-scaler retry-scaler #:retry-max-wait retry-max-wait #:retry-max-count retry-max-count #:request-cancellation request-cancellation) → string? url : string? content-type : (or/c 'json 'form) filter-signals-include : string? filter-signals-exclude : string? selector : string? headers : hash? open-when-hidden? : boolean? payload : string? retry : (or/c 'auto 'error 'always 'never) retry-interval : exact-nonnegative-integer? retry-scaler : number? retry-max-wait : exact-nonnegative-integer? retry-max-count : exact-nonnegative-integer? request-cancellation : (or/c 'auto 'cleanup 'disabled string?)
procedure
(patch url #:content-type content-type #:filter-signals-include filter-signals-include #:filter-signals-exclude filter-signals-exclude #:selector selector #:headers headers #:open-when-hidden? open-when-hidden? #:payload payload #:retry retry #:retry-interval retry-interval #:retry-scaler retry-scaler #:retry-max-wait retry-max-wait #:retry-max-count retry-max-count #:request-cancellation request-cancellation) → string? url : string? content-type : (or/c 'json 'form) filter-signals-include : string? filter-signals-exclude : string? selector : string? headers : hash? open-when-hidden? : boolean? payload : string? retry : (or/c 'auto 'error 'always 'never) retry-interval : exact-nonnegative-integer? retry-scaler : number? retry-max-wait : exact-nonnegative-integer? retry-max-count : exact-nonnegative-integer? request-cancellation : (or/c 'auto 'cleanup 'disabled string?)
procedure
(delete url #:content-type content-type #:filter-signals-include filter-signals-include #:filter-signals-exclude filter-signals-exclude #:selector selector #:headers headers #:open-when-hidden? open-when-hidden? #:payload payload #:retry retry #:retry-interval retry-interval #:retry-scaler retry-scaler #:retry-max-wait retry-max-wait #:retry-max-count retry-max-count #:request-cancellation request-cancellation) → string? url : string? content-type : (or/c 'json 'form) filter-signals-include : string? filter-signals-exclude : string? selector : string? headers : hash? open-when-hidden? : boolean? payload : string? retry : (or/c 'auto 'error 'always 'never) retry-interval : exact-nonnegative-integer? retry-scaler : number? retry-max-wait : exact-nonnegative-integer? retry-max-count : exact-nonnegative-integer? request-cancellation : (or/c 'auto 'cleanup 'disabled string?)
2.2.3 Pro Actions
Use Datastar Pro actions for clipboard, interpolation, and internationalization helpers.
> (clipboard "'Hello'") "@clipboard('Hello')"
> (clipboard "'SGVsbG8='" #:base64? #t) "@clipboard('SGVsbG8=', true)"
procedure
(fit v old-min old-max new-min new-max #:clamp? clamp? #:round? round?) → string? v : string? old-min : number? old-max : number? new-min : number? new-max : number? clamp? : boolean? round? : boolean?
Omitting both keywords emits the 5-argument form. Passing only #:clamp? emits one extra argument. Passing only #:round? emits false as the positional clamp placeholder before the round value.
> (fit "$val" 0 100 0 1) "@fit($val, 0, 100, 0, 1)"
> (fit "$x" 0 255 0 1 #:clamp? #t) "@fit($x, 0, 255, 0, 1, true)"
> (fit "$x" 0 100 0 10 #:clamp? #t #:round? #t) "@fit($x, 0, 100, 0, 10, true, true)"
procedure
(intl type value #:options options #:locale locale) → string? type : string? value : string? options : hash? locale : string?
> (intl "'number'" "$price") "@intl('number', $price)"
> (intl "'number'" "$price" #:options (hash 'style "currency" 'currency "USD")) "@intl('number', $price, {\"currency\": \"USD\", \"style\": \"currency\"})"
> (intl "'datetime'" "$date" #:options (hash 'dateStyle "full") #:locale "'en-US'") "@intl('datetime', $date, {\"dateStyle\": \"full\"}, 'en-US')"
2.2.4 Chaining Actions
Compose larger action expressions by joining smaller action strings.
All parts must be strings; non-string values raise an argument error.
> (chain "$loading = true" (post "/search")) "$loading = true; @post('/search')"
> (chain "$a = 1" "$b = 2" "$c = 3") "$a = 1; $b = 2; $c = 3"
All parts must be strings; non-string values raise an argument error. Result keeps JavaScript short-circuit behavior.
> (chain/and "$canSubmit" (post "/submit")) "$canSubmit && @post('/submit')"
> (chain/and "$isReady" "$hasToken" "$canSync") "$isReady && $hasToken && $canSync"