[Seaside] anchors behaving like buttons?

Nevin Pratt nevin at smalltalkpro.com
Fri Jun 13 18:29:28 CEST 2003


I've just updated our site to the latest SqueakMap version of Seaside.

However, the scheme I wrote about below no longer works for targeting 
different entry points into the app.

For example, if the browser URL is:
   http://localhost/seaside/foo/red
then the 'path' variable in step #4 should return '/seaside/foo/red', so 
that I can invoke the #red method on the 'foo' component as explained in 
step #4.

But with this release, 'path := self session path' in step #4 just 
returns '/seaside/foo'.  Thus, I have no idea what method of the 'foo' 
component the URL intends to invoke.

This forces me to have a single entry point into each component of the 
app, which forces me to rearchitect somewhat (unless I can find an 
alternative way to recreate the old behavior).

For example, when I wanted to give someone a URL that would take them 
directly to our 'View Cart' page, I would email them this:

   http://www.bountifulbaby.com/seaside/index/viewcart

This would invoke the #viewcart method of the 'index' component, which 
would then take them to the shopping cart.

I suppose I could create a separate 'viewcart' entry point into the app 
via '/seaside/config', but I quite liked having the ability to invoke 
arbitrary methods on a component via the URL.

Any suggestions?

Nevin


************************
************************
Derek Brans wrote:

> In Seaside, is there a way to have an anchor tag that will submit a 
> form and perform an action (behaving just like a button)?
>

I've got a scheme that seems to work OK:

Suppose you've got a component 'Foo', with launch URL of 
'http://localhost/seaside/foo' (or whatever machine and port you 
choose).  Now, suppose the 'Foo' component has links 'red' and 'green' 
in the GUI, which you want to use to invoke methods #red and #green on 
component Foo when the links are clicked on.

1. Define the URL for the 'red' link to be '/seaside/foo/red', and for 
the 'green' link to be '/seaside/foo/green'.

2. Give 'Foo' an instance variable called 'targets', and then create an 
#initialize method of 'Foo' thus:

  initialize
      targets _ OrderedCollection new.
      targets add: #red;
           add: #green

3. Give 'Foo' a 'lastTarget' instance variable, which will be used to 
prevent recursive circularities, as shown later.

4. Put the following in Foo's #renderContentOn:

  renderContentOn: html
      | path sel |
      path _ self session path.
      sel _ (path copyAfterLast: $/) asLegalSelector asSymbol.
      (lastTarget ~= sel
           and: [targets includes: sel])
       ifTrue: [lastTarget _ sel.
           ^self perform: sel].
     { ... the rest of the normal rendering code here ... }

With the above, the 'red' and 'green' links will invoke the #red and 
#green target methods (respectively) of the component, just like a 
button does.

You can, if you wish, easily eliminate the need for the 'targets' 
instance variable by, for example, looking for methods within a certain 
method category, or for methods that begin (or end) with some common 
string, or even be more general by replacing 'targets includes: sel' 
with something like 'self respondsTo: sel', but I think I would prefer 
to keep strict control over what methods can be invoked via the URL with 
this scheme.  So, I would use a 'targets' instance variable to 
explicitly define allowable methods that can be invoked with this scheme.

Nevin


_______________________________________________
Seaside mailing list
Seaside at lists.squeakfoundation.org
http://lists.squeakfoundation.org/listinfo/seaside





More information about the Seaside mailing list