Example of Domino with re-frame
(require '[domino.core :as domino])
(require '[reagent.core :as reagent])
(require '[reagent.dom :as reagent-dom])
(require '[re-frame.core :as rf])
(require '[goog.string :as string])
(require '[goog.string.format])
(require '[cljs.pprint :refer [pprint]])
;;initialize the Domino context using the supplied schema
(rf/reg-event-db
:init
(fn [_ [_ schema]]
(domino/initialize schema)))
;;trigger effects with the provided ids
(rf/reg-event-db
:trigger-effects
(fn [ctx [_ effect-ids]]
(domino/trigger-effects ctx effect-ids)))
;;dispatch an input event
(rf/reg-event-db
:event
(fn [ctx [_ id value]]
(domino/transact ctx [[(get-in (::domino/model ctx) [:id->path id]) value]])))
;;subscribe to the value at the given id
(rf/reg-sub
:id
(fn [ctx [_ id]]
(get-in (::domino/db ctx) (get-in (::domino/model ctx) [:id->path id]))))
;;returns Domino db
(rf/reg-sub
:db
(fn [ctx _]
(::domino/db ctx)))
(defn parse-float [s]
(let [value (js/parseFloat s)]
(when-not (js/isNaN value) value)))
(defn format-number [n]
(when n (string/format "%.2f" n)))
(defn text-input [label id]
[:div
[:label label]
[:input
{:type :text
:value @(rf/subscribe [:id id])
:on-change #(rf/dispatch [:event id (-> % .-target .-value)])}]])
(defn numeric-input [label id]
(reagent/with-let [value (reagent/atom nil)]
[:div
[:label label]
[:input
{:type :text
:value @value
:on-focus #(reset! value @(rf/subscribe [:id id]))
:on-blur #(rf/dispatch [:event id (parse-float @value)])
:on-change #(reset! value (-> % .-target .-value))}]]))
;;initialize Domino
(rf/dispatch-sync
[:init
{:model
[[:demographics
[:first-name {:id :first-name}]
[:last-name {:id :last-name}]
[:full-name {:id :full-name}]]
[:vitals
[:height {:id :height}]
[:weight {:id :weight}]
[:bmi {:id :bmi}]]
[:counter {:id :counter}]]
:effects
[{:id :increment
:outputs [:counter]
:handler (fn [_ state]
(update state :counter (fnil inc 0)))}
{:inputs [:full-name]
:handler (fn [_ {:keys [full-name]}]
(when (= "Bobberton, Bob" full-name)
(js/alert "Hi Bob!")))}]
:events
[{:inputs [:first-name :last-name]
:outputs [:full-name]
:handler (fn [_ {:keys [first-name last-name]} _]
{:full-name (or (when (and first-name last-name)
(str last-name ", " first-name))
first-name
last-name)})}
{:inputs [:height :weight]
:outputs [:bmi]
:handler (fn [_ {:keys [height weight]} {:keys [bmi]}]
{:bmi (if (and height weight)
(/ weight (* height height))
bmi)})}]}])
;;render the UI
(defn home-page []
[:div
[:h3 "Patient demographics"]
[text-input "First name" :first-name]
[text-input "Last name" :last-name]
[numeric-input "Height (M)" :height (fnil js/parseFloat 0)]
[numeric-input "Weight (KG)" :weight (fnil js/parseFloat 0)]
[:button
{:on-click #(rf/dispatch [:trigger-effects [:increment]])}
"increment count"]
[:p>label "Full name " @(rf/subscribe [:id :full-name])]
[:p>label "BMI " (format-number @(rf/subscribe [:id :bmi]))]
[:p>label "Counter " @(rf/subscribe [:id :counter])]
[:hr]
[:h4 "DB state"]
[:pre (with-out-str (pprint @(rf/subscribe [:db])))]])
(reagent-dom/render [home-page] js/klipse-container)