I have a bunch of maps that describe locations:
(def pizzeria
{
:LocationId "pizzeria"
:Desc "Pizzeria where Timur works"
:Address "Vorgartenstraße 126, 1020 Wien"
:Comment ""
})
(def dancing-school
{
:LocationId "dancing-school"
:Desc "Dancing school"
:Comment "4th district"
})
Some of those maps have :Comment
s, others don't.
I want to create a Clojure function that, among other things, outputs the comment to HTML, if it is present.
I wrote this function:
(defn render-location-details
[cur-location]
(let [
desc (get cur-location :Desc)
address (get cur-location :Address)
comment (get cur-location :Comment)
address-title [:h4 "Address"]
address-body [:p address]
comment-hiccup [
(if (clojure.string/blank? comment)
nil
[:div
[:h4 "Comment"]
[:p comment]
])
]
]
[:h3 desc
address-title
address-body
comment-hiccup
]
)
)
If I run the code that uses this function, I get the error
Execution error (IllegalArgumentException) at
hiccup.compiler/normalize-element (compiler.clj:59).
is not a valid element name.
If I change comment-hiccup
to nil
, the error disappears.
How can I output data to HTML conditionally using Hiccup?
Note: I am new to Clojure, so if my approach is completely wrong, please tell and show how to do it right.
Your first attempt will create
comment-hiccup
like:where valid hiccup always starts with a keyword tag like:
so the error message basically says that
nil
is not a valid html tag. However, in clojurenil
when converted to a string is of zero length, so the error message becomesis not a valid element name.
instead of something likefoo is not a valid element name.
However, Hiccup and many similar forms will accept
nil
instead of a valid Hiccup expression and just filter them out before rendering the remaining valid forms. This feature is present precisely to allow the use of inlineif
orwhen
forms, which either produce valid hiccup or anil
.Sample code:
based on my favorite template project.
Side note: Cryptic error messages such as the above are a strong reason to avoid the unnecessary use of macros in your own code. The above error does not occur during code execution, but rather during code compilation. Thus, we cannot handle the error even if we wrap the offending line with a
try/catch
.P.S.
Most clojurists would condense the above code into a more "inline" style like: