|
3 | 3 | [om.next :as om :refer-macros [defui]]
|
4 | 4 | [om.dom :as dom]))
|
5 | 5 |
|
6 |
| -(def app-state |
7 |
| - (atom |
8 |
| - {:app/title "Animals" |
9 |
| - :animals/list |
10 |
| - [[1 "Ant"] [2 "Antelope"] [3 "Bird"] [4 "Cat"] [5 "Dog"] |
11 |
| - [6 "Lion"] [7 "Mouse"] [8 "Monkey"] [9 "Snake"] [10 "Zebra"]]})) |
| 6 | +(enable-console-print!) |
12 | 7 |
|
13 |
| -(defmulti read (fn [env key params] key)) |
| 8 | +(def init-data |
| 9 | + {:list/one [{:name "John" :points 0} |
| 10 | + {:name "Mary" :points 0} |
| 11 | + {:name "Bob" :points 0}] |
| 12 | + :list/two [{:name "Mary" :points 0 :age 27} |
| 13 | + {:name "Gwen" :points 0} |
| 14 | + {:name "Jeff" :points 0}]}) |
14 | 15 |
|
15 |
| -(defmethod read :default |
16 |
| - [{:keys [state] :as env} key params] |
| 16 | +(defmulti read om/dispatch) |
| 17 | + |
| 18 | +(defn get-people [state key] |
17 | 19 | (let [st @state]
|
18 |
| - (if-let [[_ value] (find st key)] |
19 |
| - {:value value} |
20 |
| - {:value :not-found}))) |
21 |
| - |
22 |
| -(defmethod read :animals/list |
23 |
| - [{:keys [state] :as env} key {:keys [start end]}] |
24 |
| - {:value (subvec (:animals/list @state) start end)}) |
25 |
| - |
26 |
| -(defui AnimalsList |
27 |
| - static om/IQueryParams |
28 |
| - (params [this] |
29 |
| - {:start 0 :end 10}) |
| 20 | + (into [] (map #(get-in st %)) (get st key)))) |
| 21 | + |
| 22 | +(defmethod read :list/one |
| 23 | + [{:keys [state] :as env} key params] |
| 24 | + {:value (get-people state key)}) |
| 25 | + |
| 26 | +(defmethod read :list/two |
| 27 | + [{:keys [state] :as env} key params] |
| 28 | + {:value (get-people state key)}) |
| 29 | + |
| 30 | +(comment |
| 31 | + |
| 32 | + ;; IDENTITY |
| 33 | + |
| 34 | + (in-ns 'om-tutorial.core) |
| 35 | + (require '[cljs.pprint :as pp]) |
| 36 | + (def norm-data (om/tree->db RootView init-data true)) |
| 37 | + |
| 38 | + ;; normalized data |
| 39 | + (pp/pprint norm-data) |
| 40 | + |
| 41 | + (def parser (om/parser {:read read})) |
| 42 | + |
| 43 | + ;; not normalized |
| 44 | + (parser {:state (atom norm-data)} '[:list/one]) |
| 45 | + |
| 46 | + ) |
| 47 | + |
| 48 | +(defmulti mutate om/dispatch) |
| 49 | + |
| 50 | +(defmethod mutate 'points/increment |
| 51 | + [{:keys [state]} _ {:keys [name]}] |
| 52 | + {:action |
| 53 | + (fn [] |
| 54 | + (swap! state update-in |
| 55 | + [:person/by-name name :points] |
| 56 | + inc))}) |
| 57 | + |
| 58 | +(defmethod mutate 'points/decrement |
| 59 | + [{:keys [state]} _ {:keys [name]}] |
| 60 | + {:action |
| 61 | + (fn [] |
| 62 | + (swap! state update-in |
| 63 | + [:person/by-name name :points] |
| 64 | + #(let [n (dec %)] (if (neg? n) 0 n))))}) |
| 65 | + |
| 66 | + |
| 67 | +(comment |
| 68 | + |
| 69 | + (def parser (om/parser {:read read :mutate mutate})) |
| 70 | + |
| 71 | + (def st (atom norm-data)) |
| 72 | + |
| 73 | + ;; inc mary points |
| 74 | + (parser {:state st} '[(points/increment {:name "Mary"})]) |
| 75 | + |
| 76 | + ;; updated in both: |
| 77 | + (parser {:state st} '[:list/one]) |
| 78 | + |
| 79 | + (parser {:state st} '[:list/two]) |
| 80 | + |
| 81 | + ) |
| 82 | + |
| 83 | +(defui Person |
| 84 | + static om/Ident |
| 85 | + (ident [this {:keys [name]}] |
| 86 | + [:person/by-name name]) |
| 87 | + static om/IQuery |
| 88 | + (query [this] |
| 89 | + '[:name :points]) |
| 90 | + Object |
| 91 | + (render [this] |
| 92 | + (println "Render Person" (-> this om/props :name)) |
| 93 | + (let [{:keys [points name foo] :as props} (om/props this)] |
| 94 | + (dom/li nil |
| 95 | + (dom/label nil (str name ", points: " points)) |
| 96 | + (dom/button |
| 97 | + #js {:onClick |
| 98 | + (fn [e] |
| 99 | + (om/transact! this |
| 100 | + `[(points/increment ~props)]))} |
| 101 | + "+") |
| 102 | + (dom/button |
| 103 | + #js {:onClick |
| 104 | + (fn [e] |
| 105 | + (om/transact! this |
| 106 | + `[(points/decrement ~props)]))} |
| 107 | + "-"))))) |
| 108 | + |
| 109 | +(def person (om/factory Person {:keyfn :name})) |
| 110 | + |
| 111 | +(defui ListView |
| 112 | + Object |
| 113 | + (render [this] |
| 114 | + (println "Render ListView" (-> this om/path first)) |
| 115 | + (let [list (om/props this)] |
| 116 | + (apply dom/ul nil |
| 117 | + (map person list))))) |
| 118 | + |
| 119 | +(def list-view (om/factory ListView)) |
| 120 | + |
| 121 | +(defui RootView |
30 | 122 | static om/IQuery
|
31 | 123 | (query [this]
|
32 |
| - '[:app/title (:animals/list {:start ?start :end ?end})]) |
| 124 | + (let [subquery (om/get-query Person)] |
| 125 | + `[{:list/one ~subquery} {:list/two ~subquery}])) |
33 | 126 | Object
|
34 | 127 | (render [this]
|
35 |
| - (let [{:keys [app/title animals/list]} (om/props this)] |
36 |
| - (dom/div nil |
37 |
| - (dom/h2 nil title) |
38 |
| - (apply dom/ul nil |
39 |
| - (map |
40 |
| - (fn [[i name]] |
41 |
| - (dom/li nil (str i ". " name))) |
42 |
| - list)))))) |
| 128 | + (println "Render RootView") |
| 129 | + (let [{:keys [list/one list/two]} (om/props this)] |
| 130 | + (apply dom/div nil |
| 131 | + [(dom/h2 nil "List A") |
| 132 | + (list-view one) |
| 133 | + (dom/h2 nil "List B") |
| 134 | + (list-view two)])))) |
43 | 135 |
|
44 | 136 | (def reconciler
|
45 | 137 | (om/reconciler
|
46 |
| - {:state app-state |
47 |
| - :parser (om/parser {:read read})})) |
| 138 | + {:state init-data |
| 139 | + :parser (om/parser {:read read :mutate mutate})})) |
48 | 140 |
|
49 | 141 | (om/add-root! reconciler
|
50 |
| - AnimalsList (gdom/getElement "app")) |
| 142 | + RootView (gdom/getElement "app")) |
0 commit comments