   (om/replace! app [:editing] nil))
 
 (defn clear-completed [app]
-  (om/replace! app [:todos]
-    (into [] (remove :completed (:todos app)))))
+  (om/replace! app [:todos] (into [] (remove :completed (:todos app)))))
+
+(defn handle-event [app [type val]]
+  (case type
+    :toggle  (toggle-todo val)
+    :destroy (destroy-todo app val)
+    :edit    (edit-todo app val)
+    :save    (let [[todo text] val]
+               (save-todo todo text))
+    :clear   (clear-completed app)
+    :cancel  (cancel-action app)
+    nil))
 
 (defn todo-app [{:keys [todos] :as app}]
   (reify
     dom/IWillMount
     (-will-mount [_ owner]
-      (let [[toggle destroy edit save clear cancel :as cs]
-            (take 6 (repeatedly chan))]
-        (dom/set-state! owner :chans
-          (zipmap [:toggle :destroy :edit :save :clear :cancel] cs))
-        (go
-          (while true
-            (alt!
-              toggle ([todo] (toggle-todo todo))
-              destroy ([todo] (destroy-todo app todo))
-              edit ([todo] (edit-todo app todo))
-              save ([[todo text]] (save-todo todo text))
-              clear ([v] (clear-completed app))
-              cancel ([v] (cancel-action app)))))))
+      (let [comm (chan)]
+        (dom/set-state! owner :comm comm)
+        (go (while true
+              (let [[e c] (<! comm)]
+                (handle-event app e))))))
     dom/IDidUpdate
     (-did-update [_ _ _ _ _]
       (store "todos" app))
     dom/IRender
     (-render [_ owner]
-      (let [active (reduce
-                     #(if (not (:completed %2)) (inc %1) %1)
-                     0 todos)
+      (let [active (reduce #(if (not (:completed %2)) (inc %1) %1) 0 todos)
             completed (- (count todos) active)
-            chans (dom/get-state owner :chans)]
+            comm (dom/get-state owner :comm)]
         (dom/div nil
           (dom/header #js {:id "header"}
             (dom/h1 nil "todos")
             (dom/input
-              #js {:ref "newField"
-                   :id "new-todo"
+              #js {:ref "newField" :id "new-todo"
                    :placeholder "What needs to be done?"
                    :onKeyDown #(handle-new-todo-keydown % app owner)})
             (om/render main app
-              {:path [:todos]
-               :opts {:chans chans :editing (:editing app)}})
+              {:path [:todos] :opts {:comm comm :editing (:editing app)}})
             (om/render footer app
-              {:path []
-               :opts {:active active :completed completed
-                      :chans chans :showing :all}})))))))
+              {:path [] :opts {:active active :completed completed
+                               :comm comm :showing :all}})))))))
 
 (om/root app-state todo-app (.getElementById js/document "todoapp"))
 

(defn main [todos opts]
  (dom/component
    (dom/section #js {:id "main"}
      (dom/input #js {:id "toggle-all"
                      :type "checkbox"
                      :onChange #(toggle-all % todos)})
      (dom/ul #js {:id "todo-list"}
        (into-array
          (map #(om/render item/todo-item todos
                  {:path [%]
                   :opts opts
                   :key :id
                   :fn (fn [todo]
                         (if (= (:id todo) (:editing opts))
                           (assoc todo :editing true)

          (str " " (pluralize active "item") " left"))
        (dom/ul #js {:id "filters"}
          (dom/li nil
            (dom/a #js {:href "#/" :className (sel :all)} "All"))
          (dom/li nil
            (dom/a #js {:href "#/active" :className (sel :active)} "Active"))
          (dom/li nil
            (dom/a #js {:href "#/completed" :className (sel :completed)} "Completed")))
        clear-button))))

;; =============================================================================
