Skip to content

Instantly share code, notes, and snippets.

@anmonteiro
Created January 12, 2016 21:03
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save anmonteiro/72ec13f94446936edb09 to your computer and use it in GitHub Desktop.
Save anmonteiro/72ec13f94446936edb09 to your computer and use it in GitHub Desktop.
Composite with mutations & path optimization
(def composite-data
{:composite/item {:id 0
:width 400
:height 400
:color "#428BCA"
:value 0
:children [{:id 1
:width 200
:height 200
:color "#9ACD32"
:value 0
:children [{:id 3
:width 100
:height 100
:color "#CD329A"
:value 0}
{:id 4
:width 100
:height 100
:color "#32CD65"
:value 0}]}
{:id 2
:width 200
:height 200
:color "#39DBBE"
:value 0}]}})
(declare component)
(defn display-id [this]
(let [{:keys [id value children]} (om/props this)
type (if children :composite :leaf)]
(dom/div #js {:style #js {:position "absolute"
:textAlign "right"
:bottom 0
:zIndex 1
:right 5}}
(dom/span nil
(str "id: "id " value: " value)
(dom/button #js {:onClick #(om/transact! this
`[(comp/inc ~{:id id :type type})])}
"+")))))
(defn common-div [this props & children]
(let [{:keys [id width height color value]} props]
(dom/div #js {:className (str id)
:style
#js {:position "relative"
:float "left"
:width width
:height height
:zIndex 2
:textAlign "center"
:backgroundColor color}}
children
(display-id this))))
(defui Composite
static om/Ident
(ident [this {:keys [id children]}]
(if-not (nil? children)
[:composite id]
[:leaf id]))
static om/IQuery
(query [this]
'[:id :width :height :color :value {:children ...}])
Object
(render [this]
(let [{:keys [children] :as props} (om/props this)]
(common-div this props (map component children)))))
(def composite (om/factory Composite))
(defui Leaf
static om/Ident
(ident [this {:keys [id children]}]
(if-not (nil? children)
[:composite id]
[:leaf id]))
static om/IQuery
(query [this]
'[:id :width :height :color :value])
Object
(render [this]
(common-div this (om/props this))))
(def leaf (om/factory Leaf))
(defui Component
static om/Ident
(ident [this {:keys [id children]}]
(if-not (nil? children)
[:composite id]
[:leaf id]))
static om/IQuery
(query [this]
{:leaf (om/get-query Leaf)
:composite (om/get-query Composite)})
Object
(render [this]
(let [{:keys [id] :as props} (om/props this)
[type id] (om/get-ident this)]
(({:composite composite
:leaf leaf} type) props))))
(def component (om/factory Component))
(defui CompositeApp
static om/IQuery
(query [this]
[{:composite/item (om/get-query Component)}])
Object
(render [this]
(let [{:keys [composite/item]} (om/props this)]
(dom/div #js {:style #js {:margin "0 auto"
:display "table"}}
(component item)
(dom/div #js {:style #js {:clear "both"}})))))
(defmulti composite-read
(fn [{:keys [ast]} k _]
;(println k ast)
k)) ;; DEBUG
(defmethod composite-read :default
[{:keys [data] :as env} k _]
{:value (get data k)})
(defmethod composite-read :children
[{:keys [parser data union-query state] :as env} k _]
(let [st @state
f #(parser (assoc env :data (get-in st %)) ((first %) union-query))]
{:value (into [] (map f) (:children data))}))
(defmethod composite-read :leaf
[{:keys [state query query-root] :as env} k _]
{:value (om/db->tree query query-root @state)})
(defmethod composite-read :composite
[{:keys [state query query-root] :as env} k _]
{:value (om/db->tree (:composite query) query-root @state)})
(defmethod composite-read :composite/item
[{:keys [state parser query ast] :as env} k _]
(println "query " query)
(let [st @state
[type id :as entry] (get st k)
data (get-in st entry)
new-env (assoc env :data data :union-query query)]
{:value (parser new-env (type query))}))
(defmulti composite-mutate om/dispatch)
(defmethod composite-mutate 'comp/inc
[{:keys [state]} k {:keys [id type]}]
{:action #(swap! state update-in [type id :value] inc)})
(def composite-reconciler
(om/reconciler {:state composite-data
:parser (om/parser {:read composite-read :mutate composite-mutate})
:pathopt true}))
(om/add-root! composite-reconciler CompositeApp (js/document.getElementById "app"))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment