[Seaside] Web Calendar for Seaside

Avi Bryant seaside@lists.squeakfoundation.org
Sat, 23 Nov 2002 14:02:14 -0800 (PST)


On Sat, 23 Nov 2002 tblanchard@mac.com wrote:

> OK - lets start with creating an application.  The config utility has a
> page, which lets me add an application - I name it and it presents a
> pair of popup menus.  Based on this - I am guessing that there is only
> one class that is the application - and that this class is configured
> with a default page (the first popup menu) and you can select a
> particular type of session type (the second popup menu).  The menus are
> populated as subclasses of WAComponent for the default page and
> subclasses of WASession for the session class selector.

Correct on all counts.

> So all I have to do is write a WAComponent for the first page of my
> app, set it as the entry point in config - then use WASession or a
> subclass of that for the session.

Also correct.

> I think I get that.  I'm not quite clear on how to navigate to a new
> page from there though.

You navigate to a new page by creating an instance of a WAComponent
subclass and passing it into the #call: method.  So, for example, let's
say you're writing a simple guestbook - it has a default page which lists
the guests, and a link to a page to add a new guest.  The first thing you
would do is write the #renderOn: method of the GuestList; somewhere in
there you would render the "Add Guest" link, which you would attach to a
callback that called, say, the #addGuest method on GuestList.  So:

GuestList>>renderOn: html

  "render the guest list"
  ...

  "render the Add Guest link"
  html anchorWithAction: [self addGuest] text: 'Add Guest'.


Ok, now when that link is clicked, #addGuest will be called.  That's where
you need to navigate to the AddGuest page.  So:

GuestList>>addGuest
  self call: (AddGuest new)

Now, that answers your question, sort of.  But let's keep going, and look
at AddGuest.  We'll give it an instance variable "guest", and
initialize it to a new Guest object.

AddGuest>>initialize
  guest := Guest new

The AddGuest page is going to render a form that fills in the fields of
Guest, and it's also going to have a "Save" submit button.

AddGuest>>renderOn: html

  html form: [
    html textInputWithValue: guest name callback: [:n | guest name: n].
    .....

    html submitButtonWithAction: [self save] text: 'Save'.
  ]

Now, here's the interesting part: what happens in #save?  In traditional
web app terms, we want to navigate back to the GuestList.  So, we could
have something like this:

AddGuest>>save
  ... do something to save the Guest object ..

  self call: (GuestList new)

But in Seaside, every "call" to a page can be "answered" - bringing us
back to the point it was called from.  And in fact, it can pass a value
as its answer, which will be returned from the call; in this case, let's
pass the guest object we just created.

AddGuest>>save
  self answer: guest

Since AddGuest was called from GuestList, by calling #answer: we're
returning back to the GuestList.  But in fact, we're returning back to the
#addGuest method, and we're returning it a Guest object.  So in fact
#addGuest should look like this:

GuestList>>addGuest
  |newGuest|
  newGuest := self call: (AddGuest new).
  guests add: newGuest

Did that all make sense?

Avi