ClojureScript
The angular-ts-cljs Maven artifact provides the angular-ts.core API and the
Closure externs needed by an optimized ClojureScript build. Keep it on the same
version as the AngularTS runtime loaded by the page.
Before you start
Install Java 21, Node.js, and Shadow CLJS. Create a project with
src/main/todo/app.cljs, shadow-cljs.edn, and an HTML entry page.
Configure Shadow CLJS
Add the Maven artifact and tell Closure where the packaged extern file is:
{:source-paths ["src/main"]
:dependencies [[io.github.angular-wave/angular-ts-cljs "0.37.0"]]
:builds
{:app {:target :browser
:output-dir "public/js"
:asset-path "/js"
:modules {:app {:entries [todo.app]}}
:compiler-options
{:externs ["angular_ts/externs/angular.js"]
:infer-externs true
:warnings-as-errors true}}}}
Keep :warnings-as-errors true; extern or type-tag drift should stop the build
instead of producing renamed runtime calls.
Register the application
Use angular-ts.core for fluent module registration. Dependency names stay
explicit because optimized ClojureScript function names are not injectable
names.
(ns todo.app
(:require [angular-ts.core :as ng]
[goog.object :as gobj]))
(defn create-model []
(js-obj "newTodo" "" "tasks" #js []))
(defn create-controller [model]
(gobj/set model "add" #(js/console.log "add"))
model)
(defonce app
(-> (ng/create-module "todo" [])
(ng/model "todoModel" [] create-model)
(ng/controller "TodoCtrl" ["todoModel"] create-controller)))
Use JavaScript objects and arrays at the framework boundary. Keep persistent Clojure collections inside domain code and convert them once when assigning a template-visible value.
Load and start the application
Load AngularTS before the compiled module and bootstrap after both are ready:
<main id="app" ng-controller="TodoCtrl as ctrl"></main>
<script src="angular-ts.umd.js"></script>
<script src="/js/app.js"></script>
<script>
angular.bootstrap(document.getElementById('app'), ['todo']);
</script>
Build with npx shadow-cljs release app. Serve public over HTTP.
Production practices
- Prefer the fluent facade; use the lower-level namespace only when no helper exists.
- Keep
*warn-on-infer*enabled and fix every inference warning. - Use explicit injection vectors for controllers, services, directives, and configuration blocks.
- Load one AngularTS runtime even when several ClojureScript modules share the page.
- Compile and test with Closure ADVANCED optimization before release.
Complete example
Use integrations/closure/clojurescript/demo as a complete Shadow CLJS todo
project, or browse all integration examples.
Feedback
Was this page helpful?
Glad to hear it! Please tell us how we can improve.
Sorry to hear that. Please tell us how we can improve.