1

I want to create a template with Clojure's Enlive for a "table" like html page, that should have a header and rows. I want to populate this "table" with data that comes from this map. Basicaly I want to populate header with keys, and cells with vals from each of the maps that come from :event-data key.

(def dummy-content
{:title "Events Mashup"
 :event-data [{ :event-name "event name 1"
                    :performer "performer 1"
                  :date "date 1"
                       :start-time "start time 1"
                       :end-time "end time 1"}
  {:event-name "event name 2"
                       :performer "performer 2"
                      :date "date 2"
                       :start-time "start time 2"
                       :end-time "end time 2"}]})

My snippets and template look like this:

(defsnippet header-cell "index.html" [:.psdg-top-cell] [value] [:.psdg-top-cell]

(defsnippet value-cell "index.html" [:.psdg-right] [value] [:.psdg-right] 

(deftemplate mshp "index.html" [content] 
 [:.psdg-top] (append (for [c (keys content)] (header-cell c)))
 [:.psdg-right] (append (for [v (vals content)] (value-cell v))))

And index.html has these tags, that are rellevant for this template.

<div id="psdg-top">
<div class="psdg-top-cell" style="width:129px; text-align:left; padding- left:24px;">Summary</div>
<div class="psdg-top-cell">Website.com</div>
</div>
<div class="psdg-right">10 000</div>

When I call the template I get this error:

 => (mshp (:event-data dummy-content))

ClassCastException clojure.lang.PersistentHashMap cannot be cast to java.util.Map$Entry clojure.lang.APersistentMap$ValSeq.first (APersistentMap.java:183) What am I doing wrong?

4

1 回答 1

1

The error is occurring when you call (keys content), because (:event-data dummy-content) returns a vector, and keys won't work on a vector. You've got two options - you can either define your header columns elsewhere, or just take them from the first element in the vector, like this: (keys (first content)).

Edit

I've had a go at replicating what you set out in the question, but fixing the errors, and you can find my efforts here: https://www.refheap.com/17659.

If you want something that has a more typical table structure, with the value cells contained in rows, you can try the following. It uses clone-for rather than a combination of append and for, and uses nth-of-type to just return the first "psdg-top-cell" (otherwise there would be twice as many)

(def template
  (html-snippet
   "<div id=\"psdg-top\">
    <div class=\"psdg-top-cell\">Summary</div>
    <div class=\"psdg-top-cell\">Website.com</div>
    </div>
    <div class=\"psdg-right\">10 000</div>"))

(defsnippet header-row template [[:.psdg-top-cell (nth-of-type 1)] ] [headers]
  (clone-for [h headers] 
     (content h)))

(defsnippet value-row template [:.psdg-right] [values]
  (clone-for [v values]
     (content v)))

(deftemplate mshp template [events]
  [:#psdg-top] (content (header-row (map name (keys (first events)))))
  [:.psdg-right] (clone-for [e events]
                        (do->
                         (wrap :div {:class "psdg-row"})
                         (content (value-row (vals e))))))
于 2013-08-14T15:37:08.350 回答