dependenciesorg.clojure/clojure |
| 1.7.0 | org.clojure/clojurescript |
| 1.7.170 | org.clojure/core.async |
| 0.2.374 | keechma |
| 0.1.0-SNAPSHOT | reagent |
| 0.6.0-alpha |
| (this space intentionally left almost blank)
|
|
|
| |
| (ns keechma-counter.main-component
(:require [keechma.ui-component :as ui]))
|
Increments the counter if the current value is odd.
| (defn inc-if-odd
[ctx counter-val]
(when (odd? counter-val)
(ui/send-command ctx :inc)))
|
Increments the counter after 1 second.
| (defn inc-async
[ctx]
(.setTimeout js/window #(ui/send-command ctx :inc) 1000))
|
Main renderer function. ctx argument is partially applied when
the application is started.
First we resolve the counter-sub subscription which will hold
the current counter value.
User can do one of four actions:
- Increment the counter
- Decrement the counter
- Increment the counter if the current value is odd
- Increment the counter in async way (after 1 second)
Each of these actions sends the command to the controller
by calling the `(ui/send-command ctx :command) function.
| (defn render
[ctx]
(let [counter-sub (ui/subscription ctx :counter-value)]
(fn []
[:p
(str "Clicked: " @counter-sub " times ")
[:button {:on-click #(ui/send-command ctx :inc)} "+"]
" "
[:button {:on-click #(ui/send-command ctx :dec)} "-"]
" "
[:button {:on-click #(inc-if-odd ctx @counter-sub)} "Increment if odd"]
" "
[:button {:on-click #(inc-async ctx)} "Increment async"]])))
|
Definition of the component. This component depends on one subscription:
counter-value . This subscription will be resolved on the record when the
application is started.
After that the record will be partially applied to the :renderer function
which will allow it to resolve it from the function body and read the value.
| (def component
(ui/constructor {:renderer render
:subscription-deps [:counter-value]}))
|
| |
| |
| (ns keechma-counter.core
(:require [keechma-counter.counter-controller :as counter]
[keechma-counter.main-component :as main-component]
[keechma.app-state :as app-state])
(:require-macros [reagent.ratom :refer [reaction]]))
|
| (enable-console-print!)
|
Subscription that returns the current value of the counter.
| (defn counter-value-sub
[app-state]
(reaction
(get-in @app-state [:kv :counter])))
|
Definition of the application.
:controllers param holds all of the controllers needed to run the app
- Counter controller is registered under the
:counter key. Main component
has the :counter :topic assoc-ed to it which allows it to send the
commands to the Counter controller.
:component param holds all the component needed to render the app
:subscriptions param holds the application subscriptions
| (def app-definition
{:controllers {:counter (counter/->Controller)}
:components {:main (assoc main-component/component :topic :counter)}
:subscriptions {:counter-value counter-value-sub}
:html-element (.getElementById js/document "app")})
|
| (defonce running-app (clojure.core/atom))
|
Helper function that starts the application.
| (defn start-app!
[]
(reset! running-app (app-state/start! app-definition)))
|
Helper function that restarts the application whenever the
code is hot reloaded.
| (defn restart-app!
[]
(let [current @running-app]
(if current
(app-state/stop! current start-app!)
(start-app!))))
|
| (restart-app!)
|
| (defn on-js-reload []
;; optionally touch your app-state to force rerendering depending on
;; your application
;; (swap! app-state update-in [:__figwheel_counter] inc))
|
| |
| |
| (ns keechma-counter.counter-controller
(:require [keechma.controller :as controller]
[cljs.core.async :refer [<!]])
(:require-macros [cljs.core.async.macros :refer [go]]))
|
Implements the counter controller.
params function returns true because this controller should be always running.
start function sets the default counter value (0). :kv is used to store any key - value pairs
handler function is waiting for commands on the in-chan . When the command comes (if it's :inc or :dec ) it will increment or decrement the counter.
| (defrecord
Controller []
controller/IController
(params [_ _] true)
(start [_ params app-db]
(assoc-in app-db [:kv :counter] 0))
(handler [_ app-db-atom in-chan _]
(controller/dispatcher app-db-atom in-chan
{:inc #(swap! app-db-atom update-in [:kv :counter] inc)
:dec #(swap! app-db-atom update-in [:kv :counter] dec)})))
|
| |