5

Trying react for the first time, and I want to make a simple todo list app. But every time I press enter to trigger onSubmit it says Uncaught Error: Cannot manipulate cursor outside of render phase, only om.core/transact!, om.core/update!, and cljs.core/deref operations allowed. While I think this is a very good error message, I don't know what to do.

(ns app.core
  (:require [om.core :as om :include-macros true]
            [sablono.core :as html :refer-macros [html]]))

(def app-state (atom
                {:todos [{:todo "first"}
                         {:todo "second"}]
                 :current ""}))

(defn to-do
  [data]
  (om/component
   (html [:li (:todo data)])))

(defn to-dos
  [data]
  (om/component
   (html [:div
          [:form {:on-submit (fn [e]
                               (.preventDefault e)
                               (om/transact! data :todos (fn [v]
                                                           (js/console.log (:current data))
                                                           (conj v (:current data)))))}
           [:input {:type "text" 
                    :placeholder "Enter some text."
                    :on-change (fn [e] (om/update! data :current (.. e -target -value)))}]]
          [:ul 
          (om/build-all to-do (:todos data))]])))

(om/root to-dos app-state {:target js/document.body})
Faris Nasution
  • 3,450
  • 5
  • 24
  • 29

2 Answers2

4

I think the problem is where you access data inside om/transact! where you should operate on v:

(:current v) instead of (:current data)

or you may try (:current @data) for most recent value of data

edbond
  • 3,921
  • 19
  • 26
  • 1
    Using `(:current v)` is much preferable to accessing the `@data` cursor again. There is a second problem here, though, with the `:todos` argument to `om/transcat!`. See my answer below. – prabhasp Apr 19 '15 at 03:47
1

There are actually two issues with:

(om/transact! data :todos (fn [v]
  (js/console.log (:current data))
  (conj v (:current data)))))

One is what @edbond said above: you should use (:current v) rather than (:current data). The other problem, however, is that you are specifying the :todos keyword, and instead, you should simply change data itself, since :current is outside of :todos in your app-state shown. So the correct formulation would be:

(om/transact! data (fn [v]
  (js/console.log (:current v))
  (conj v (:current v)))))
prabhasp
  • 528
  • 3
  • 18