[Seaside] Metamodel and Form support

Adrian Lienhard seaside@lists.squeakfoundation.org
Sat, 14 Dec 2002 16:02:53 +0100


Hi all

So, the moment has come where I would like to have your critical oppinion!

There are two parts: The metamodel (a model which describes your actual
domain model) and the form support which now depends on the metamodel. The
leading idea is that a metamodel which has to be defined only once, delivers
the neccesary information to the components.

I'll first show a simple example how it works and then try to go a little
more into how it is implemented.

A part of the metamodel definition may look like this:

page := WANamingAttributePage new
    label: 'ATextLabel';
    description: 'some description';
    yourself.
Metamodel addAttributePage: page forInstvar: #text.
or:
page := WARelationshipTypeAttributePage new
    beMultiple;
    ownerObjectBlock: [WASession currentSession domainmodel];
    collectionSelector: #teamMembers;
    yourself.
Metamodel addAttributePage: page forInstvar: #responsiblePeople.

When creating the form this information is used to name the fields, to
create the right input tags, to populate select lists, to assign validation
rules etc.

To create a form you subclass WAForm (Avi, I tried to change this to
compositioning. But it makes things more complicated and less stright
forward) and overwrite initializeFields:

textfield _ WATextField on: self model for: #text.
textfield loadAttributePagesFrom: metamodel.
self addField: textfield.

or much simpler: add all your fields to the form at once with one single
statement ...
form
    addFields: #(#text #responsiblePeople #number #date )
    with: metamodel.

...and you have a fully working form! Is this not cool?

Metamodel:
A metamodel (instance of WAMetamodel) describes one domain model class. All
the description is separated into "attribute pages". The metamodel can
contain global pages and pages for each instvar. A attribute page is a
subclass of WAAttributePage. In the above example I used
WARelationshipTypeAttributePage (better names?) which describes a instvar
"of type relationship". Each page has a name which makes it easier to access
a page. (e.g. "metamodel attributePage: #Type forInstVar:
#responsiblePeople"). I did this "page-apporach" because like this, the
attributes (or whatever will be stored in the pages) can be spearated into
semantic units. (Naming, Type, ValidationRules etc.). You only add pages
which willl be needed by your components.

Form:
The class WAForm manages all Fields. A Field (the unit for label,
description, input type,..) is responsible for loading, cashing, committing
(Avi, I don't use the proxy anymore) and validating data. Each field holds
the required meta information which can be loaded from a metamodel (loading
just sets all found attributes in the field). This makes it enough flexible
to manually alter information after loading the metamodel or not use the
metamodel at all.

What to be done next:
- Additional Attribute pages (type: text, number, boolean, date, .. rules:
... sorting/filtering: ...)
- Factor out the rendering of form and field.
- Support for radio groups and multiple-select lists.

There is one basic example: WAFormExample (in the Form-Test category)
There are Unit-Tests for the form support

Source can be downloaded here:
    http://www.adrian-lienhard.ch/files/squeak/Seaside-Metamodel.st
    http://www.adrian-lienhard.ch/files/squeak/Seaside-Form.st
    http://www.adrian-lienhard.ch/files/squeak/tableRowWithFix.cs
(#tableRowWith:with: had a tiny bug)


So, if you have read all this, you might be interested in it ;-). I'd like
to hear what you think about it. What could be done better? Does it go in
the right direction? Is it usable? What is missing?

Adrian

_____________________
Adrian Lienhard
www.adrian-lienhard.ch
www.netstyle.ch