Search code examples
onchangeclojurescriptreagentdplyr

Binding on-change in ClojureScript/Reagent


I am trying to understand how input fields work in Reagent.

I first tried to bind on-change to a simple function that changes underlying atom:

(defonce app-state
  (reagent/atom "Teodor"))

(defn page [ratom]
  [:div
    [:p
      "Please enter your name: "
      [:input {:on-change #(swap! ratom %)
               :value @ratom}]]
    [:p "Your name is " @ratom]])

... which did not work. This, however, does:

(defonce app-state
  (reagent/atom "Teodor"))

(defn page [ratom]
  [:div
    [:p
      "Please enter your name: "
      [:input {;:on-change #(swap! ratom %)
               :on-change (fn [evt]
                             (reset! ratom (-> evt .-target .-value)))
               :value @ratom}]]
    [:p "Your name is " @ratom]])

I've managed to desugar the -> macro:

(fn [evt]
  (reset! ratom (-> evt .-target .-value)))
;; is the same as
(fn [evt]
  (reset!
    ratom
    (.-value (.-target evt))))
  1. What do .-value and .-target do?
  2. Where can I find documentation for .-value and .-target?
  3. Why choose the more complicated semantics?

Solution

  • The evt that is coming into your function is a JavaScript event object. .-target and .-value are the JavaScript DOM properties that allow you to access the underlying value that the event is holding.

    Here you are in the world of JavaScript interop, so you will have to go to JavaScript for the documentation.

    As far as the complicated semantics of using the -> macro or not: that's just handy for people who like to unpeel properties from left to right as they read. The -> macro will be making your code look similar to the equivalent JavaScript code.