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.
When firing the onChange event in the
input
form, the quoted expression does not grab the text from the box.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?
I would make the
:onChange
event look like this:Here the value
v
will actually be going through. But alsoom/transact!
needs either a component or the reconciler to be passed as its first parameter. Here I'm passing inthis
which will be the root component.