Is there a way to make an onClick handler in Om without using an anonymous function?

I want to make a click handler function for the Om component. The docs and Stack Overflow docs I submitted always declare anonymous functions like this

(defn main-view [_ owner]
  (reify
  om/IRender
   (render [_]
    (let [xs (items)]
      (dom/div nil
        (om/build sub-view {:title "View A"})
        (om/build sub-view {:title "View B"})
        (dom/button
          #js {:onClick
               (fn [e] (om/transact! xs #(assoc % 1 {:text "zebra"})))}
          "Switch To Zebra!"))))))

      

I think it is cleaner to declare the click functions outside of the jsx / template scope inside the component, as is usually done in regular React. Is there a way to do this in Om inside a component? I tried this, but it doesn't work because onClick is undefined:

(defn my-component []
  (reify
    om/IRender
    (render [this]
       ; Using Sablono syntax
       (html [:h1 "Here is a heading" {:on-click 'onClick} ]))
    onClick
    (onClick [this]
      ; this part never gets executed when you click
      (.log js/console "click"))))

      

I would like to avoid defining a separate function outside of the component, if possible.

+3


source to share


2 answers


Your question is reasonable and it is about data processing.

Possibly, but the problem with this approach is in most cases you will need local scope data from an outer block of code (in your case it's the Om component).

I would explain in code. Let's say you want to move your handler function:

(anything
 (let [a 1 b 2]
   (on-event (fn my-handler [evt] (log (+ a b (.someAttr evt)))))))

      

You end up with a longer path:

(defn local-data->handler [a b]
  (fn [evt] (log (+ a b (.someAttr evt)))))

(anything
 (let [a 1 b 2]
   (on-event (local-data->handler a b))))

      



if you just want to navigate inside the component definition:

(anything
 (let [a 1
       b 2
       my-handler (fn [evt] (log (+ a b (.someAttr evt))))]
   (on-event my-handler)))

      

Please note, to preserve your event handler, make sure your non-anonymous function (created with defn or let) matches the anonymous form, especially in the argument list.

onClick is undefined because you are using it as if it were the Om protocol. Consult Om Lifecycle Protocols for correct use.

https://github.com/swannodette/om/wiki/Documentation

+5


source


As per your requirement, you should transfer the function definition from the component.

Then you can pass the name of the function to the event listener:



(defn foo [] (println "foo"))

(defn my-component [text owner]
  (reify
    om/IRender
    (render [_]
        (dom/button
          #js { :onClick foo }
          "Click Here"))))

      

+2


source







All Articles