I'm displaying a menu in Om, using a component and subcomponent like this:
(def app-state (atom {:location ""
:menuitems [["Pages" "/pages/"]
["Images" "/images/"]]}))
(defn menu-item-view [parent-cursor item owner]
(reify
om/IRender
(render [this]
(dom/li #js {:className (if (= (:location @app-state) (last item)) "active" "inactive")}
(dom/a #js
{:onClick (fn [_] (swap! app-state assoc :location (last @item)))}
(first item))))))
(defn menu-view [app owner]
(reify
om/IRender
(render [this]
(dom/li #js {:className "has-dropdown not-click"}
(dom/a nil "Menu")
(apply dom/ul #js {:className "dropdown"}
(om/build-all (partial menu-item-view app)
(:menuitems app)))))))
(om/root menu-view app-state
{:target (. js/document (getElementById "menu"))})
My question is how do I update the (@app-state :location) and correctly rerender the menu?
The update in the code above:
(swap! app-state assoc :location (last @item))
does work, but the tree is not updated correct.
I suspect i need to use om/update! or om/transact! but they take a cursor and the only cursor i have in menu-item-view is to the current menu item, not the full app-state. So i cannot access :location.
How is this handled?
I would prefer to aviod core.async and channels for the time being if possible.
Now that we have reference cursors you could probably do something like this:
(def app-state (atom {:location ""
:menuitems [["Pages" "/pages/"]
["Images" "/images/"]]}))
(defn location []
(om/ref-cursor (:location (om/root-cursor app-state))))
(defn menu-item-view [item owner]
(reify
om/IRender
(render [this]
(let [x (location)]
(dom/li #js {:className (if (= x (last item)) "active" "inactive")}
(dom/a #js
{:onClick (fn [_] (om/update! x (last @item)))}
(first item)))))))
(defn menu-view [app owner]
(reify
om/IRender
(render [this]
(dom/li #js {:className "has-dropdown not-click"}
(dom/a nil "Menu")
(apply dom/ul #js {:className "dropdown"}
(om/build-all menu-item-view (:menuitems app)))))))
(om/root menu-view app-state
{:target (. js/document (getElementById "menu"))})
It's just an idea - I haven't actually tested it.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With