Navigation, back button and action

7 views
Skip to first unread message

Tim

unread,
Sep 26, 2009, 9:42:58 AM9/26/09
to weblocks
Hello,

I wrote the following code:

(defun init-user-session (comp)
(setf (widget-children comp)
(make-navigation 'main-menu
(list "First" (make-first) "first")
(list "Second" (make-widget 2) "second"))))

(defun make-first ()
(let ((w (make-instance 'widget)))
(setf (widget-children w)
(list (make-widget 1)
(lambda ()
(render-link (lambda (&rest args)
(declare (ignore args))
(with-flow w
(yield (make-widget 3))))
"Third"))))
w))

I use the back button on the second widget, then click on the action
link and see the second widget again. I would like to see a third
widget. What am I missing?

Thanks,

Tim

Leslie P. Polzer

unread,
Sep 29, 2009, 1:11:29 PM9/29/09
to weblocks

Hi Tim,

On Sep 26, 3:42 pm, Tim <tym...@gmail.com> wrote:

> I use the back button on the second widget, then click on the action
> link and see the second widget again. I would like to see a third
> widget. What am I missing?

Sorry I haven't got around to check out your problem here. I'll try to
do so within the next few days.

Leslie

nunb

unread,
Sep 30, 2009, 3:05:53 AM9/30/09
to weblocks
Could you explain what exactly you are trying to do?

Is it:

1. Make a navigation, and have each widget in the navigation capable
of flowing out to another and back.
2. Have the navigation links themselves start a flow?

nunb

unread,
Sep 30, 2009, 3:44:39 AM9/30/09
to weblocks
Well, after looking at that code I saw a few things that seemed
wrong.

1. If you want to render a link that starts a flow, use lambda/cc to
signal cl-cont to do its job.
2. Don't ignore the args in your render-link lambda, that's where the
continuation parameter k gets passed (details not important, unless
I'm totally mistaken!).
3. For preference, I do not use lambda's with flows. A simple widget
is always better imho, because it takes care of the continuation-
passing without having to futz around with K parameters (for the
continuation) since widgets store continuations in a slot. There's a
previous post regarding flows/continuations that has some code on
paste.lisp.org -- it may help to look at that too.

> I use the back button on the second widget, then click on the action
> link and see the second widget again.

IMO this should not be possible. The action link should have nothing
to do with the widget that was declared as part of a navigation (ie,
the 2nd widget).

This is what I tried:

1. Nav with two children 1st and 2nd.
2. 1st has a link for a with flow, yielding 3rd.

Results:

Flowing from 1st to 3rd works. Going to 2nd and using back button
brings one back to the 1st widget (whether in a state of having flowed
out to 3, or pre-flow).

The code is below, but since I'm on the old version of weblocks
(before nav and composites change) perhaps my code will be confusing,
so caveat lector.

Also, here's a short screencast showing what happens in the browser.
It's divided at the point I realized there needed to be a return from
widget 3 (back button does not work to return from continuations) and
oh, the CSS is screwed up. Nav menu is the stuff under "LaGru".

Code:


(defun init-user-session (comp)
(setf (composite-widgets comp)
(let ((main-nav (make-instance 'main-navigation :name
"LaGru")))
(init-navigation main-nav
'First (make-first)
'Second (make-widget 2))
(wrap-in-composite main-nav))))

(defun make-first ()
(let ((w (make-instance 'composite)))
(setf (composite-widgets w)
(list (make-widget 1) ; OK this works
(make-instance 'simple-widget
:render-fn
(f_
(with-html
(render-link (lambda/cc (&rest args)
(with-flow _
(yield (make-answering-widget 3))))
"Third"))))))
w))


(defun make-answering-widget (arg)
(make-instance 'simple-widget
:render-fn
(f_
(with-html (str (format nil "This is widget ~A " arg))
(when (widget-continuation _)
(render-link (f_% (answer _))
" (return from cont) "))))))

(defun make-widget (arg)
(make-simple-message-2 (format nil "ARGE ~A" arg)))

(defun make-simple-message-2 (astr)
(make-instance 'simple-widget
:render-fn (closure (with-html (:div :class "error" (str astr))))))


(defwidget simple-widget ()
((var :accessor get-var :initarg :var)
(render-fn :accessor render-fn :initarg :render-fn :initform
(constantly nil))))

(defmethod render-widget-body ((widget simple-widget) &rest args)
(funcall (render-fn widget) widget))

nunb

unread,
Sep 30, 2009, 5:02:22 AM9/30/09
to weblocks

Tim

unread,
Sep 30, 2009, 6:01:17 PM9/30/09
to weblocks
On Sep 29, 9:11 pm, "Leslie P. Polzer" <leslie.pol...@gmx.net> wrote:
> Sorry I haven't got around to check out your problem here. I'll try to
> do so within the next few days.

Thanks for your reply.
Neither first nor second. I just want to use the action with
continuation after pressing the back button.

On Sep 30, 11:44 am, nunb <nandan.bagc...@gmail.com> wrote:
> Well, after looking at that code I saw a few things that seemed
> wrong.
>
> 1. If you want to render a link that starts a flow, use lambda/cc to
> signal cl-cont to do its job.

with-flow macro uses lambda/cc to start a flow. I can rewrite my make-
first function this way, but this change nothing:

(defun make-first ()
(let ((w (make-instance 'widget)))
(setf (widget-children w)
(list (make-widget 1)
(lambda ()
(render-link (lambda/cc (&rest args)
(declare (ignore args))
(do-widget w (lambda (k)
(declare (ignore k))
(render-widget (make-widget 3)))))
"Third"))))
w))

> 2. Don't ignore the args in your render-link lambda, that's where the
> continuation parameter k gets passed (details not important, unless
> I'm totally mistaken!).

There is no continuation parameter, because there is no continuation.

> This is what I tried:
>
> 1. Nav with two children 1st and 2nd.
> 2. 1st has a link for a with flow, yielding 3rd.
>
> Results:
>
> Flowing from 1st to 3rd works. Going to 2nd and using back button
> brings one back to the 1st widget (whether in a state of having flowed
> out to 3, or pre-flow).
>
> The code is below...

What your code do is not what I want. You replace not the first widget
but the children of the first widget. Try this and you will see my
problem:

(defun make-first ()
(let ((w (make-instance 'composite)))
(setf (composite-widgets w)
(list (make-widget 1)
(make-instance 'simple-widget
:render-fn
(f_
(with-html
(render-link (lambda/cc (&rest args)
(with-flow w ; I have changed underscore with w
(yield (make-answering-widget 3))))
"Third"))))))
w))

On Sep 30, 1:02 pm, nunb <nandan.bagc...@gmail.com> wrote:
> screencast:http://www.youtube.com/watch?v=zQkxxUcHzxg

By the way, the screencast is not available.

I think that after pressing back button and calling the action the
first widget cannot be found in the navigation. This widget has become
invalid since the closure was created. Am I right?

I wrapped first widget in another widget. This code works:

(defun make-first ()
(let ((w (make-instance 'widget)))
(setf (widget-children w)
(list (make-widget 1)
(lambda ()
(render-link (lambda (&rest args)
(declare (ignore args))
(with-flow w
(yield (make-widget 3))))
"Third"))))
(make-instance 'widget
:children (list w))))

Thanks,

Tim

Leslie P. Polzer

unread,
Oct 1, 2009, 2:25:19 AM10/1/09
to weblocks
On Oct 1, 12:01 am, Tim <tym...@gmail.com> wrote:

> I think that after pressing back button and calling the action the
> first widget cannot be found in the navigation. This widget has become
> invalid since the closure was created. Am I right?

The back button should have nothing to do with this, actually.

Have you tried reproducing this in a case where the back button
is not involved at all? It should fail too.


> I wrapped first widget in another widget. This code works:

Interesting. This used to be necessary since the DO-WIDGET code
(which is what the WITH-FLOW expands to) knew only how to
replace widgets in simple parent containers (of 'composite' class
then).

The current code should work with all widgets however, so there's
a bug, probably in MAKE-WIDGET-PLACE-WRITER.

I'm going to fix that.

In the meantime thanks for pointing out; the current dev head
definitely needs more testing of that kind.

Leslie

Leslie P. Polzer

unread,
Oct 1, 2009, 3:40:31 AM10/1/09
to weblocks
Related test:

* replace a widget in a nav. New widget gets displayed properly via
AJAX.
* reload the page; the old widget is there again.

Leslie P. Polzer

unread,
Oct 1, 2009, 5:50:10 AM10/1/09
to weblocks
Fixed in 3d4834d18aa8:

http://bitbucket.org/S11001001/weblocks-dev/changeset/3d4834d18aa8/

Tim, your original problem was indeed related to the back button and
should
be solved as of 9773e8121f34:

http://bitbucket.org/S11001001/weblocks-dev/changeset/9773e8121f34/

Cheers,

Leslie
Reply all
Reply to author
Forward
0 new messages