/
core.cljs
122 lines (100 loc) · 3.38 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
(ns examples.todo.core
(:require [reacl2.core :as reacl :include-macros true]
[reacl2.dom :as dom :include-macros true]))
(enable-console-print!)
(defrecord TodosApp [next-id todos])
(defrecord Todo [id text done?])
(defrecord Delete [todo])
(def mix
(reacl/mixin foo app-state local-state
[parent]
component-did-mount (fn []
(println "DID MOUNT!" parent foo app-state local-state))
component-will-update (fn [next-app-state next-local-state]
(println "WILL UPDATE!" next-app-state next-local-state))
component-did-update (fn [previous-app-state previous-local-state]
(println "DID UPDATE!" previous-app-state previous-local-state))))
(reacl/defclass to-do-item
this todo [parent]
mixins [(mix parent)]
render
(dom/div (dom/input
{:type "checkbox"
:value (:done? todo)
:onchange (fn [e]
(reacl/send-message! this
(.. e -target -checked)))})
(dom/button
{:onclick
(fn [_]
(reacl/send-message! parent (->Delete todo)))}
"Zap")
(:text todo))
handle-message
(fn [checked?]
(reacl/return :app-state
(assoc todo :done? checked?))))
(defrecord NewText [text])
(defrecord Submit [])
;; Note this needs to be a top-level function as not to ruin update checks
(defn embed-changed-todo
[app-state changed-todo]
(let [changed-id (:id changed-todo)]
(assoc app-state
:todos (map (fn [todo]
(if (= changed-id (:id todo) )
changed-todo
todo))
(:todos app-state)))))
(reacl/defclass to-do-app
this app-state []
local-state [local-state ""]
render
(dom/div
(dom/h3 "TODO")
(dom/div
(map (fn [todo]
(dom/keyed (str (:id todo))
(to-do-item
(reacl/opt :embed-app-state embed-changed-todo)
todo
this)))
(:todos app-state)))
(dom/form
{:onsubmit (fn [e]
(.preventDefault e)
(reacl/send-message! this (->Submit)))}
(dom/input {:onchange
(fn [e]
(reacl/send-message!
this
(->NewText (.. e -target -value))))
:value local-state})
(dom/button
(str "Add #" (:next-id app-state)))))
handle-message
(fn [msg]
(cond
(instance? NewText msg)
(reacl/return :local-state (:text msg))
(instance? Submit msg)
(let [next-id (:next-id app-state)]
(reacl/return
:local-state ""
:app-state
(assoc app-state
:todos
(concat (:todos app-state)
[(->Todo next-id local-state false)])
:next-id (+ 1 next-id))))
(instance? Delete msg)
(let [id (:id (:todo msg))]
(reacl/return :app-state
(assoc app-state
:todos
(remove (fn [todo] (= id (:id todo)))
(:todos app-state))))))))
(reacl/render-component
(.getElementById js/document "content")
to-do-app
(TodosApp. 0 []))