Search code examples
reactjsclojurescriptom

Conditionally Add a Class to an Element with Om


In Om, is there a way to add a class to an element based on some value in the main app atom?

Take the following element, for example:

(defn some-component [app owner]
  (reify
    om/IRender
    (render
      [_]
      (html
        [:div {:class (when (:some-key app) "awesomeclass")} "Some text!"])))) 

If I somehow toggle the value of :some-key between true and false, the class doesn't get added or removed. The value of :some-key on page load determines whether or not the class gets added.

I am using this idea to conditionally show/hide (using Twitter Bootstrap's hide class) menu options based on the value of the :access key in my app state:

[:ul.dropdown-menu {:role "menu"}
  [:li {:class (when (:access app) "hide")} [:a.pointer {:on-click #(om/update! app :view :login)} "Login"]]
  [:li {:class (when (:access app) "hide")} [:a.pointer {:on-click #(om/update! app :view :register)} "Register"]]
  [:li {:class (when-not (:access app) "hide")} [:a.pointer {:on-click #(om/update! app :view :dashboard)} "Dashboard"]]
  [:li {:class (when-not (:access app) "hide")} [:a.pointer {:on-click #(om/update! app :view :settings)} "Settings"]]
  [:li [:a.pointer {:on-click #(om/update! app :view :about)} "About"]]]

Solution

  • This code works as expected. When I click on "Click Me!", while looking at the Elements in Developer Tools (Chrome), I see the class toggling between "awesomeclass" and disappearing:

     (defonce app-state (atom {:some-key true}))
    
     (defn main []
       (om/root
         (fn [app owner]
           (reify
             om/IRender
             (render [_]
               (html
                [:div {:class (when (:some-key app) "awesomeclass")}
                 "Some text!"
                 [:a {:on-click #(om/transact! app :some-key not)}
                  "Click Me!"]]))))
         app-state
         {:target (. js/document (getElementById "app"))}))  
    

    As rojoca pointed out, the problem might be in the way you update app-state, consider using om/transact! and om/update!. If you keep having problems, post the code that updates the state.

    Note: I'm running this in Chestnut.