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)