Weave provides JavaScript interoperability through Squint, a lightweight Clojure-to-JavaScript transpiler. This allows you to write Clojure code that gets converted to JavaScript for client-side execution.
Weave uses Squint to:
This approach gives you the expressiveness of Clojure with direct access to browser capabilities.
There are several ways to use JavaScript in Weave:
push-script!The simplest way to execute JavaScript is with push-script!:
(weave/push-script!
(squint/clj->js
(js/alert "Hello from Clojure!")))
This transpiles the Clojure code to JavaScript and sends it to the current browser tab for execution.
To send JavaScript to all connected browser tabs for the current user:
(weave/broadcast-script!
(squint/clj->js
(js/console.log "This appears in all tabs")))
You can combine DOM updates with JavaScript execution:
{:data-on-click
(weave/handler []
;; Update the DOM
(weave/push-html! [:div#status "Processing..."])
;; Execute JavaScript
(weave/push-script!
(squint/clj->js
(let [result (js/fetch "/api/data")]
(.then result #(.json %))
(.then result #(js/console.log "Data received:" %))
(.catch result #(js/console.error "Error:" %))))))}
You can directly manipulate the DOM:
(weave/push-script!
(squint/clj->js
(let [element (js/document.getElementById "counter")]
(set! (.-textContent element)
(inc (js/parseInt (.-textContent element)))))))
clj->js MacroThe clj->js macro is the primary tool for JavaScript interoperability:
(weave/push-script!
(squint/clj->js
(defn greet [name]
(js/alert (str "Hello, " name "!")))
(greet "World")))
This transpiles the Clojure code to JavaScript and executes it in the browser.
The clj->js macro accepts an optional map of options:
(weave/push-script!
(clj->js
{:elide-imports true
:elide-exports true
:top-level false
:context :expr
:core-alias "squint.core"}
(defn advanced-example []
(js/console.log "Custom options"))
(advanced-example)))
While Squint provides excellent JavaScript interoperability, it's important to understand its limitations:
Here's a complete example of a timer application using JavaScript interoperability:
(defn timer-view []
[:div.p-6
[:h1#timer.text-4xl.font-bold "0"]
[:div.flex.gap-2.mt-4
[:button.bg-green-500.text-white.px-4.py-2.rounded
{:data-on-click
(weave/handler []
(weave/push-script!
(squint/clj->js
(let [interval-id (js/setInterval
(fn []
(let [timer (js/document.getElementById "timer")
current (js/parseInt (.-textContent timer))]
(set! (.-textContent timer) (inc current))))
1000)]
(set! (.. js/window -weaveTimerId) interval-id)))))}
"Start"]
[:button.bg-red-500.text-white.px-4.py-2.rounded
{:data-on-click
(weave/handler []
(weave/push-script!
(squint/clj->js
(when (.. js/window -weaveTimerId)
(js/clearInterval (.. js/window -weaveTimerId))
(set! (.. js/window -weaveTimerId) nil)))))}
"Stop"]
[:button.bg-blue-500.text-white.px-4.py-2.rounded
{:data-on-click
(weave/handler []
(weave/push-script!
(squint/clj->js
(let [timer (js/document.getElementById "timer")]
(set! (.-textContent timer) "0")))))}
"Reset"]]])
This example demonstrates:
Can you improve this documentation?Edit on GitHub
cljdoc builds & hosts documentation for Clojure/Script libraries
| Ctrl+k | Jump to recent docs |
| ← | Move to previous article |
| → | Move to next article |
| Ctrl+/ | Jump to the search field |