clojurehiccup

How to create a Clojure function that returns a Hiccup structure?


Imagine I want to write a Clojure function that returns a Hiccup structure equivalent to <h3>Hello</h3>.

How can I do it?

I tried

(defn render-location-details
  [cur-location]
  (let []
    (list :h3 "Hello")
    )
  )

and

(defn render-location-details
  [cur-location]
  (let []
    [:h3 "Hello"]
    )
  )

but in both cases got the error message (:h3 "Location X") is not a valid element name..

Update 1: I am calling the above function from this one:

(defn generate-location-details-report
  [all-locations]
  (let
    [
     hiccup-title [:h2 "Locations"]
     hiccup-body (into []
                       (map
                         render-location-details
                         all-locations)
                       )
     ]
    (str
      (html hiccup-title)
      hiccup-body
      )
    )
  )

There is a collection all-locations. For each element of it, I want to create a section in HTML (with the h3) header (hiccup-body), prepend the title (hiccup-title) and convert all of this to HTML.


Solution

  • The hiccup html function will take a sequence of tags and render them as a string.

    (let [locations ["one" "two" "three"]
          title-html [[:h2 "Locations"]]
          location-html (map (fn [location] [:h3 location]) locations)]
     (html (concat title-html location-html)))
    
    "<h2>Locations</h2><h3>one</h3><h3>two</h3><h3>three</h3>"
    

    The first render-location-details doesn't work because a list isn't a vector, and so Hiccup won't render it as a tag.

    The second render-location-details is OK and does what you want. The empty (let [] binding is unnecessary. However Hiccup is then confused by putting hiccup-body (into [] - it is trying to understand your vector of location tags as a tag, because as far as Hiccup is concerned vector = tag.