I'm using Om/Sente/Sablono and working with dynamic menus. Here's my navigation 
component (like your dropdown):

(defn navigation
  "Primary navigation."
  [app-state self]
  (reify
    om/IRenderState
    (render-state [this state]
                  (html [:div {:id "main-nav"}
                         [:div {:id "env"}
                          (when (:environment app-state)
                            (get-in app-state [:environment :name]))]
                         [:div {:id "nav-items"}
                          (into [:ul] (map (nav-item app-state)
                                           (nav-menu app-state)))]
                         [:div {:style {:clear "both"}}]]))))

nav-item builds the actual HTML along with selecting the currently active 
element:

(defn nav-item
  [app-state]
  (fn [{:keys [item label key]}]
    [:li {:class (nav-selected app-state item) :id (str "menu-" key)
          :on-click (fn [e] (om/update! app-state :nav/state item))}
     label]))

And nav-menu extracts the sequence of items from the app-state, each as a map 
of value (item) / name (label) and React key - in my case so I can ensure all 
the elements in the sequence of :li's are unique.

I do a similar thing in another component to build a drop-down list:

(defn upstream-app
        ... lots of stuff omitted ...
                          [:div
                           [:div "Select a tier to work on:"]
                           (into [:select {:on-change #(om/update! app-state 
[:upstream :tier :name]
                                                                  (keyword (.. 
% -target -value)))
                                           :value (get-in app-state [:upstream 
:tier :name])}]
                                 (cons [:option {:value nil} "-- select --"]
                                       (map tier-option (get-in app-state 
[:environment :tiers]))))])))))

Hope that helps?

Sean

On Sep 4, 2014, at 7:50 PM, Tom George <[email protected]> wrote:
> I'm doing my first real work in clojurescript/om.  I have a little web 
> service that queries a database and returns a JSON message of all known 
> schema owners.  I want to use this data source to populate a dropdown.
> 
> The demo page for om-bootstrap is really nice, but in the examples for 
> populating a dropdown, the menu-items are known beforehand, so they just nest 
> a lot of (menu-item) calls.  I won't know the size of my dropdown until I hit 
> the database, and I don't want to spell out each individual menu item....  Is 
> there a better way to do this?  I was thinking maybe creating a map of 
> number-string pairs, where the keys are menu item keys, and the values are 
> the schema owners.  However, I can't think of how I would get around 
> specifying each individual menu item.  I tried mapping the menu-item function 
> to no avail.  
> 
> The relevant clojurescript looks like this right now:
> 
> (ns junk-browser.core
> (:require-macros [cljs.core.async.macros :refer [go]])
> (:require [cljs.core.async :refer [>! <! chan close!]]
>              [om.core :as om :include-macros true]
>              [om.dom :as dom :include-macros true]
>              [om-bootstrap.button :as b]
>              [cljs-http.client :as http]))
> 
> 
> (defn schema-dropdown [app owner]
>  (reify
>    om/IInitState
>    (init-state [_]
>      {:owners []})
>    om/IWillMount
>    (will-mount [_]
>       (go
>          (let [owners (into [] (<! (schema-owners)))]  ; (schema-owners) is a 
> cljs-http GET
>             (om/update-state! owner #(assoc % :owners owners)))))
>    om/IRenderState
>    (render-state [ _ state]
>       (dom/div nil 
>                    (b/dropdown {:title "Schema Owners"}
>                         (b/menu-item {:key 1} (nth (:owners state) 0 
> :not-found
>                            ...
>                          (b/menu-item {:key n} (nth (:owners state) n-1 
> :not-found)))))))
> 
> 
> 
> Any ideas on how I can tackle this in a better way?

Attachment: signature.asc
Description: Message signed with OpenPGP using GPGMail

Reply via email to