[Seaside] A bit of help with Seaside

Avi Bryant avi at beta4.com
Fri Feb 14 17:46:04 CET 2003


On Fri, 14 Feb 2003, [iso-8859-1] Germ=E1n S. Arduino wrote:

> By example: I would to have a html grid showing people records, then by
> means of a check box in each row I want to be able to select a record and
> modify or delete. Also I must to add records. But I can't figure how to
> build that grid (table), how to populate with my objects, and so.

German,

Start with a WAComponent subclass that will display this grid.  Let's call
it RecordList:

WAComponent subclass: #RecordList
=09instanceVariableNames: ''
=09classVariableNames: ''
=09poolDictionaries: ''
=09category: 'German-Example'

RecordList will need some method, say, #records that will get a list of
all the records you want it to show.  I don't know where you have these
stored, so I'll just assume you have a global for them somewhere (not
that I endorse that approach - really, this should probably be something
that's passed into the component when it's created).

RecordList>>records
  ^ AllRecords

The main responsibility of the RecordList is to implement
#renderContentOn:, which will display the list and create the links, etc,
that you need.  It'll start quite simply: creating a table, and then
calling a second method to render a table row for each record.

RecordList>>renderContentOn: html
  html table: [
    self records do:
      [:record |
      self renderRowForRecord: record on: html]
  ]

We can now implement #renderRowForRecord:on:.  I'll leave out the
checkboxes for now, and just have it create a 'modify' and 'delete' link
for each record.

RecordList>>renderRowForRecord: aRecord on: html
  html tableRow: [
    "one column describing the record"
    html tableData: [html text: aRecord printString].

    "one column with links"
    html tableData: [
      html anchorWithAction: [self modify: aRecord] text: 'modify'.
      html space.
      html anchorWithAction: [self delete: aRecord] text: 'delete'.
  ]

This will display a table with a row for each record that contains a
modify and a delete link.  Clicking those links will call #modify: or
#delete: on the RecordList, passing in the correct record.

To implement #modify:, you probably need a RecordEditor component, that
can be given a record, and displays a form to edit it.  A good example of
such a component is WSMCardEditor from Seaside/Examples-SM.  You would
want #modify: to create one of these components, pass it the record, and
then #call: it, causing that page to be shown instead of the list:

RecordList>>modify: aRecord
  self call: (RecordEditor new record: aRecord)

To implement #delete:, you might want to ask the user if they really want
to delete the record first.  Then, simply delete it from your list of
records.

RecordList>>delete: aRecord
  (self confirm: 'Are you sure you want to delete ', aRecord printString, '=
?')
    ifTrue: [AllRecords remove: aRecord]

Now, if you want to use checkboxes, things get a little trickier.  You
need tp create some data structure to store which rows are checked and
which aren't.  I'll show you how you'd do it using a Dictionary that has
a true or false entry for each record being shown.  You'll need to add a
'selected' instance variable to the component:

WAComponent subclass: #RecordList
        instanceVariableNames: 'selected'
        classVariableNames: ''
        poolDictionaries: ''
        category: 'German-Example'

and override the component's #initialize method to create a Dictionary:

RecordList>>initialize
  selected :=3D Dictionary new.

now, when you render a row, you want it to also have a checkbox.  This
checkbox will always be displayed unchecked, but when the form is
submitted, it will store true or false in the 'selected' dictionary:

RecordList>>renderRowForRecord: aRecord on: html
  html tableRow: [
    "one column with a checkbox"
    html tableData: [
     html
       checkboxWithValue: false
       callback: [:b | selected at: aRecord put: b]
    ]

    "one column describing the record"
    html tableData: [html text: aRecord printString].

    "one column with links"
    html tableData: [
      html anchorWithAction: [self modify: aRecord] text: 'modify'.
      html space.
      html anchorWithAction: [self delete: aRecord] text: 'delete'.
  ]

You need to make sure that the table is wrapped inside a form, and add a
Delete button that will delete all of the selected records:

RecordList>>renderContentOn: html
  html form: [
    html table: [
      self records do:
        [:record |
        self renderRowForRecord: record on: html]
    ]
    html submitButtonWithAction: [self deleteSelected] text: 'Delete'.
  ]

We can implement a method #selectedRecords that will find only records
that have been checked off:

RecordList>>selectedRecords
  ^ self records select: [:ea | selected at: ea]

Finally, implement #deleteSelected; we can put in a check to make sure the
selection is not empty

RecordList>>deleteSelected
  |recordsToDelete|
  recordsToDelete :=3D self selectedRecords.
  recordsToDelete isEmpty
    ifTrue: [^ self inform: 'You must select at least one record!'].

  (self confirm: 'Delete ', recordsToDelete size asString, ' records?')
    ifTrue: [AllRecords removeAll: recordsToDelete]

And I think that's it.  Does that help?

Avi



More information about the Seaside mailing list