-
Notifications
You must be signed in to change notification settings - Fork 5
/
core.cljs
149 lines (120 loc) · 4.71 KB
/
core.cljs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
(ns devcards-om-next.devcards.core
(:require [devcards-om-next.core :refer-macros [defcard-om-next om-next-root]]
[devcards.core :as dc :refer-macros [start-devcard-ui! defcard-doc defcard]]
[om.next :as om :refer-macros [defui ui]]
[om.dom :as dom]
[sablono.core :as sab :include-macros true]))
(defn init! []
(enable-console-print!)
(start-devcard-ui!))
(defcard-doc
"## Rendering Om Next components with `om-next-root` and `defcard-om-next`
The `om-next-root` will render Om Next components, much the way `om.core/add-root!` does.
It takes one or two arguments. The first argument is the Om Next component. The second (optional)
argument is either a map or atom with the state to pass to the component, or an Om Next reconciler.
The `defcard-om-next` is a shortcut to `(defcard (om-next-root ...))`.
Its arguments are the same of a normal `defcard`, with the following exception:
after the optional name and documentation, there must be an Om Next component. The argument after that
is optional, and may either the initial state map, or an Om Next reconciler.
Please refer to code of this file to see how these Om Next examples are
built.
### One more thing
- If you want to experience the best of a live-programming environment, don't forget to write reloadable code:
- `defui ^:once` your components
- `defonce` your reconcilers!
")
(defui ^:once Widget
Object
(render [this]
(sab/html [:h2 "This is an Om Next card, " (:text (om/props this))])))
(defonce om-next-root-data {:text "yep"})
(defcard om-next-card-ex-1
"This card calls `om-next-root` with one argument, the component. The initial data
is passed as an argument to `defcard`."
(om-next-root Widget)
om-next-root-data)
(defcard om-next-card-ex-2
"This is the same example but `om-next-root` now takes two arguments."
(om-next-root Widget om-next-root-data))
(defcard om-next-card-reconciler-ex
"This card calls `om-next-root` with 2 args, the component and the Om Next reconciler"
(om-next-root Widget
(om/reconciler
{:state om-next-root-data
:parser (om/parser {:read (fn [] {:value om-next-root-data})})})))
(defcard-om-next om-next-no-reconciler
"This `defcard-om-next` card takes the initial state map as its last arg"
Widget
om-next-root-data)
(defcard om-next-share-atoms
(dc/doc
"#### You can share an Atom between `om-next-root`/`defcard-om-next` cards.
Interact with the counters below."))
(defonce om-test-atom (atom {:count 20}))
(defn counter-mutate
[{:keys [state]} _ {:keys [f]}]
{:value {:keys [:count]}
:action #(swap! state update :count f)})
(defn counter-read
[{:keys [state]} _ _]
{:value (:count @state)})
(defn counter [f s]
(ui
static om/IQuery
(query [this]
[:count])
Object
(render [this]
(let [{:keys [count] :as props} (om/props this)]
(sab/html
[:div
[:h1 (om/shared this :title) count]
[:div [:a {:onClick #(om/transact! this `[(counter-mutate! {:f ~f})])} s]]
(dc/edn props)])))))
(def om-next-counter-inc (counter inc "inc"))
(defonce rec1
(om/reconciler {:state om-test-atom
:parser (om/parser {:read counter-read
:mutate counter-mutate})
:shared {:title "First counter "}}))
(defcard-om-next om-next-card-shared-ex-1
om-next-counter-inc
rec1)
(def om-next-counter-dec (counter dec "dec"))
(defonce rec2
(om/reconciler {:state om-test-atom
:parser (om/parser {:read counter-read
:mutate counter-mutate})
:shared {:title "Second counter "}}))
(defcard-om-next om-next-card-shared-ex-2
om-next-counter-dec
rec2
{:history true})
(defcard om-test-atom-data
"### You can share an Atom with an `edn-card` too:"
om-test-atom)
(defn display-state [c [k v]]
(dom/li #js {:key (str k)}
(str k ": " v)
(dom/button #js {:onClick #(om/update-state! c update k inc)} "inc!")))
(defui ^:once ComponentWithLocalState
static om/IQuery
(query [this]
[:count])
Object
(initLocalState [this]
{:a 1
:b 2})
(render [this]
(let [{:keys [count] :as props} (om/props this)]
(dom/div nil
(dc/edn props)
(map #(display-state this %) (om/get-state this))))))
(defonce local-reconciler
(om/reconciler {:state om-test-atom
:parser (om/parser {:read counter-read})}))
(defcard-om-next local-state-om-next-card
"Test that reloading preserves local state. Increment the counters, modify the
source (e.g. the button label) and see the updated label with the same counter state"
ComponentWithLocalState
local-reconciler)