Clojure use of (for) with hiccup and noir
Question
I am using clojure and hiccup (with noir) and I have this code:
(defn dataframe [id]
(db/db-to-data id))
(defpartial drop-downs [nms]
(for [nm (keys nms)] (drop-down nm (get nms nm))[:br])
(submit-button "Refresh")
)
(defpage "/dataset/table/:id" {:keys [id]}
(common/layout
(form-to [:post (format "/dataset/table/%s" id)]
(drop-downs {"alessio" [:col0], "test" [:col1]})
)
(html-table (dataframe id))))
My problem is with:
(for [nm (keys nms)] (drop-down nm (get nms nm))[:br])
I want to have multiple select in my form. The line above does that, but for some reason it does not consider [:br], so it does not break the lines. However, if I do this:
(form-to [:post (format "/dataset/table/%s" id)]
(drop-down "Test1" "1")[:br]
(drop-down "Test2" "2")[:br]
)
The [:br] tag does work. I believe this is connected with how the (for) macro works, but I could not figure out the reason and how to fix it.
EDIT
As advised, I dropped the use of for. Final result below (which is Joost answer with a slight mod):
(mapcat #(vector (drop-down % (nms %)) [:br]) (keys nms))
Solution
That code doesn't even compile; for
takes exactly two arguments.
If you want to put two items at once in the sequence returned by for
, put them in a vector and unpack them later.
Though personally I prefer mapcat for these situations. Something like:
(into (form-to [:post (format "/dataset/table/%s" id)])
(mapcat #(vector (drop-down % (nms %)) [:br]) nms))
OTHER TIPS
I put together a little something that doesn't use Noir or hiccup, but maybe will guide you in a better direction. It uses mapcat instead of for:
(let [nms {"alessio" [:col0], "test" [:col1]}]
(mapcat
(fn [mapentry] [[:dropdown (first mapentry) (second mapentry)] [:br]]) nms))
;;=> ([:dropdown "alessio" [:col0]] [:br] [:dropdown "test" [:col1]] [:br])
Hiccup automatically "unwraps" seqs/lists (not vectors!) for you, so you can write this as:
(for [[k v] nms]
(list (drop-down k v)
[:br])))