Unless things have changed *a lot*, try taking a look at
http://teddyb.org/rlp/tiki-index.php?page=Learning+About+Weblocks#Wrapping_Things_In_Login_Widgets_A_Better_Way
-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/
I think you are getting caught on this:
(defview default-login-view (:type form #|blah blah|#)
(email :requiredp t)
(password #|blah blah|#))
Because you don't provide the :data argument, you get an instance of an
autovivified class created by `class-from-view'. This is a convenience
available for all dataforms that allows you to write forms without also
having to write a class to accept the data if you aren't interested in
keeping the form data in your model (in this example, you usually
extract the two pieces of data and use them to search through a custom
model class)—all you need to to is write a view, and CFV will make and
instantiate the dummy class for you.
The default implementation of CFV calls `make-class' in
utils/runtime-class.lisp. As you can see from that, no reader or writer
GFs are defined.
You have two solutions available: either use `slot-value' or
`with-slots' instead (highly recommended), or elide do-login in your
code, passing the :data argument to make-instance on `login'. Which one
you choose depends on how you store authentication information, but I
think for most people the first fits better. See the slot doc for
`data' in the `login' class definition for more details.
--
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.
That's a fairly standard problem. When I encountered it, it was
because I used a do-* call outside of an action. In fact,
http://teddyb.org/rlp/tiki-index.php?page=Learning+About+Weblocks#Wrapping_Things_In_Login_Widgets_The_Bad_Way
is all about that issue; let me know if that doesn't help so I can
try to make it better.
-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
Unfortunately, I haven't actually done any weblocks in a few weeks.
I notice that you have everything wrapped in lists in the navigation
widget there, which certainly isn't how things used to work, but
maybe it is now; dunno.
Can you post a tarball of the whole thing somewhere?
Clarification:
The new INIT-/MAKE-NAVIGATION supports both ways of specifying the
navigation items: the old way of spliced id/widget pairs
and the new way where an item specifier is a list.
Sorry, got busy.
It definitely wasn't working, and as far as I can tell, you hadn't
failed to use it in any way.
In fact, I have no idea *how* it was working. My best guess is that
the login widget it inherits from would re-render no matter what
happened in :on-login.
I had a version in my tree that I hadn't put in the tutorial that
would expect the child widget to always be a zero-arg lambda, and
run that exactly once; it makes stuff nicer down the road.
Moving the logic for that into check-login gives this patch against
your tarball, which seems to work, and is The Right Thing anyway.
Thanks for giving me chance to clean this up outside of my own work;
I'll go put this new stuff in the tutorial too.
An earlier version simply set dirty in check-login; watching
weblocks freakout was funny, and also very happy-making: style and
error checking *GOOD*:
[2009-03-11 01:30:10 [WARNING]] During the rendering phase, 1 widgets were marked dirty, which should typically be done only during action handling
[2009-03-11 01:30:10 [WARNING]] Warning while processing connection: During the rendering phase, 1 widgets were marked dirty, which should typically be done only during action handling
> I don't know if this issue is already settled, but I too had problems
> using the login widget.
> After reading the related postings, I came up with a rather simple and
> elegant solution (which is a variant of one of those posted here)
> which works for me.
Cool, thanks for fixing this!
Would you like to have this added to contrib/?
Leslie
Cool, thanks for fixing this!
Would you like to have this added to contrib/?
____________________________________________________
Paul Meurer
Research Group for Language Technology
Unifob AS, Department of Culture, Language and Information Technology (AKSIS),
University of Bergen
This is a bug in the new dispatching system.
We will need to fix this before the next release.
Volunteers?
I'm looking at it. It's puzzling -- this can only happen if
update-children was never called for the selector that the navigation is
derived from. This is something that should never happen.
Paul -- any chance you could provide me with a more complete backtrace?
I'd really like to know who called selector-base-uri and when.
--J.
> I'm looking at it. It's puzzling -- this can only happen if
> update-children was never called for the selector that the
> navigation is
> derived from. This is something that should never happen.
>
> Paul -- any chance you could provide me with a more complete
> backtrace?
> I'd really like to know who called selector-base-uri and when.
I tried to reproduce the problem, but it magically disappeared! The
solution to the puzzle is that I had changed two things in the
meanwhile: I used Opera instead of Safari 4 Beta, and I had set
hunchentoot::*default-content-type* to "application/xhtml+xml;
charset=utf-8". Then it works in Opera, but not in Safari or Firefox.
If I set hunchentoot::*default-content-type* back to "text/html; ...",
it doesn't work. I get the following trivial-backtrace: (see below).
If you need, I can set up a minimal test case for you.
...
Description
UNBOUND-SLOT: Slot WEBLOCKS::BASE-URI is unbound in #<NAVIGATION
WEBLOCKS-CLSQL-DEMO::MAIN-MENU>
Date/time: 2009-04-27-20:00
An unhandled error condition has been signalled: Slot WEBLOCKS::BASE-
URI is unbound in #<NAVIGATION WEBLOCKS-CLSQL-DEMO::MAIN-MENU>
(23D8CB8) : 0 (PRINT-BACKTRACE-TO-STREAM #<STRING-OUTPUT-STREAM
#x300042B84A9D>) 101
(23D8CF0) : 1 (PRINT-BACKTRACE #<UNBOUND-SLOT #x300042B9162D> [...])
749
(23D8D88) : 2 (FUNCALL #'#<#<STANDARD-METHOD WEBLOCKS:HANDLE-ERROR-
CONDITION (WEBLOCKS::WEBLOCKS-WEBAPP T)>> #<WEBLOCKS-CLSQL-
DEMO::WEBLOCKS-DEMO #x30004238F24D> #<UNBOUND-SLOT #x300042B9162D>) 3461
(23D8E28) : 3 (FUNCALL #'#<(:INTERNAL (WEBLOCKS:HANDLE-CLIENT-
REQUEST :AROUND (T)))> #<UNBOUND-SLOT #x300042B9162D>) 133
(23D8E60) : 4 (SIGNAL #<UNBOUND-SLOT #x300042B9162D> [...]) 997
(23D8EB8) : 5 (%ERROR #<UNBOUND-SLOT #x300042B9162D> NIL 4698588) 117
(23D8EE0) : 6 (FUNCALL #'#<#<CCL::STANDARD-KERNEL-METHOD SLOT-
UNBOUND (T T T)>> #<WEBLOCKS:WIDGET-CLASS WEBLOCKS:NAVIGATION>
#<NAVIGATION WEBLOCKS-CLSQL-DEMO::MAIN-MENU> 'WEBLOCKS::BASE-URI) 693
(23D8F68) : 7 (FUNCALL #'#<(:INTERNAL CCL::%XERR-DISP)>) 453
(23D8FC0) : 8 (FUNCALL-WITH-ERROR-REENTRY-DETECTION #<COMPILED-
LEXICAL-CLOSURE (:INTERNAL CCL::%XERR-DISP) #x24EA21F>) 181
(23D9000) : 9 (FUNCALL #'#<CCL::%XERR-DISP> 371644550) 493
(23D9038) : 10 (%PASCAL-FUNCTIONS% 2 371644550) 397
*(23D90A0) : 12 (FUNCALL #'#<#<CCL::STANDARD-KERNEL-METHOD SLOT-VALUE-
USING-CLASS (STANDARD-CLASS T STANDARD-EFFECTIVE-SLOT-DEFINITION)>>
#<WEBLOCKS:WIDGET-CLASS WEBLOCKS:NAVIGATION> #<NAVIGATION WEBLOCKS-
CLSQL-DEMO::MAIN-MENU> #<WIDGET-EFFECTIVE-SLOT-DEFINITION for instance
slot WEBLOCKS::BASE-URI #x300041E9C68D>) 849
(23D9120) : 13 (FUNCALL #'#<#<STANDARD-METHOD WEBLOCKS:RENDER-
NAVIGATION-MENU (WEBLOCKS:NAVIGATION)>> #<WIDGET-EFFECTIVE-SLOT-
DEFINITION for instance slot WEBLOCKS::BASE-URI #x300041E9C68D> [...])
197
(23D9180) : 14 (FUNCALL #'#<(:INTERNAL (CLOSER-MOP:COMPUTE-
DISCRIMINATING-FUNCTION (GENERIC-FUNCTION)))> [...]) 141
(23D91B0) : 15 (FUNCALL #'#<(:INTERNAL (CLOSER-MOP:COMPUTE-
DISCRIMINATING-FUNCTION (GENERIC-FUNCTION)))> [...]) 141
(23D91E0) : 16 (FUNCALL #'#<(:INTERNAL (WEBLOCKS:RENDER-WIDGET
(T)))> #<NAVIGATION WEBLOCKS-CLSQL-DEMO::MAIN-MENU> [...]) 133
(23D9200) : 17 (FUNCALL #'#<#<STANDARD-METHOD WEBLOCKS:WITH-WIDGET-
HEADER (T T)>> #<NAVIGATION WEBLOCKS-CLSQL-DEMO::MAIN-MENU> #<Compiled-
function (:INTERNAL #) (Non-Global) #x300041DECC7F> [...]) 2253
(23D9288) : 18 (FUNCALL #'#<(:INTERNAL (CLOSER-MOP:COMPUTE-
DISCRIMINATING-FUNCTION (GENERIC-FUNCTION)))> [...]) 141
(23D92B8) : 19 (FUNCALL #'#<#<STANDARD-METHOD WEBLOCKS:RENDER-WIDGET
(T)>> #<NAVIGATION WEBLOCKS-CLSQL-DEMO::MAIN-MENU> [...]) 965
(23D9320) : 20 (FUNCALL #'#<(:INTERNAL (CLOSER-MOP:COMPUTE-
DISCRIMINATING-FUNCTION (GENERIC-FUNCTION)))> [...]) 141
(23D9350) : 21 (FUNCALL #'#<#<STANDARD-METHOD WEBLOCKS:RENDER-WIDGET-
CHILDREN (WEBLOCKS:WIDGET)>> #<COMPOSITE "6"> [...]) 317
(23D9390) : 22 (FUNCALL #'#<(:INTERNAL (CLOSER-MOP:COMPUTE-
DISCRIMINATING-FUNCTION (GENERIC-FUNCTION)))> [...]) 141
(23D93C0) : 23 (FUNCALL #'#<#<STANDARD-METHOD WEBLOCKS:WITH-WIDGET-
HEADER (T T)>> #<COMPOSITE "6"> #<Compiled-function (:INTERNAL #) (Non-
Global) #x300041DECC7F> [...]) 2253
(23D9448) : 24 (FUNCALL #'#<(:INTERNAL (CLOSER-MOP:COMPUTE-
DISCRIMINATING-FUNCTION (GENERIC-FUNCTION)))> [...]) 141
(23D9478) : 25 (FUNCALL #'#<#<STANDARD-METHOD WEBLOCKS:RENDER-WIDGET
(T)>> #<COMPOSITE "6"> [...]) 965
(23D94E0) : 26 (FUNCALL #'#<(:INTERNAL (CLOSER-MOP:COMPUTE-
DISCRIMINATING-FUNCTION (GENERIC-FUNCTION)))> [...]) 141
(23D9510) : 27 (FUNCALL #'#<#<STANDARD-METHOD WEBLOCKS:RENDER-WIDGET-
CHILDREN (WEBLOCKS:WIDGET)>> #<WIDGET "root"> [...]) 317
(23D9550) : 28 (FUNCALL #'#<(:INTERNAL (CLOSER-MOP:COMPUTE-
DISCRIMINATING-FUNCTION (GENERIC-FUNCTION)))> [...]) 141
(23D9580) : 29 (FUNCALL #'#<#<STANDARD-METHOD WEBLOCKS:WITH-WIDGET-
HEADER (T T)>> #<WIDGET "root"> #<Compiled-function (:INTERNAL #) (Non-
Global) #x300041DECC7F> [...]) 2253
(23D9608) : 30 (FUNCALL #'#<(:INTERNAL (CLOSER-MOP:COMPUTE-
DISCRIMINATING-FUNCTION (GENERIC-FUNCTION)))> [...]) 141
(23D9638) : 31 (FUNCALL #'#<#<STANDARD-METHOD WEBLOCKS:RENDER-WIDGET
(T)>> #<WIDGET "root"> [...]) 965
(23D96A0) : 32 (FUNCALL #'#<(:INTERNAL (CLOSER-MOP:COMPUTE-
DISCRIMINATING-FUNCTION (GENERIC-FUNCTION)))> [...]) 141
(23D96D0) : 33 (FUNCALL #'#<(:INTERNAL WEBLOCKS::RENDER-ENQUEUED
WEBLOCKS::RENDER-DIRTY-WIDGETS)> '(#<# #> #<# #>)) 237
(23D9710) : 34 (FUNCALL #'#<(:INTERNAL WEBLOCKS::ABSORB-DIRTY-
WIDGETS WEBLOCKS::RENDER-DIRTY-WIDGETS)>) 277
(23D9758) : 35 (RENDER-DIRTY-WIDGETS) 237
(23D9798) : 36 (FUNCALL #'#<#<STANDARD-METHOD WEBLOCKS:HANDLE-CLIENT-
REQUEST (WEBLOCKS::WEBLOCKS-WEBAPP)>> #<WEBLOCKS-CLSQL-DEMO::WEBLOCKS-
DEMO #x30004238F24D>) 5293
(23D9900) : 37 (%CALL-NEXT-METHOD '(NIL #<#> . 4698950) [...]) 1021
(23D9980) : 38 (FUNCALL #'#<#<STANDARD-METHOD WEBLOCKS:HANDLE-CLIENT-
REQUEST :AROUND (T)>> #<WEBLOCKS-CLSQL-DEMO::WEBLOCKS-DEMO
#x30004238F24D>) 509
(23D99D0) : 39 (%%STANDARD-COMBINED-METHOD-DCODE '(#<#> #<#>)
4698950) 741
(23D9A40) : 41 (FUNCALL #'#<(:INTERNAL (CLOSER-MOP:COMPUTE-
DISCRIMINATING-FUNCTION (GENERIC-FUNCTION)))> [...]) 165
(23D9A78) : 42 (FUNCALL #'#<#<STANDARD-METHOD HUNCHENTOOT:PROCESS-
REQUEST (T)>> #<HUNCHENTOOT:REQUEST #x300042A9ED9D>) 1269
(23D9B60) : 43 (FUNCALL #'#<#<STANDARD-METHOD HUNCHENTOOT:PROCESS-
CONNECTION (HUNCHENTOOT:ACCEPTOR T)>> #<WEBLOCKS-ACCEPTOR (host *,
port 8080)> #<USOCKET:STREAM-USOCKET #x300042A9C78D>) 2133
(23D9C88) : 44 (%CALL-NEXT-METHOD '(NIL #<#> . 4699092) [...]) 1021
(23D9D08) : 45 (FUNCALL #'#<#<STANDARD-METHOD HUNCHENTOOT:PROCESS-
CONNECTION (WEBLOCKS:WEBLOCKS-ACCEPTOR T)>> #<WEBLOCKS-ACCEPTOR (host
*, port 8080)> #<USOCKET:STREAM-USOCKET #x300042A9C78D>) 93
(23D9D50) : 46 (%CALL-NEXT-METHOD '(NIL #<#> . 4699092) [...]) 1021
(23D9DD0) : 47 (FUNCALL #'#<#<STANDARD-METHOD HUNCHENTOOT:PROCESS-
CONNECTION :AROUND (HUNCHENTOOT:ACCEPTOR T)>> #<WEBLOCKS-ACCEPTOR
(host *, port 8080)> #<USOCKET:STREAM-USOCKET #x300042A9C78D>) 517
(23D9E40) : 48 (%%STANDARD-COMBINED-METHOD-DCODE '(#<#> #<#> #<#>)
4699092) 741
(23D9EB8) : 50 (RUN-PROCESS-INITIAL-FORM #<PROCESS Hunchentoot
worker (client: 127.0.0.1:61229)(118) [Active] #x300042A9C1ED> '(#)) 717
(23D9F48) : 51 (FUNCALL #'#<(:INTERNAL CCL::%PROCESS-PRESET-
INTERNAL)> #<PROCESS Hunchentoot worker (client: 127.0.0.1:61229)(118)
[Active] #x300042A9C1ED> '(#)) 397
(23D9F98) : 52 (FUNCALL #'#<(:INTERNAL CCL::THREAD-MAKE-STARTUP-
FUNCTION)>) 293
---
- Paul
> Hi,
>
>> I'm looking at it. It's puzzling -- this can only happen if
>> update-children was never called for the selector that the navigation
>> is derived from. This is something that should never happen.
>>
>> Paul -- any chance you could provide me with a more complete
>> backtrace?
>> I'd really like to know who called selector-base-uri and when.
>
> I tried to reproduce the problem, but it magically disappeared! The
> solution to the puzzle is that I had changed two things in the
> meanwhile: I used Opera instead of Safari 4 Beta, and I had set
> hunchentoot::*default-content-type* to "application/xhtml+xml;
> charset=utf-8". Then it works in Opera, but not in Safari or Firefox.
> If I set hunchentoot::*default-content-type* back to "text/html; ...",
> it doesn't work. I get the following trivial-backtrace: (see below).
Thanks, this backtrace explains things very well. But I don't think this
has much to do with *default-content-type*.
The problem is that after you log in, the login widget gets replaced
with a navigation widget in an AJAX request. Then weblocks tries to
render the dirty widgets, which include the navigation widget. However,
the navigation widget does not know what its base-uri is, because it was
never accessed with an URI before. It suddenly got dropped in and tree
shakedown wasn't performed.
I don't know what the correct solution is here. It is not something I
expected when I wrote the new navigation code. I'll keep thinking, in
the meantime any suggestions are welcome.
--J.
I haven't investigated this deeply but have two mutually
exclusive proposals:
1) make navigation (or was it selector here?) more resilient
by detecting a missing base uri. In this case the base URI
and the remaining tokens should be inferred from the parent
trail of dispatchers and the children set appropriately.
I'm not sure how well this would work outside of the theory
domain.
2) perform an explicit tree reconfiguration after the insert
(SETF WIDGET-CHILDREN) of a child of type dispatcher has
been detected.
Both solutions are too complex for my taste -- I'd rather look harder
for a simpler way out.
How about getting rid of the base-uri slot altogether? That way,
navigation would render relative URLs, code would be simpler, and would
work better.
The only other use for base-uri is code that redirects to the first pane
if no default pane was provided. I do not think we can redirect to a
relative URL, but I don't see a big need for this functionality. And
perhaps someone can think of a solution not involving base-uri here?
--J.
The current base URI might be useful for more elaborate purposes
(building links, specifically). But let us get rid of BASE-URI
and think of another solution later as needed.
But what worries me is how the flow-introduced nav will decide
on its children if it's not instructed specifically to do so.
The current code might account for that, of course; I haven't
checked.
Ok, I finally got around to this. This is not an obvious fix,
unfortunately.
One thing is that base-uri is unnecessary in my opinion and we should
get rid of it. Relative links should be used whenever possible
anyway. If anybody has a good use for base-uri (or needs absolute links
in navigation widgets), please speak up now.
> But what worries me is how the flow-introduced nav will decide
> on its children if it's not instructed specifically to do so.
That is a more significant issue.
> The current code might account for that, of course; I haven't
> checked.
It does not. I always assumed that actions would not perform major tree
modifications and a full tree shakedown would not be required. Now that
I think of it, it was an incorrect assumption. There could be many cases
when you will need to shake down the tree and determine exactly what the
children are all the way down.
Here's what I propose (please comment);
1. Get rid of base-uri.
2. Perform a tree shakedown (call update-widget-tree) on both normal
requests and AJAX requests. I don't fully understand how the URI could
change here, but I assume we can just process the uri-tokens as usual.
--J.
> 1. Get rid of base-uri.
>
> 2. Perform a tree shakedown (call update-widget-tree) on both normal
> requests and AJAX requests. I don't fully understand how the URI could
> change here, but I assume we can just process the uri-tokens as usual.
Yes, I don't think that we will encounter surprises here because
the AJAX client code sends the correct URI.
Intriguingly I just took a look at the old nav code and it seems
that this issue wasn't really accounted for either.
From what I gathered it just happened to work for nav widgets sitting
at /.
Leslie
> A project I'm helping with is running into this problem, too.
>
> If anyone has a work-around or unofficial patch that I could use while
> we wait for a fix to be committed to weblocks-dev, that would be
> helpful.
Jan, what's your status here?
Matthew, you might get away with just removing code pertaining to
BASE-URI.
If Jan says that he won't be able to fix it within the next few
days I will take over.
Sorry. I'll have a patch out by tomorrow.
--J.
Actually, having looked into the problem, I'm looking for feedback on
the following points (thoughts):
-- a quick fix for the base-uri problem is to redirect after the action
(or issue a non-ajax request), this will cause a full request, the
tree will be updated and everything will work,
-- this kind of tree modification will only work if it doesn't have to
modify the URI, so in most cases you will be redirecting or doing a
full request anyway,
-- if we enable the possibility of swapping in navigation widgets in
AJAX actions, we need to do a tree shakedown on every request
(including AJAX requests),
-- the URI of an AJAX request is not something we can rely on (there is
a comment about w3m in make-action-url?),
-- so in order to support AJAX swapping of navigation widgets we would
have to remember the last "normal" request URI and use that to do the
tree shakedown. I'm having second thoughts about whether this is
something we want to do.
My main point is that there are very few cases where you swap in a
navigation widget in an AJAX request (without changing the URI), so I am
not sure if we want to build machinery to support that and run a tree
shakedown on every AJAX request. Perhaps it is enough to document it and
tell everyone to set :ajaxp nil when they are about to modify the
navigation hierarchy in the tree?
Thoughts? Comments? Am I way off?
--J.
> My main point is that there are very few cases where you swap in a
> navigation widget in an AJAX request (without changing the URI), so I am
> not sure if we want to build machinery to support that and run a tree
> shakedown on every AJAX request. Perhaps it is enough to document it and
> tell everyone to set :ajaxp nil when they are about to modify the
> navigation hierarchy in the tree?
That does sound like an acceptable solution.
But I don't understand why we'd have to do a tree shakedown on
every AJAX request because of this. Wouldn't it suffice to do so
when a selector widget enters another widget's children list?
But how do you determine that without walking the entire tree?
--J.
>> But I don't understand why we'd have to do a tree shakedown on
>> every AJAX request because of this. Wouldn't it suffice to do so
>> when a selector widget enters another widget's children list?
>
> But how do you determine that without walking the entire tree?
(setf widget-children) could check whether a genuinely new
widget that is a selector has entered the children list
and schedule a tree walk accordingly.