Skip to content

Instantly share code, notes, and snippets.

@griff
Created January 13, 2016 15:34
Show Gist options
  • Save griff/e2bd4b41bc9f3fee66fe to your computer and use it in GitHub Desktop.
Save griff/e2bd4b41bc9f3fee66fe to your computer and use it in GitHub Desktop.
First transaction render
(ns om-tutorial.core
(:require [goog.dom :as gdom]
[om.next :as om :refer-macros [defui]]
[om.dom :as dom]))
(enable-console-print!)
(def init-data
{:list/one {:modal {:visible false}
:list [{:name "John" :points 0 :manager [:person/by-name "Jeff"] :employees []}
{:name "Mary" :points 0 :employees []}
{:name "Bob" :points 0 :employees []}]}
:list/two {:modal {:visible false}
:list [{:name "Mary" :points 0 :age 27 :employees []}
{:name "Gwen" :points 0 :employees []}
{:name "Jeff" :points 0 :employees [{:name "John"}]}]}})
(defmulti read om/dispatch)
#_(defn get-person [env key]
(let [st @state
p (get-in st key)]
(assoc p (om/parser parser))))
(defn get-people [state key]
(let [st @state]
(into [] (map #(get-in st %)) (get st key))))
(defmethod read :person/by-name
[{:keys [state query query/root] :as env} key params]
(do #_(.apply (.-log js/console) js/console (into-array ["PersonByName" env key]))
{:value (om/db->tree query root @state)}))
(defmethod read :list/one
[{:keys [state query query/root] :as env} key params]
(let [st @state]
#_(.apply (.-log js/console) js/console (into-array ["List one" key query root]))
{:value (om/db->tree query (:list/one st) st)}))
(defmethod read :list/two
[{:keys [state query query/root] :as env} key params]
(do
#_(.apply (.-log js/console) js/console (into-array ["List two" key query root]))
(let [st @state]
{:value (om/db->tree query (:list/two st) st)})))
(defmulti mutate om/dispatch)
(defmethod mutate 'points/increment
[{:keys [state path]} _ {:keys [name]}]
{:action
(fn []
(swap! state update-in
[:person/by-name name :points]
inc))})
(defmethod mutate 'points/decrement
[{:keys [state path]} _ {:keys [name]}]
{:action
(fn []
(swap! state update-in
[:person/by-name name :points]
#(let [n (dec %)] (if (neg? n) 0 n))))})
(defmethod mutate 'modal/close
[{:keys [state] :as inp} k {:keys [path] :as muh} ]
{:value {:keys [:list/one]}
:action (fn []
(swap! state update-in
(concat path [:visible])
(constantly false)))})
(defmethod mutate 'modal/open
[{:keys [state] :as inp} k {:keys [path] :as muh} ]
{:value {:keys [:list/one]}
:action
(fn []
(swap! state update-in
(concat path [:visible])
(constantly true)))})
(declare list-view)
#_(defn all-points [person]
(let [{:keys [points employees]} person]
(reduce + points (map all-points employees))))
(defui Person
static om/Ident
(ident [this {:keys [name]}]
[:person/by-name name])
static om/IQuery
(query [this]
'[:name :points (get test) :age])
Object
(render [this]
(println "Render Person" (-> this om/props :name) (count (-> this om/props :employees)))
(let [{:keys [name points] :as props} (om/props this)]
(dom/li nil
(dom/label nil (str name ", points: " points))
(dom/button
#js {:onClick
(fn [e]
(om/transact! this
`[(points/increment ~props)]))}
"+")
(dom/button
#js {:onClick
(fn [e]
(om/transact! this
`[(points/decrement ~props)]))}
"-")
#_(list-view employees)))))
(def person (om/factory Person {:keyfn :name}))
(defui Modal
static om/IQuery
(query [this]
'[:visible])
Object
(render [this]
(let [{:keys [visible] :as props} (om/props this)
{:keys [header footer close-handler]} (om/get-computed this)
classes {:modal true
:fade true
:in visible}]
(println "Render Modal" (om/path this))
(dom/div #js {:className "dialog"}
(when visible
(dom/div #js {:className "modal-backdrop fade in"}))
(dom/div #js {:className "modal fade in" :style #js {:display (if visible "block" "none")}}
(dom/div #js {:style #js {:top 0
:right 0
:bottom 0
:left 0
:position "absolute"}
:onClick #(when close-handler (close-handler % this))})
(dom/div #js {:className "modal-dialog"}
(dom/div #js {:className "modal-content"}
(dom/div #js {:className "modal-header"}
(when close-handler
(dom/button
#js{:type "button"
:className "close"
:aria-hidden true
:onClick #(close-handler % this)}
"×"))
(dom/h4 #js {:className "modal-title"} header))
(dom/div #js {:className "modal-body"}
(om/children this))
(dom/div #js {:className "modal-footer"}
footer))))))))
(def modal (om/factory Modal))
(defui ListView
Object
(render [this]
(println "Render ListView" (-> this om/path))
(let [list (om/props this)]
(apply dom/ul nil
(map person list)))))
(defn- compute-react-key [props]
(if-let [rk (:react-key props)]
rk
(if-let [idx (-> props meta :om-path)]
idx
js/undefined)))
(def list-view (om/factory ListView {:keyfn compute-react-key}))
(defui RootView
static om/IQuery
(query [this]
(let [subquery (om/get-query Person)
modal (om/get-query Modal)]
`[{:list/one [{:modal ~modal} {:list ~subquery}]}
{:list/two [{:modal ~modal} {:list ~subquery}]}]))
Object
(render [mis]
(let [{:keys [list/one list/two]} (om/props mis)]
#_(println "Render RootView" one two)
(dom/div nil
(dom/button #js {:onClick (fn [_] (om/transact! mis `[(modal/open {:path [:list/one :modal]})])) :type "button"} "Show List Muh")
(dom/button #js {:onClick (fn [_] (om/transact! mis `[(modal/open {:path [:list/two :modal]})])) :type "button"} "Show List B")
(modal (om/computed (:modal one) {:header "List Muh"
:close-handler (fn [_ m] (om/transact! mis `[(modal/close {:path ~(om/path m)})]))})
(list-view (:list one)))
(modal (om/computed (:modal two) {:header "List B"
:close-handler (fn [_ m] (om/transact! mis `[(modal/close {:path ~(om/path m)})]))})
(list-view (:list two)))))))
(def parser (om/parser {:read read :mutate mutate}))
(def reconciler
(om/reconciler
{:state init-data
:parser parser}))
(om/add-root! reconciler
RootView (gdom/getElement "app"))
(def norm-data (om/tree->db RootView init-data true))
(comment
(in-ns 'om-tutorial.core)
(require '[cljs.pprint :as pp])
(pp/pprint norm-data)
(parser {:state (atom norm-data)} '[{:list/two [:name {:employees ...}]}])
(parser {:state (atom norm-data)} '[[:person/by-name "Jeff"]])
)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment