validationinputclojurescriptreagent

Trigger onchange event of input in Reagent app


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"]]))

Solution

  • 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.