I'm brand new to clojure and the web development stack. I'm trying to use enlive to set values in an HTML template:
(en/deftemplate project-main-page
(en/xml-resource "project-main.html")
[id]
[:#project-name] (en/content (str "Name: " ((get-project id) :name)))
[:#project-desc] (en/content (str "Desc: " ((get-project id) :desc))))
This works fine to set my two HTML elements, but it involves a repeated call to my function get-project
. At the moment this just reads from a local map, but eventually it will involve some external storage access, so I'd prefer to just perform it once in this function.
I was thinking of using let
:
(en/deftemplate project-main-page
(en/xml-resource "project-main.html")
[id]
(let [project (get-project id)]
[:#project-name] (en/content (str "Name: " (project :name)))
[:#project-desc] (en/content (str "Desc: " (project :desc)))))
But this only affects the description element and ignores the name forms.
What is the best way to bind a local var within deftemplate
?
Enlive's
deftemplate
macro expects a series of tag/content pairs after the args vector (the args vector is[id]
in your example). You can't just stick alet
in there because the macro isn't expecting alet
form, so when it does its splicing everything gets messed up and results in the behavior you described above.One way you could fix this would be to write your own
deftemplate
macro that allows binding definitions using the identifiers in the args vector. Example:The
deftemplate
macro is a simple wrapper aroundtemplate
, which usessnippet*
and this is probably where you'd need to insert your changes:The other option—which might be simpler since you don't have to muck around in the library code—would be to add a level of indirection to your
get-project
function to cache results. You might try the core.cache library.