Anchors

David Shaffer
Shaffer Consulting

Basics

Anchors (links) are used for several purposes including navigating to other documents and performing actions (removing an item from a list, for example). In Seaside, when we create anchors we specify an action block much like a GUI application callback. When the user follows the anchor our callback is invoked. This block can perform any of the actions discussed above. We haven't discussed how to display other components yet (I'm saving that for another unit) but we can use WAComponent>>inform: to display a simple message for the user. Here's an example:
renderContentOn: html
	html anchorWithAction: [self sayHello] text: 'Say hello'.
Basically this tells the renderer to create an anchor and execute our block when that anchor is followed. Here's an implementation of sayHello:
sayHello
	self inform: 'Hello!'
Now play with the application in your web browser. Don't worry about just how inform: works...its effect is obvious. Note that when the OK button is pressed our original component is displayed.

Quite often an anchor's action just changes the state of the component and returns. That is, it doesn't display anything itself. There are lots of examples of this in the code included with Seaside. Look at WACounter, for example. There is already an excellent tutorial on WACounter so I'll just show a simple example of changing a string displayed by our component. At the moment our component doesn't have any state so lets add a name instance variable:

WAComponent subclass: #HelloWorldComponent
	instanceVariableNames: 'name'
	classVariableNames: ''
	poolDictionaries: ''
	category: 'SCSeasideTutorial'
Now we give it an initial value and supply some methods to change the value:
initialize
	super initialize.
	name := 'Anonymous user'

bobIsHere
	name := 'Bob'


janeIsHere
	name := 'Jane'
Now we modify our render method to display the name and allow us to change it:
renderContentOn: html
	html heading: 'Welcome ' , name level: 1.
	html anchorWithAction: [self bobIsHere] text: 'Bob'.
	html br.
	html anchorWithAction: [self janeIsHere] text: 'Jane'
Try this new version of the application. Follow the links and see that the heading changes to reflect the name. Pretty simple huh? Now press the "New Session" link at the bottom of the web browser page. Notice that you get a fresh version of the component (the name is reset to "Anonymous user"). How does Seaside know when to use an existing instance of your root component versus creating a new one? Basically this information is placed in the anchors. Follow one of the anchors and you'll notice that the URL contains a parameter named "_s":

This is how Seaside tracks the current user's session from request to request. Anytime you visit a seaside URL without a session variable in the request you are given a new instance of the application's root component. The concept of a user's session is reified in an instance of the class WASession associated with each active session which can be accessed by evaluating self session. We will make extensive use of this later. The renderer takes care of making sure your session ID appears in internal (callback) anchors and in forms. There are low level methods in the renderer that generate forms and anchors without the session information. These methods are useful when you want to link to an external web site.

How do I get my anchor to display another component?

Yes, it would make sense to answer that question here. However I have a whole section dedicated to that topic.

Links to external resources

You can generate run-of-the-mill HTML anchors (those not associated with a Seaside callback) using anchorWithUrl:text: such as:
renderContentOn: html
	html anchorWithUrl: 'http://www.amazon.com' do: 'Amazon'
Of course the second argument can be any renderable. When a user leaves your site through such an anchor, their association with their session will be lost (unless they use the "back button" to return to your site). Sometimes it is nice to raise a new window when they're leaving your site. Seaside provides some simple javascript code to and convenience methods to support these "popup windows":
renderContentOn: html
	html anchorWithPopupUrl: 'http://www.amazon.com'  extent: 400@350 text: 'Amazon'.
If the user's browser doesn't support javascript (or it has been disabled) this will act like a normal anchor.

Exercises

  1. There are several other convenience methods associated with generating anchors...experiment with them.

C. David Shaffer
Last modified: Sun May 15 16:52:08 EDT 2005