I wanted to make the logo we had in the lop right corner a link that takes the user to the homepage. Pretty standard, right? However, passing (with-html (:img :id "logo" :src "/pub/images/logo-dollar.png")) to render-link as the last argument didn't work. Searching the weblocks google group confirmed that render-link only takes strings. I found this thread.
Jan Rychter asked:
And another question: how do I make the following work?
(with-html (:p (render-link #'some-function (:img :src "somewhere.png"))))
I worked around the problem by wrapping the :img in a
(cl-who:with-html-output-to-string), but there must be a better way?
--J.
Slava replied:
> (with-html (:p (render-link #'some-function (:img :src "somewhere.png"))))
Currently render-link is a function that expects a string for the link
contents. You'd have to hack it a little to accept cl-who code (it
would have to be turned into a macro). If you do this, please send me
a patch :)
Lucky for me, later in the thread Evan Monroig gave a solution:
Hi,
I just needed this functionality and made a macro for it, then found
this post. So here it is.
http://paste.lisp.org/display/56069
(in-package :weblocks)
(export 'with-render-link)
(defmacro with-render-link ((action &key (ajaxp t) id class) &body
body)
"same as RENDER-LINK but executes body inside the A tag"
;; Note: it is important to protect action against multiple
;; evaluation here as the closure might be computed two times due to
;; the IF clause. I also protected all variables against capture,
;; multiple evaluation and maintained a correct evaluation order
(with-unique-names (action-code url action-var id-var class-var
ajaxp-var)
`(let ((,action-var ,action)
(,ajaxp-var ,ajaxp)
(,id-var ,id)
(,class-var ,class))
(if ,action-var
(let* ((,action-code (function-or-action->action
,action-var))
(,url (make-action-url ,action-code)))
(with-html
(:a :id ,id-var :class ,class-var
:href ,url :onclick (when ,ajaxp-var
(format nil "initiateAction(\"~A\", \"~A\"); return false;"
,action-code
(session-name-string-pair)))
,@body)))
,@body))))
;; example use
#+nil
(with-html
(:div
(with-render-link ((lambda (&rest args)
(declare (ignore args))
(do-something)))
(render-widget some-widget))))
I love that Evan's code included an example, so I actually knew how to use it. My code ended up being:
(with-render-link ((lambda (&rest args)
(declare (ignore args))
(do-page (make-main-page))))
(with-html (:img :id "logo" :src "/pub/images/logo-dollar.png"))))