Trigger onchange event of input in Reagent app

165 Views Asked by At

How can I trigger the onchange event of a controlled input in a Reagent application?

[:input {:on-change (fn [e] ...) :id :my-input}]

Reagent implements React and the input components are Controlled React inputs so as I found out the input eventually doesn't have the on-change function. It has some kind of React property that contains the passed on-change function and the default on-change fn is nil in the input element object.

So therefore this doesn't working:

(let [input (.get-element-by-id js/document "my-input")]
     (.onchange input))

The purpose is that I have input fields and I want to make a field value validator that could be called anytime (e.g. clicking on a submit button). So I put the validator in the on-change function and it works well but now I need to call the on-change function if I want validate the fields when Im clicking on the submit button.

I tried this but nothing happened:

(defn input
  []
  (letfn [(f [] (let [e (js/Event. "change")
                      el (.getElementById js/document "my-input")]
                     (.dispatchEvent el e)))]
     [:<> [:input  {:id :my-input :on-change (fn [_] (println "Changed"))}]
          [:button {:on-click f} "Trigger on-change"]]))
2

There are 2 best solutions below

0
Thomas Heller On BEST ANSWER

What you are trying to do is a bad idea, since the browser treats events triggered by the user differently than those triggered by code. So, you might find stuff work on the actual :on-change but not otherwise. Instead, just write a function to do what you want.

(defn stuff-i-want-to-happen [maybe with args] ...)

(defn input []
  [:<> [:input {:on-change (fn [_] (println "Changed") (stuff-i-want-to-happen 1 2 3)}]
       [:button {:on-click #(stuff-i-want-to-happen 4 5 6)} "Trigger on-change"]])

If you need to track additional state, you can just move that to the appropriate place.

0
Phil Cooper On

The purpose is that I have input fields and I want to make a field value validator that could be called anytime (e.g. clicking on a submit button).

Since you are using Reagent, I think what you want is to use form validator hooks. You can rummage around npm but one I would suggest is react hook form

It does require you to learn their concept of "registering" a validation but it will be able to keep up with all of you validation needs (which only grow as real users get involved).