clojureenlive

Clojure: enlive deftemplate can't use snippet


I'm trying to create template that produces table with some data in it. Data comes from a map defined in msh-contents.

   (require '[net.cgrand.enlive-html :as html])

   (def msh-contents {:title "Events mashup",
                  :data-content [{:title "ICTM Study Group ",  
                                :url "http://some-url.com"} 
                                {:title "Volodja Balzalorsky - Hinko Haas",
                                :url "http://some- other-url.com"}
                                ]})

   ;; define snippets based on some divs in the template
    (html/defsnippet header-cell (template-div) [:div.Heading :div.Cell][value]
    (html/content value))

   (html/defsnippet value-cell (template-div) [:div.Row :div.Cell] [value]
   (html/content value))

   ;; define a template
   (html/deftemplate mshp "index.html" [cont]
   [:div.Heading] 
   (html/content (for [c (keys (first (:data-content cont)))] (header-cell (name c))))
   [:div.Row] 
   (html/content (map #(value-cell %) (for[e (:data-content cont)] (vals e)))))

So, callling the template in REPL

   (mshp msh-contents)

Produces error: IllegalArgumentException ArityException Wrong number of args (0) passed to: PersistentArrayMap clojure.lang.AFn.throwArity (AFn.java:437), and its probably because snippets produces LazySeq.


Solution

  • This might be really dumb, but the code works perfectly fine for me. The only difference I made was represent your html as hiccup notation then converting to nodes which is equivalent to just giving it a html file(I do this because I still haven't figured out how exactly html-resource works and not sure where I can put the file). Working code below:

    (require '[net.cgrand.enlive-html :as h])
    
    (def msh-contents {:title "Events mashup",
         :data-content [{:title "ICTM Study Group ",  
                                :url "http://some-url.com"} 
                                {:title "Volodja Balzalorsky - Hinko Haas",
                                :url "http://some- other-url.com"}]})
    
    (defn template-div []
      (h/html [:div {:class "Table"}
                    [:div {:class "Title"}
                          [:p "This is a Table"]]
                    [:div {:class "Heading"}
                          [:div {:class "Cell"}
                                [:p "Heading 1"]]]
                    [:div {:class "Row"}
                          [:div {:class "Cell"}
                                [:p "Row 1 Column 1"]]]]))
    
    (defn index []
      (h/html [:html [:div {:class "Table"}
                           [:div {:class "Title"}
                                 [:p "This is a Table"]]
                           [:div {:class "Heading"}
                                 [:div {:class "Cell"}
                                       [:p "Heading 1"]]]
                           [:div {:class "Row"}
                                 [:div {:class "Cell"}
                                       [:p "Row 1 Column 1"]]]]]))
    
    (h/defsnippet header-cell (template-div) [:div.Heading :div.Cell] [value]
                  (h/content value))
    
    (h/defsnippet value-cell (template-div) [:div.Row :div.Cell] [value]
                  (h/content value))
    
    (h/deftemplate mshp (index) [cont]
                   [:div.Heading] 
                   (h/content (for [c (keys (first (:data-content cont)))] (header-cell (name c))))
                   [:div.Row] 
                   (h/content (map #(value-cell %) (for[e (:data-content cont)] (vals e)))))
    

    Final Result:

    (clojure.string/join (mshp msh-contents))
    => "<html><div class=\"Table\"><div class=\"Title\"><p>This is a Table</p></div><div class=\"Heading\"><div class=\"Cell\">title</div><div class=\"Cell\">url</div></div><div class=\"Row\"><div class=\"Cell\">ICTM Study Group http://some-url.com</div><div class=\"Cell\">Volodja Balzalorsky - Hinko Haashttp://some- other-url.com</div></div></div></html>"
    

    Perhaps you're giving defsnippet a bad source when doing (template-div). defsnippet and deftemplate both take nodes. When you give them a file like "index.html", it converts the file into nodes.