Skip to content

Instantly share code, notes, and snippets.

@anmonteiro
Last active January 18, 2016 20:53
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/085d3d0636a3bc14f9f7 to your computer and use it in GitHub Desktop.
Save anmonteiro/085d3d0636a3bc14f9f7 to your computer and use it in GitHub Desktop.
tempids + Simulated server
(def init-data
{:list/one [{:id 0 :name "John" :points 0}
{:id 1 :name "Mary" :points 0}
{:id 2 :name "Bob" :points 0}]
:list/two [{:id 1 :name "Mary" :points 0 :age 27}
{:id 3 :name "Gwen" :points 0}
{:id 4 :name "Jeff" :points 0}]})
;; =============================================================================
;; Parsing
(declare reconciler)
(defmulti read om/dispatch)
(defn get-people [state key]
(let [st @state]
(into [] (map #(get-in st %)) (get st key))))
(defmethod read :list/one
[{:keys [state] :as env} key params]
{:value (get-people state key)})
(defmethod read :list/two
[{:keys [state] :as env} key params]
{:value (get-people state key)})
(declare Person)
(defmulti mutate om/dispatch)
(defmethod mutate 'person/add!
[{:keys [state ast] :as env} _ {:keys [new-person lista]}]
(.log js/console env)
{:value {:keys []}
:action #(do
(swap! state update-in [:person/by-id] merge {(:id new-person) new-person})
(swap! state update-in [lista] conj [:person/by-id (:id new-person)]))
:remote (assoc ast :params new-person)})
(defmethod mutate 'points/increment
[{:keys [state]} _ {:keys [id]}]
{:action
(fn []
(swap! state update-in
[:person/by-id id :points]
inc))})
(defmethod mutate 'points/decrement
[{:keys [state]} _ {:keys [id]}]
{:action
(fn []
(swap! state update-in
[:person/by-id id :points]
#(let [n (dec %)] (if (neg? n) 0 n))))})
;; =============================================================================
;; Components
(defui Person
static om/Ident
(ident [this {:keys [id]}]
[:person/by-id id])
static om/IQuery
(query [this]
'[:id :name :points :age])
Object
(render [this]
(let [{:keys [points name foo] :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)]))}
"-")))))
(def person (om/factory Person {:keyfn :id}))
(defn on-change [this e]
(om/update-state! this assoc :person (.. e -target -value)))
(defn add-person! [c params]
(om/transact! reconciler [:person/by-id 0] `[(person/add! ~params)]))
(defn make-new-person [name]
{:id (om/tempid)
:name name
:points 0
:age 25})
(defui ListView
Object
(initLocalState [this]
{:person ""})
(render [this]
(let [list (om/props this)
{:keys [mutatef lista]} (om/get-computed this)
st-person (om/get-state this :person)]
(dom/div nil
(apply dom/ul nil
(map person list))
(dom/input #js {:value st-person :onChange #(on-change this %)})
(dom/button #js {:onClick #(mutatef {:new-person (make-new-person st-person)
:lista lista})}
"Add to the list")))))
(def list-view (om/factory ListView))
(defui RootView
static om/IQuery
(query [this]
(let [subquery (om/get-query Person)]
`[{:list/one ~subquery} {:list/two ~subquery}]))
Object
(render [this]
(let [{:keys [list/one list/two]} (om/props this)]
(apply dom/div nil
[(dom/h2 nil "List A")
(list-view (om/computed one {:mutatef (partial add-person! this)
:lista :list/one}))
(dom/h2 nil "List B")
(list-view (om/computed two {:mutatef (partial add-person! this)
:lista :list/two}))]))))
(defn send [edn cb]
(let [ast (om/query->ast edn)
person (-> edn first second first second)
thetmpid (:id person)]
(cb {'person/add! {:tempids {[:person/by-id thetmpid] [:person/by-id 42]}}})))
(def reconciler
(om/reconciler
{:state init-data
:id-key :id
:parser (om/parser {:read read :mutate mutate})
:send send}))
(om/add-root! reconciler RootView (js/document.getElementById "app"))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment