@@ -989,7 +989,7 @@ NOTE: `:duct/logger` is often defined as an optional dependency, via a
989
989
*refset*. Without explicitly specifying this as one of the keys, the
990
990
migrator will run without logging.
991
991
992
- === Database-Driven Todos
992
+ === Database Integration
993
993
994
994
Now that we have a database table and a web server, it's time to put the
995
995
two together. The database we pass to the index function can be used to
@@ -1102,6 +1102,92 @@ The second addition is the `new-todo` function. This inserts a new row
1102
1102
into the todo table, then returns a "`303 See Other`" response that will
1103
1103
redirect the browser back to the index page.
1104
1104
1105
- If we reset via the REPL and check http://localhost:3000/, you should
1105
+ If you reset via the REPL and check http://localhost:3000/, you should
1106
1106
see a text input box at the bottom of the todo list, allowing more todo
1107
1107
items to be added.
1108
+
1109
+ === ClojureScript
1110
+
1111
+ At this point we're hitting the limitations of what we can do with HTML
1112
+ alone. JavaScript allows for more sophisticated user interaction, and in
1113
+ the Clojure ecosystem we have _ClojureScript_, a version of Clojure that
1114
+ compiles to JavaScript.
1115
+
1116
+ You be unsurprised to learn that Duct has a module for compiling
1117
+ ClojureScript. As always we begin with our dependencies, and add the
1118
+ '`cljs`' module.
1119
+
1120
+ .deps.edn
1121
+ [,clojure]
1122
+ ----
1123
+ {:deps {org.clojure/clojure {:mvn/version "1.12.0"}
1124
+ org.duct-framework/main {:mvn/version "0.1.5"}
1125
+ org.duct-framework/module.cljs {:mvn/version "0.5.0"}
1126
+ org.duct-framework/module.logging {:mvn/version "0.6.5"}
1127
+ org.duct-framework/module.web {:mvn/version "0.12.0"}
1128
+ org.duct-framework/module.sql {:mvn/version "0.7.1"}
1129
+ org.xerial/sqlite-jdbc {:mvn/version "3.47.0.0"}
1130
+ com.github.seancorfield/next.jdbc {:mvn/version "1.3.955"}}
1131
+ :aliases {:duct {:main-opts ["-m" "duct.main"]}}}
1132
+ ----
1133
+
1134
+ As before, we can load these dependencies by either restarting the REPL,
1135
+ or by using the `(sync-deps)` command.
1136
+
1137
+ Next, the `:duct.module/cljs` key needs to be added to the Duct
1138
+ configuration file.
1139
+
1140
+ .duct.edn
1141
+ [,clojure]
1142
+ ----
1143
+ {:vars {jdbc-url {:default "jdbc:sqlite:todo.db"}}
1144
+ :system
1145
+ {:duct.module/logging {}
1146
+ :duct.module/sql {}
1147
+ :duct.module/cljs
1148
+ {:builds {:client todo.client}}
1149
+ :duct.module/web
1150
+ {:features #{:site}
1151
+ :handler-opts {:db #ig/ref :duct.database/sql}
1152
+ :routes [["/" {:get :todo.routes/index
1153
+ :post :todo.routes/new-todo}]]}}}
1154
+ ----
1155
+
1156
+ The module requires a `:builds` option to be set. This connects a
1157
+ build name to a ClojureScript namespace, or collection of namespaces. In
1158
+ the above example, the `todo.client` namespace will be compiled to the
1159
+ `target/cljs/client.js` JavaScript file. When Duct is started, this will
1160
+ be accessible at: <http://localhost:3000/cljs/client.js>.
1161
+
1162
+ Before `todo.client` can be compiled, we first need to write it. In
1163
+ order to check everything works, we'll have it trigger an JavaScript
1164
+ alert.
1165
+
1166
+ .src/todo/client.cljs
1167
+ [,clojure]
1168
+ ----
1169
+ (ns todo.client)
1170
+
1171
+ (js/alert "Hello World")
1172
+ ----
1173
+
1174
+ In order to test this script compiles correct, we'll add the script to
1175
+ our `index` function in the `todo.routes` namespace.
1176
+
1177
+ [,clojure]
1178
+ ----
1179
+ (defn index [{:keys [db]}]
1180
+ (fn [_request]
1181
+ [:html {:lang "en"}
1182
+ [:head
1183
+ [:title "Todo"]
1184
+ [:script {:src "/cljs/client.js"}]]
1185
+ [:body
1186
+ [:ul
1187
+ (for [rs (jdbc/execute! db [list-todos])]
1188
+ [:li (:todo/description rs)])
1189
+ [:li (create-todo-form)]]]]))
1190
+ ----
1191
+
1192
+ If you restart the REPL and check http://localhost:3000, you should see
1193
+ the alert.
0 commit comments