|
|
@ -8,6 +8,10 @@
|
|
8
|
8
|
ICloneable
|
|
9
|
9
|
(-clone [s] (js/String. s)))
|
|
10
|
10
|
|
|
|
11
|
(extend-type number
|
|
|
12
|
ICloneable
|
|
|
13
|
(-clone [n] (js/Number. n)))
|
|
|
14
|
|
|
11
|
15
|
; data for one node: type and optionally data
|
|
12
|
16
|
; if data is present, fill the node with the data
|
|
13
|
17
|
; on input, check if input conforms to data, if it
|
|
|
@ -23,7 +27,21 @@
|
|
23
|
27
|
(keyword name)
|
|
24
|
28
|
nil)))
|
|
25
|
29
|
|
|
26
|
|
(defn typed-keyword [kw owner]
|
|
|
30
|
(defmulti make-typed-input
|
|
|
31
|
(fn [_ _ {type :type} & _]
|
|
|
32
|
(cond
|
|
|
33
|
(sequential? type) (first type)
|
|
|
34
|
(map? type) (:type type)
|
|
|
35
|
:else type)))
|
|
|
36
|
|
|
|
37
|
(defmethod make-typed-input 'Number [number owner]
|
|
|
38
|
(om/component
|
|
|
39
|
(dom/input #js {:type "number"
|
|
|
40
|
:className "field"
|
|
|
41
|
:value (om/value number)
|
|
|
42
|
:onChange #(om/update! number (fn [_ n] n) (js/parseFloat (.. % -target -value)))})))
|
|
|
43
|
|
|
|
44
|
(defmethod make-typed-input 'Keyword [kw owner]
|
|
27
|
45
|
(om/component
|
|
28
|
46
|
(dom/input #js {:type "text"
|
|
29
|
47
|
:className "field"
|
|
|
@ -33,29 +51,36 @@
|
|
33
|
51
|
(when (valid? (.-target ev))
|
|
34
|
52
|
(om/update! kw (fn [o n] n) (read-keyword (.. ev -target -value)))))})))
|
|
35
|
53
|
|
|
36
|
|
(defn typed-string [string owner]
|
|
|
54
|
(defmethod make-typed-input 'String [string owner]
|
|
37
|
55
|
(om/component
|
|
38
|
56
|
(dom/input #js {:type "text"
|
|
39
|
57
|
:className "field"
|
|
40
|
58
|
:value (om/value string)
|
|
41
|
|
:onChange #(om/update! string (fn [o n] n) (.. % -target -value))})))
|
|
|
59
|
:onChange #(om/update! string (fn [_ n] n) (.. % -target -value))})))
|
|
|
60
|
|
|
|
61
|
(defmethod make-typed-input 'HMap [m owner {type :type}]
|
|
|
62
|
(om/component
|
|
|
63
|
(dom/div #js {:className "field"}
|
|
|
64
|
(dom/span nil "{")
|
|
|
65
|
(into-array
|
|
|
66
|
(map (fn [[k v]]
|
|
|
67
|
(dom/div #js {:className "field"}
|
|
|
68
|
(dom/label nil (str k))
|
|
|
69
|
(om/build make-typed-input v {:opts {:type (k (nth type 2))}})))
|
|
|
70
|
m))
|
|
|
71
|
(dom/span nil "}"))))
|
|
|
72
|
|
|
|
73
|
(def app-state
|
|
|
74
|
(atom
|
|
|
75
|
'{:type (HMap :mandatory {:name String, :age Number, :gender Keyword})
|
|
|
76
|
:data {:name "Paul", :age 3, :gender :unknown}}))
|
|
42
|
77
|
|
|
43
|
|
(defn typed-input [data owner]
|
|
|
78
|
(defn typed-input [{:keys [type data]} owner]
|
|
44
|
79
|
(reify
|
|
45
|
80
|
om/IWillUpdate
|
|
46
|
|
(will-update [_ p s] (prn p s))
|
|
|
81
|
(will-update [_ p s] (prn (:data p) s))
|
|
47
|
82
|
om/IRender
|
|
48
|
83
|
(render [_]
|
|
49
|
|
(dom/div nil
|
|
50
|
|
(dom/span nil "{")
|
|
51
|
|
(om/build typed-keyword (:kw data))
|
|
52
|
|
(om/build typed-string (:str data))
|
|
53
|
|
(dom/span nil "}")))))
|
|
54
|
|
|
|
55
|
|
(def app-state
|
|
56
|
|
(atom
|
|
57
|
|
{:kw :hello
|
|
58
|
|
:str "hello"
|
|
59
|
|
:many [1 2 3]}))
|
|
|
84
|
(om/build make-typed-input data {:opts {:type type}}))))
|
|
60
|
85
|
|
|
61
|
86
|
(om/root app-state typed-input (.getElementById js/document "typed_input"))
|