Last active
January 18, 2016 20:53
-
-
Save anmonteiro/085d3d0636a3bc14f9f7 to your computer and use it in GitHub Desktop.
tempids + Simulated server
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(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