Reading Input With Om Next

251 views Asked by At

I'm trying to understand how to read state from a text box in om.next. As I understand it, we are no longer bound/supposed to use core.async.

As a small example, consider writing in a textbox and binding it to a paragraph element, so that the text you enter automatically appears on the screen.

(def app-state (atom {:input-text "starting text"}))


 (defn read-fn
   [{:keys [state] :as env} key params]
   (let [st @state]
     (if-let [[_ v] (find st key)]
       {:value v}
       {:value :not-found})))

 (defn mutate-fn
   [{:keys [state] :as env} key {:keys [mytext]}]
   (if (= 'update-text key)
     {:value {:keys [:input-text]}
      :action
      (fn []
        (swap! state assoc :input-text mytext))}
     {:value :not-found}))

(defui RootView
   static om/IQuery
   (query [_]
          [:input-text])
   Object
   (render [_]
           (let [{:keys [input-text]} (om/props _)]
             (dom/div nil
                      (dom/input
                       #js {:id "mybox"
                            :type "text"
                            :value input-text
                            :onChange #(om/transact! _ '[(update-text {:mytext (.-value (gdom/getElement "mybox"))})])
                            })
                      (dom/p nil input-text)))))

This doesn't work.

  1. When firing the onChange event in the input form, the quoted expression does not grab the text from the box.

  2. The first mutation fires and updates, but then subsequent mutations are not fired. Even though the state doesn't changed, should the query read the string from app-state and force the text to be the same?

1

There are 1 answers

0
Chris Murphy On

I would make the :onChange event look like this:

:onChange (fn (_)
            (let [v (.-value (gdom/getElement "mybox"))]
              #(om/transact! this `[(update-text {:mytext ~v})])))

Here the value v will actually be going through. But also om/transact! needs either a component or the reconciler to be passed as its first parameter. Here I'm passing in this which will be the root component.