re-frame: Input :on-change reset! doesn't change input value

2.9k views Asked by At

I'm playing around with the re-frame framework.


In the code below, I am having trouble with updating the input value when the user types something in:

(defn measurement-input [{:keys [amount unit path]}]
  (let [amt (atom amount)]
    (fn []
      [:div
       [:input {:type "text"
                :value @amt
                :on-change #(reset! amt (-> % .-target .-value))}]
       [:input {:type "button"
                :value unit}]])))

The input value will not change until until I change :value to :defaultValue. I am pretty sure the above example closely mirrors Reagent's input example.


In the code below, I am trying to do two things when the user updates the input value. I'm trying to reset! the input's value as well as dispatch the value to an event handler. I've wrapped up both of these function calls in a do call.

Also of note is that in the code below, the user is able to update the value in the text field.

(defn measurement-input [{:keys [amount unit path]}]
  (let [amt (atom amount)]
    (fn []
      [:div
       [:input {:type "text"
                :value @amt
                :on-change (do #(reset! amt (-> % .-target .-value))
                                (re-frame/dispatch [:update-value @amt]))}]
       [:input {:type "button"
                :value unit}]])))

In the javascript console, I get the following error:

Uncaught TypeError: Cannot read property 'call' of null  template.cljs?rel=1435381284083:101 

Any help is appreciated everybody!

1

There are 1 answers

0
Kurt Mueller On BEST ANSWER

Daniel Kersten over at the ClojureScript Google Groups, explained to me why the code snippets weren't working. The link to the post is here.


1st code snippet

reagent overrides clojure's atom with it's own implementation. re-frame's views.cljs doesn't refer to this by default. Once you refer to reagent's version of atom, things will work.

At the top of the views.cljs file, change this:

(ns performance-tracker.views
    (:require [re-frame.core :refer [subscribe dispatch]]))

to:

(ns performance-tracker.views
    (:require [reagent.core  :as reagent :refer [atom]]
              [re-frame.core :refer [subscribe dispatch]]))

2nd code snippet

:on-change expects a function. I was passing in a do block. Simply wrapping the do block inside a function fixed the error. See below for the correct code:

(defn measurement-input [{:keys [amount unit path]}]
  (let [amt (atom amount)]
    (fn []
      [:div
       [:input {:type "text"
                :value @amt
                :on-change #(do (reset! amt (-> % .-target .-value)) ;; argument literal, %, is the event passed in the function callback
                            (re-frame/dispatch [:update-value @amt [:measurements path :amount]]))}]
       [:input {:type "button"
                :value unit}]])))