Binding local var in deftemplate to revitalize

I am new to clojure and the web development stack. I am trying to use animate 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 great for setting up my two HTML elements, but it involves calling my get-project function again. At the moment it is just readable from the local card, but ultimately it will require some external access to the repository, so I would rather just execute it once in this function.

I was thinking about 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 forms of names.

What is the best way to bind a local var in a deftemplate ?

+4
source share
2 answers

The enlive deftemplate macro expects a series of tag / content pairs after the args vector (the args [id] vector in your example). You cannot just paste let there because the macro does not expect a let form, so when it performs its splicing, everything gets corrupted and leads to the behavior described above.

One way to fix this is to write your own deftemplate macro, which allows you to bind definitions using identifiers in the args vector. Example:

 (alt/deftemplate project-main-page (en/xml-resource "project-main.html") [id] [project (get-project id)] [:#project-name] (en/content (str "Name: " (project :name))) [:#project-desc] (en/content (str "Desc: " (project :desc)))) 

The deftemplate macro is a simple wrapper around the template that uses snippet* , and this is probably where you need to insert your changes:

 (defmacro snippet* [nodes args & forms] `(let [nodes# (map annotate ~nodes)] (fn ~args ; You could add let bindings here since args are in scope (doall (flatmap (transformation ~@forms ) nodes#))))) 

Another option, which might be simpler since you do not need to guess in the library code, would be to add a level of indirection to your get-project function to cache the results. You can try the core.cache library.

+1
source

If I understand what you are trying to achieve; You can also try using the conversion macro provided by the enlive function.

 (defn main-page [{:keys [name desc] :as project}] (en/transformation [:#project-name] (en/content (str "Name: " name) [:#project-desc] (en/content (str "Desc: " desc)))) (en/deftemplate project-main-page (en/xml-resource "project-main.html") [id] (main-page (get-project id))) 

The code has not been verified, but I hope it provides a different way to do what you need.

+2
source

All Articles