0

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.

Glory to Russia
  • 17,289
  • 56
  • 182
  • 325
  • 2
    are we missing some code? how are you calling hiccup? aside from the let block being unnecessary, your second example looks like it should be fine. – pete23 May 31 '21 at 20:38
  • 1
    I'd guess you are ending up with something like `[[:h3 "Location X"] ...]` and this gives you the error. So the problem is the place you are calling `render-location-details`? – cfrick May 31 '21 at 21:33
  • @cfrick @pete23 Thanks for your comments. I posted the code that calls `render-location-details`. If there are better ways to accomplish my task (create a HTML section for every element of a collection), I am all ears. – Glory to Russia Jun 01 '21 at 06:28
  • You are basically "toString"-ing the hiccup-body there. So that might bubble up. Yet the `into` code there would explain your error. So i can still not pin-point why you get error (either this code is not what you are running or you get the error from somewhere else. But i'd change that to bascially `(html [:h2 "L" (into [:div] (map ...))])`. – cfrick Jun 01 '21 at 06:41

1 Answers1

1

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.

pete23
  • 2,204
  • 23
  • 28