[Seaside] On playing with tutorial 1

Avi Bryant avi@beta4.com
Thu, 9 May 2002 16:22:35 -0700 (PDT)


On Thu, 9 May 2002, Tim Rowledge wrote:

> My first thought was "what? I have to manually type html? Bugger". The
> problem is that it's so tedious trying to find that missing $", or $>
> that is making something very wierd turn up in your browser (or not, on
> occasion).

Well, that particular problem can be solved by using the s-expr syntax
instead of standard HTML; you'll notice it used in a few of the examples.
It allows array literals like

#(html
   (h1 'Hello world')
   (form sea:id: foo
     (input type: submit value: 'Some Button')))

instead of the equivalent html:

<html>
  <h1>Hello World</h1>
  <form sea:id="foo">
   <input type="submit" value="Some Button">
  </form>
</html>

The #html method supports both, just return an array literal instead of a
string.

Of course, what you really want is probably a higher level programmatic
way of specifying the layout - I've thought about that a tiny bit, but
haven't done any work on it.  Most people tend to want to move to HTML
templates at some point anyway, either to get more control or to let a
designer make things pretty, so getting templating working was the first
priority.

> Secondly, I'm very perturbed by the idea of using a 'path' syntax to
> rape and molest objects as in the [each.value] phrase. What happened to
> message sends?

Well, it's a shortcut.  It purposely doesn't look like a message send
because it doesn't directly map to one - for example, you can use the same
syntax to access keys in a Dictionary.  Being able to embed such paths
into the template is useful for quickly whipping stuff up, but you don't
have to use them if you don't like them (well, more on that below).  You
could, for example, use [someMeaningfulName] instead of [each.value] and
then have a method #someMeaningfulName that returned what you needed - in
this case, since 'each' is a template-local variable, the method would
look something like

someMeaningfulName
 ^ (locals at: #each) value

The problem comes when you have two-way bindings; say you have a form
input bound to 'each.address' - you can't write a single method to handle
this, because you need to be able to both get and set that value, and so
currently a path binding is the only reasonable way of doing that.

One thing I'm strongly considering doing is deprecating this whole notion
of path binding in favor of specifying every binding as a pair of get/set
blocks.  This will make explicit bindings somewhat more cumbersome to
type, ie, what's currently

(template elementNamed: 'foo')
 bind: #value toPath: 'foo.bar'

will become

(template elementNamed: 'foo')
  bind: #value to: [foo bar] updateWith: [:v | foo bar: v]

It's definitely more in the Smalltalk spirit, and I have a feeling would
make it easier for people to grasp what's going on.  Of course, you would
still be able to embed paths in the html, but at least you could avoid
using that particular shortcut if you wanted.  This style would also work
nicely with a programmatic template builder.

This change would require a fair bit of reorganization of Seaside's
internals, though (the main problem is that currently the same bindings
objects are shared between all instances of a component - using blocks in
that way obviously is going to break that, at least without playing nasty
context games), so even if people like the idea, it won't happen
immediately.

Thanks for the feedback, Tim.  I hope to hear more of it as you progress
further.

Cheers,
Avi