Hi Dave,
Perhaps an overview of one way of building a Seaside web app will help. I'm not a Seaside expert but I am working on a Seaside project at the moment. I think it was Joachim who put me on to this approach a few years ago when I first started working with Seaside, so if you like it, he deserves the credit, if not lay the blame with me.
Create your own sub-class of WASession - to hold session state data.
Create your own root component - so Seaside will flow through it to render you web pages.
I divide each web page into three parts. A top/header/logo section, a work region and a bottom or footer section. If the the top and bottom sections are complex enough, they should be components. There should be a work region component for each page of your web app. In your session object make a way to keep track of your work region components and which one is the current one to render. You can do this anyway you like.
I usually sub-class WAObject and make it like something called XXXCurrentComponents and have the session object hold an instance. It contains a lookup table keyed by symbols used to name each web page. The values are the components that render those pages. Again it keeps track of the current page to render and maybe the last page rendered among other stuff.
Seaside will run through #renderContentOn: of your root components every time it wants to render a page.
In the #renderContentOn: of your root, you render the top. work region and bottom of the page like so:
wrc := self getWorkRegionComponentFromSession.
html render: self logoComponent.
html render: wrc.
html render: self footerComponent.
or if your top and bottom parts are not too complex, they can be rendered from methods in the root:
wrc := self getWorkRegionComponentFromSession.
self renderLogoOn html.
html render: wrc.
self renderFooterOn: html.
Now to get to your question. Often, Seaside web apps get data from the web pages they render and the flow of the app may be controlled by that data and the button pushed or whatever resulted in a submit. For this, I like buttons over anchors. Seaside will set the URL up to come back to your app. The callbacks on the buttons will run code you want run for that button. This code is normally a method of your component that rendered the button and the data fields. This is nice because the data is right there for you to do what you want with it. At the end of whatever you are doing, you tell you session object or the object holding the components, what component (page) you want to render next. You then fall out the end of the method. Seaside will do what it wants to and then go back through your root component (#renderContentOn:). The next page is rendered and the app flows on.
For example, lets say you have a page with among other things has three buttons, A, B and a cancel button. You might render them like so:
html submitButton value: 'A'; callback: [self doA].
html submitButton value: 'B'; callback: [self doB].
html cancelButton value: 'Cancel'; callback: [self doCancel].
The method #doA might end by setting up to move on to page "A".
The method #doB might end by setting up to move on to page "B". The method #doCancel might end by setting up to move back to the previous page.
Note, that with the components saved in the lookup table, the state of the app and each page is maintained if your app wants to go back to a previous page. This often means that the user should not use the web browser back button but that is up to your app care about and deal with if it is a problem.
With the above approach you can use anchors to flow your app but I think buttons of whatever causes a submit are easier to deal with.
Also note that HTML doesn't have a cancel button but Seaside does. It is a submit button with the callback set to a priority that gets the callback run before all the other callbacks (somewhat hidden ones for input fields). This allows Seaside to cancel updating your object that the input fields are connected to.
Well this is long enough, I hope it helps.
Lou