                     (dom/span nil (display-name contact))
                     (dom/button #js {:onClick (fn [e] (put! delete @contact))} "Delete")))))
 
+(defn parse-contact [contact-str]
+  (let [[first middle last :as parts] (string/split contact-str #"\s+")
+        [first last middle] (if (nil? last) [first middle] [first last middle])
+        middle (when middle (string/replace middle "." ""))
+        c (if middle (count middle) 0)]
+    (when (>= (count parts) 2)
+      (cond-> {:first first :last last}
+              (== c 1) (assoc :middle-initial middle)
+              (>= c 2) (assoc :middle middle)))))
+
+(defn add-contact [data owner]
+  (let [input-el (om/get-node owner "new-contact")
+        new-contact (-> input-el
+                        .-value
+                        parse-contact)]
+    (when new-contact
+      (om/transact! data :contacts #(conj % new-contact))
+      (set! (.-value input-el) ""))))
+
 (defn contacts-view [data owner]
   (reify
     om/IInitState

                     (dom/h2 nil "Contact List")
                     (apply dom/ul nil
                            (om/build-all contact-view (:contacts data)
                                          {:init-state {:delete delete}}))))))

(om/root contacts-view app-state
  {:target (. js/document (getElementById "contacts"))})

  (:require-macros [cljs.core.async.macros :refer [go]])
  (:require [om.core :as om :include-macros true]
            [om.dom :as dom :include-macros true]
            [cljs.core.async :refer [put! chan <!]]
            [clojure.string :as string]))

(enable-console-print!)

(defonce app-state (atom
    {:contacts
