I'm having a nested loop that generates <select>
tags, and I want to set them to a certain value.
I thought I could create a lambda {{selected}}
that would take the context and check if it's the correct value for this selectbox. Except I'd also need the id from the {{team}}
array.
For a single select, you could include a selected
boolean in champions
, but this gets messy pretty quick quick select boxes.
Would there be a way to get the needed info, or another way to generated the selected
attribute? I'm using Clojure's Stencil with data the looks like this:
{:params {"winner0" 16, "winner1" 4, ...}
:champions [{:name "Soraka", :id 16}, ...]
:team (range 5)
:selected (fn [] if params[idx] == champion-id: return selected)}
HTML excerpt:
<form method="get" action="">
{{#team}}
<select name="winner{{.}}">
<option value="">None</option>
{{#champions}}
<option {{selected}} value="{{id}}">{{name}}</option>
{{/champions}}
</select>
{{/team}}
<input type="submit" value="Recommend my pick!" />
</form>
Mustache templates are supposed to be "dumb". Even though there exist a lambda construct, it has very limited capabilities. Your best bet is to transform the data so it's already "massaged" for the template. Clojure shines here: it has very powerful data transformation primitives.
Here's an example (reduced for brevity) based on yours:
(require '[stencil.core :as stencil])
(def form "{{#teams}}
<select name='winner{{id}}'>
<option value=''>None</option>
{{#champions}}
<option {{#selected}}selected='selected' {{/selected}}value='{{id}}'>{{name}}</option>
{{/champions}}
</select>
{{/teams}}")
(let [data {:params {"winner0" 16, "winner1" 4}
:champions [{:name "Soraka", :id 16}
{:name "champ4" :id 4}
{:name "champ5" :id 5}]}]
(->> (range 2)
(map (fn [team-id]
(let [winner (get (:params data) (str "winner" team-id))]
{:id team-id
:champions (map #(assoc % :selected (= (:id %) winner))
(:champions data))})))
(hash-map :teams)
(stencil/render-string form))
Result:
<select name='winner0'>
<option value=''>None</option>
<option selected='selected' value='16'>Soraka</option>
<option value='4'>champ4</option>
<option value='5'>champ5</option>
</select>
<select name='winner1'>
<option value=''>None</option>
<option value='16'>Soraka</option>
<option selected='selected' value='4'>champ4</option>
<option value='5'>champ5</option>
</select>
Even though that seems to do what you need, if you have the chance to choose I strongly recommend using something like hiccup. It's a DSL to represent html using clojure data structures, so it's very expressive and powerful.