Search code examples
javascriptclojureclojurescriptreagenthiccup

How do I add a click event to trigger a JavaScript event in ClojureScript using Reagent Hiccup


I have just started using Reagent and am very new to Clojure.

I have created a mobile menu function and want the mobile hamburger menu to be clickable in order to show the actual menu. When clicked on again, the menu must hide. I have no idea how to do

(defn mobile-menu [primary-menu secondary-menu logo-el]
 [:div#ca-horizontal-mobile
  [:div#logo logo-el]
  [:div#menu-button
   [:a
    [:i.icon.bars]]]

  [:header#menu.mobile
   [:div
    [:div.center.menu
     (let [menu (concat primary-menu secondary-menu)]
       (for [i menu]
         [:div.item {:key (:key i)}
          [:a.item {:id   (:key i)
                    :href (:target i)} (:name i)]]))
     [:div.item
      [:a
       {:style    {:cursor :pointer}
        :id       :logout
        :on-click #(re-frame/dispatch [:logout])} (str "Logout")]]]]]])])

The anchor needs to expand and hide the menu.

   [:a
    [:i.icon.bars]]]

All I need is an example of how to make a JavaScript call on a JavaScript event and a little bit of help understanding it.

I found this snippet online https://www.reddit.com/r/Clojure/comments/4ofct5/calling_methods_on_an_element_in_a_reagent/ but am unsure how it hooks up to anything. How does the .play element know what to do on-click?

(defn video-elem [src-url uid]
  [:div
    [:video {:src src-url :id uid}]
        [:button {:on-click #(.play (.getElementById js/document uid))} "Play!"]
        [:button {:on-click #(.pause (.getElementById js/document uid))} "Pause!"]])

Solution

  • With the help of a colleague we added the following. I am not sure if I have explained this correctly though.

    (re-frame/reg-event-db
      :toggle-mobile-menu
      (fn [db _]
        (assoc db :mobile-menu-visible (not (:mobile-menu-visible db)))))
        
    (re-frame/reg-sub :show-mobile-menu #(:mobile-menu-visible %))))
    
    (defn mobile-menu [primary-menu secondary-menu logo-el]
      [:div#ca-horizontal-mobile
       [:div#logo logo-el]
       [:div#menu-button
        {:on-click #(re-frame/dispatch [:toggle-mobile-menu])}
        [:i.icon.bars]]
        
       (let [show-menu (re-frame/subscribe [:show-mobile-menu])]
         (if @show-menu
           [:header#menu.mobile
            [:div
             [:div.center.menu
              (let [menu (concat primary-menu secondary-menu)]
                (for [i menu]
                  [:div.item {:key (:key i)}
                   [:a.item {:id   (:key i)
                             :href (:target i)} (:name i)]]))
              [:div.item
               [:a
                {:style    {:cursor :pointer}
                 :id       :logout
                 :on-click #(re-frame/dispatch [:logout])} (str "Logout")]]]]]))])]])
    
    • The menu button click event dispatches a :toggle-mobile-menu re-frame/reg-event-db which toggles the visibility of the menu

    • The show_menu binding subscribes to the re-frame/reg-sub :show-menu-mobilewhich gets the:mobile-menu-visible` value from the db

    • The @show-menu value from the db is destructured to a truthy value indicating if the menu should be hidden or displayed.