3

Is it possible to append a value to an attribute using enlive?

example: I have this

<a href="/item/edit/">edit</a>

and would like this

<a href="/item/edit/123">edit</a>

I am currently doing this:

(html/defsnippet foo "views/foo.html" [:#main]
  [ctxt]
  [:a] (html/set-attr :href (str "/item/edit/" (ctxt :id))))

But I would prefer not to embed the URL into my code, by just appending the id to the existing URL

(html/defsnippet foo "views/foo.html" [:#main]
  [ctxt]
  [:a@href] (html/append (ctxt :id)))
Xian
  • 76,121
  • 12
  • 43
  • 49
  • I haven't found a good way to ahev selectors extend to attributes in enlive but I'd like to. – cgrand Oct 02 '12 at 08:52

2 Answers2

6

@ddk answer is spot on but you may prefer a more generic way to solve the problem

(defn update-attr [attr f & args]
    (fn [node]
      (apply update-in node [:attrs attr] f args))))

and then

(update-attr :href str "123")
cgrand
  • 7,939
  • 28
  • 32
5

You could always write your own append-attr in the same vein as set-attr. Here is my attempt

(defn append-attr
  [& kvs]
    (fn [node]
      (let [in-map (apply array-map kvs)
            old-attrs (:attrs node {})
            new-attrs (into {} (for [[k v] old-attrs] 
                                    [k (str v (get in-map k))]))]
        (assoc node :attrs new-attrs))))

Which gives the following, when appending "/bar" to href, on enlive's representation of <a href="/foo">A link</a>

((append-attr :href "/bar") 
  {:tag :a, :attrs {:href "/foo"}, :content "A link"})
;=> {:tag :a, :attrs {:href "/foo/bar"}, :content "A link"}
ddk
  • 1,813
  • 1
  • 15
  • 18
  • Thanks for this.. was hoping that there might be something I was just missing. Will mark this as solution if no one else knows anything magical :) – Xian Sep 25 '12 at 22:16