Scriptacu-list Tutorial(Part 2)

So we’ve got our first cut domain model and now its time to add our views. Today we are going to add another two classes MyAddressBookView and MyContactEditor…


  1. We begin by creating MyAddressBookView as a sublcass of WAComponent with an instance variable of addressBook. (NB by using an instance variable it will mean that your address book gets reset for every session. If you’re not happy with that you can use a class variable instead)
  2. Once again we will lazy initialize our variable

    ^addressBook ifNil: [addressBook := MyAddressBook new]

  3. Now we will create our rendering method. We start simple by coding a heading…

    renderContentOn: html
    html heading: 'Contacts' level: 1.

  4. Then we add some more lines that will iterate over our collection of contacts and for each one display their name as a hyperlink to a page where their details can be edited…

    self addressBook
    contacts do: [:contact |
    html div class: ('row');
    with: [
    html anchor
    callback: [self showContact: contact];
    with: (contact firstName , ' ', contact surname )]]

  5. Lastly we will add a few lines to create a button which will allow us to create a new Contact…

    html form: [
    html span class: 'button';
    with: [html submitButton on: #addContact of: self]]

    (Note here the the on: aSymbol of: anObject is a convenience method that uses aSymbol to derive a label for the button and the method to perform. Neat eh!)

  6. Before this code can run we need to define the two methods that called in the renderContentOn: method above. First we will define the addContact: method

    | contactEditor contact |
    contact := MyContact new.
    contactEditor := MyContactEditor on: contact.
    (self call: contactEditor) ifTrue: [self addressBook addContact: contact]

    …this is all pretty straightforward except to point out that we will only add our new contact if the editor replies true (as a result of clicking save)

  7. Finally for this class we will add our showContact: method…

    showContact: aContact
    self call: (MyContactEditor on: aContact)

    …managing save and cancel for new contacts is easy. For editing it is a little more involved. Next time we will alter this method to implement a memento for the contact


  1. Now we need to create the editor for our contacts. Again we create MyContactEditor as a subclass of WAComponent this time with an instance variable of contact.
  2. Now create the accessors for the contact variable like we did for the variables in our domain classes last time.
  3. We are now going to create a class method that will deliver us a new Editor with the contact already populated…

    on: aContact
    ^self new
    contact: aContact ;

  4. One of the most powerful things about seaside is the ability to factor your html into small callable methods. When creating a form I often repeat the same pattern for each input field; I create a div; I put a label for the field inside a “label” span; I put an input field inside a “field” span. So lets create a method that will do that for us…

    renderLabel: aLabel withInput: anInputFieldBlock on: html
    html div class: 'row';
    with: [
    html span
    class: 'label';
    with: aLabel .
    html span
    class: 'field';
    with: anInputFieldBlock].

  5. Now we can use this in our rendering…

    renderContentOn: html
    html heading: 'Contact Details'.
    html form
    self renderLabel: 'First Name: ' withInput: [html textInput on: #firstName of: contact] on: html.
    self renderLabel: 'Surname: ' withInput: [html textInput on: #surname of: contact] on: html.
    self renderLabel: 'Date of Birth: ' withInput: [html dateInput on: #dateOfBirth of: contact] on: html.
    self renderLabel: 'Telephone: ' withInput: [html textInput on: #telephoneNumber of: contact] on: html.
    self renderLabel: 'Email: ' withInput: [html textInput on: #emailAddress of: contact] on: html.
    html span class: 'button';
    with: [html submitButton on: #save of: self].
    html span class: 'button';
    with: [html submitButton on: #cancel of: self].

  6. Finally we need to create the save and cancel methods called by our buttons…

    self answer: true

    self answer: false

If you got through all that OK then open up a workspace and evaluate MyAddressBookView registerAsApplication: 'AddressBook' and hopefully you can then try out your app (most probably on http://localhost:8080/seaside/AddressBook)

Explore posts in the same categories: Seaside, Smalltalk

8 Comments on “Scriptacu-list Tutorial(Part 2)”

  1. Steve Says:

    This will be a neat blog thanks for taking the time to put it up. I tried entering the example but get a walk back as MyContactEditor>>contact: was missing. Hope I didn’t miss something.


  2. Ramon Leon Says:

    Nice example, good to see people groking Seaside, you hit a major point with #4, well factored html, something you just can’t do in other frameworks.

    One thing to consider, on a per project basis, if you have things you’d like available everywhere, you can subclass WACanvasRenderer, add those helpers to your own rendering class, and then override the factory method that creates the rendering component to have your custom renderer passed to all components, making something like #renderLabel available everywhere, not just on self.

    Also, components answer nil by default, so you can just return your object when successful, allowing this..

    (self call: (MyContactEditor on: MyContact new))
    ifNotNilDo: [:contact | self addressBook addContact: contact]

  3. Steve

    I didn’t provide the code for the contact accessors referred to in step 2. If you add a setter method like…

    contact: aContact
    contact := aContact

    …all should be well.

  4. Ramon

    Thanks for looking in and taking the time to comment. It’s good to have someone with a good knowledge of seaside helping out with some “tricks of the trade”

  5. Conrad Says:

    Hi, do you have a downloadable package that consists of the individual parts of the 7 part tutorial?
    At this time, I’m getting the error message on part 2 of the tutorial in regards to the #renderContentOn: method. BTW, I’m using Seaside 2.8 Beta with VisualWorks 7.5.

    Thanks in advance,


  6. Hi Conrad

    I just saw your stack trace on the seaside mailing list.

    It looks as though the contacts OrderedCollection has boolean values in it rather than MyContact instances. I would suspect that the cause of the error is in the #addContact method.

    If you have used Ramon’s code you will also have to change the #save method on MyContactEditor so that instead of returning ‘true’ it returns the contact

  7. arosenzweig Says:

    Now in Seaside 3 you need to do the following to register your app:

    WAAdmin register: MyAddressBookView asApplicationAt: ‘AddressBook’.

    Also, the call to:

    html heading: ‘Contacts’ level: 1.

    That doesn’t seem to be available anymore either. I don’t see how to set the level so I just did:

    html heading: ‘Contacts’.

  8. arosenzweig Says:

    I figured out Seaside 3 heading syntax:

    html heading level: 1; with: ‘Contacts’.

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: