- -----------
(defmethod render-widget-body ((self my-widget) &rest args)
(render-link
(lambda (&rest args)
(declare (ignore args))
(let ((comp (make-instance
'composite
:widgets (list
(lambda ()
(render-link
(lambda (&rest args)
(answer self))
"Test Back"))))))
(do-widget self comp)))
"Test Button"))
- -----------
What *used* to happen (like, a few days ago) was that "Test Button"
would appear as a link. If you clicked on it, "Test Back" would
appear, and if you cilck on that "Test Button" would reppear.
Today, when you click on "Test Button", nothing whatsoever happens.
Even this simplified version doesn't work:
- ---------
(defmethod render-widget-body ((self agreement-bits) &rest args)
(render-link
(lambda (&rest args)
(declare (ignore args))
(let ((comp (make-instance
'composite
:widgets (list "Test Plain"))))
(do-widget self comp)))
"Test Button"))
- ---------
Again, nothing happens when you cilck on "Test Button".
I don't know if this is something I've changed in my own code
somewher, or something that has changed elsehwere in Weblocks (I'm
keeping up with -dev for the most part), but any pointers would be
most welcome.
-Robin
--
They say: "The first AIs will be built by the military as weapons."
And I'm thinking: "Does it even occur to you to try for something
other than the default outcome?" -- http://shorl.com/tydruhedufogre
http://www.digitalkingdom.org/~rlpowell/ *** http://www.lojban.org/
*sigh*
Every time I was rendering the widget containing the broken ones, it
was creating new sub-widgets, which started in the initial state.
D'oh.
Erm, no, that wasn't it.
I've commented *everything* out; my entire application is now:
(make-navigation
; FIXME: used to be (class "upper-right") (id "upper-right")
'main-menu
'home (make-instance
'composite
:widgets (list
(lambda ()
(format t "recreation.~%")
"foo"))))
Every time I hit reload, "recreation." gets printed. Every time.
I'm really pretty certain that's wrong; you can't have state stored
in the widgets if they get recreated on every single user action.
Help?
Right you are; there was a single function in the way. Just to be
extra clear then:
- -------------------
(defun init-user-session (comp)
(setf (composite-widgets comp)
(make-navigation
'main-menu
'home (make-instance
'composite
:widgets
(lambda ()
(format t "recreation.~%")
(list
"foo"))))))
- -------------------
I also flipped tha lambda and the list, just to be extra clear.
> If it's in INIT-USER-SESSION then it's working correctly. The
> composite gets spawned exactly once when the session is created.
You'd think so, but that doesn't seem to actually be the case. As I
said, every time I hit reload, "recreation." gets printed out. That
*must* mean the composite widget is getting recreated every time I
hit reload. That's not OK.
And the moral of the story is: lambdas as widgets get re-run on
every render, which means that if you want persistent widgets,
(make-instance
'composite
:widgets (list
(lambda ()
(render-list
(make-instance 'foo)))))
will not do what you want.
Sorry to waste people's time.
Time to go off and make a render-list widget. :)
* datalist
* listedit (datalist + dataedit-mixin)
* dataseq's on-query slot lets you bypass the store API
Also, some presentation code that you may like:
;;;; A stripped-down view-only single-field dataform
(defwidget singledata (weblocks:widget)
((data :initarg :data :initform nil :accessor singledata-data
:documentation "The item to render.")
(view :initarg :view :initform nil
:documentation "The view used to render the item. Defaults
to the scaffold view."))
(:documentation "Show a single view."))
(defwidget closeable-singledata (singledata)
()
(:documentation "Like `singledata', but also provide a Close
button."))
(defgeneric singledata-view (widget)
(:method ((widget singledata))
(or (slot-value widget 'view)
(weblocks:find-view
(list 'data (class-name-of (singledata-data widget)))))))
(defgeneric (setf singledata-view) (new-value widget)
(:method (new-value (widget singledata))
(setf (slot-value widget 'view) new-value)))
(defmethod weblocks:render-widget-body ((widget singledata) &key &allow-other-keys)
(weblocks:render-object-view
(singledata-data widget) (singledata-view widget) :widget widget))
(defmethod weblocks:render-widget-body :after
((self closeable-singledata) &key &allow-other-keys)
"Show said close button."
(with-html
(:div :class "operations"
(weblocks:render-form-and-button
"Close" (f_% (weblocks:answer self))))))
(defclass single-field-view (weblocks:data-view)
()
(:documentation "Render a single field and leave off all the chrome
for lists of fields."))
(defclass single-field-view-field (weblocks:inline-view-field)
()
(:documentation "Default field type for `single-field-view'.
This is just here to make the view compiler happy."))
--
I write stuff at http://failex.blogspot.com/ now. But the post
formatter and themes are terrible for sharing code, the primary
content, so it might go away sooner or later.
All of those are for presenting lists of data objects, whereas I
want to present a list of widgets. I suppose I could just use
composite, but I actually wanted the ul wrapping visually.
> Also, some presentation code that you may like:
>
> ;;;; A stripped-down view-only single-field dataform
Hey! Thanks! I started to write that but ended up not actually
using it, but I'm sure I will in the future.
This is what I would suggest, given the need to render separate widgets.
A "render-list" function cannot take advantage of all the machinery of
`composite' that is already in place, such as replacement in flow and
path finding.
(defclass list-composite (composite)
()
(:documentation "Render subwidgets in a UL."))
(defmethod render-widget-body ((obj list-composite) &rest args)
(with-html
(:ul (dolist (wij (composite-widgets obj))
(htm (:li (render-widget wij)))))))
If your reason for thinking of a `render-list' function before this was
so render-list calls could be tossed into rendering functions with other
things to be rendered, try to consider the overall widget as a composite
containing a list-composite alongside other widgets to contain the other
things.
And, in fact, what I did, although I subclassed widget rather than
composite; *shrug*.
-Robin
--
They say: "The first AIs will be built by the military as weapons."
And I'm thinking: "Does it even occur to you to try for something
[snip]
> (defgeneric singledata-view (widget)
> (:method ((widget singledata))
> (or (slot-value widget 'view)
> (weblocks:find-view
> (list 'data (class-name-of (singledata-data widget)))))))
Neither sbcl nor google seem to have any idea of what class-name-of
is.
Oops, that's from arnesi.