[Seaside] Re: session variable vs. dynamic variable

Holger Kleinsorgen h.kleinsorgen at i-views.de
Fri Feb 8 19:51:12 UTC 2008


Ramon Leon schrieb:
>> "Ramon Leon" <ramon.leon at allresnet.com> wrote
>>
>>> Use announcements instead, break the coupling.
>> I'd like to use announcements, but am not clear about two points:
>>
>> I have a root component (R), and a n-level deep leaf 
>> component (L). A callback on L needs to cause something like:
>>     html updater
>>       id: R id;
>>       callback: [:r |
>>         self doModelStuff.
>>         r render: R]
>> How would you recommend getting this effect with announcements?
>>
>> Also, would requiring a custom session subclass to hold the 
>> announcer make it hard to use my component elsewhere?
 >
> I wouldn't let a child component redraw anything on the parent or rerender
> the parent.  Components should render themselves.  Off the top of my head,
> I'd say if a child callback needs to refresh the parent, I'd have the
> callback send an announcement with the rendering canvas as an argument, let
> the parent catch the announcement and use that renderer to call any
> necessary rendering methods.  The child need only be concerned with
> announcing, which could be either a global session announcer, or its own
> announcer that the parent registered interest in when it first created the
> child.  Every object *can* be it's own announcer, this creates a simple
> event system where any object can signal events.

This potentially reverses the problem: The root R now needs to know 
about the leaf component L, which might be not desirable, because R does 
not know L directly.

I had a similiar problem recently, and used the following approach, 
which works quite well and decouples the components.

- add a back link from each child component to its parent (but keep it 
private, no component should explicitely send stuff to its parent).

- implement #announceOrDelegate:. This method checks if there are any 
subscribers for the specific announcement. If yes it is announced, 
otherwise the component delegates the announcement to the parent 
component (the only piece of code that uses the back link to the parent 
component).

It's similiar to the upcast mechanism used by VisualWorks' views.


Also, I added a mechanism to reduce the amount of work and coupling 
required by AJAX callbacks. Basically it works the following way:

- in the component that encloses the asynchronously updated area, the 
render method looks like this:

renderContentOn: canvas
    ...
    canvas div
      id: canvas nextId;
      asyncRenderWith: [ : updateCanvas |
        self renderDynamicContentOn: updateCanvas
      ].


#asyncRenderWith: adds an AsyncAreaBrush to the canvas. AsyncAreaBrush 
takes care of rendering the dynamic content immediately (using the given 
canvas), and later rendering the updated area (in this example the 
contents of the <div> element), using the canvas passed by the AJAX 
framework (I'm currently using MooTools).

- in the component with the callback, the render method looks like this

renderContentOn: canvas
    ...
    canvas anchor
      asyncCallback: [ ... ];
      with: [ ...  ]

#asynCallback: traverses the brush parent hierarchy until it encounters 
the AsyncAreaBrush, and let it create an updater for the callback.

This way, the component with the callback does not need to know any 
details about the parent component. Also, it's easy to turn AJAX 
requests off (by making #asyncRenderWith: simply evaluating the block, 
and #asyncCallback: falling back to #callback:).


More information about the seaside mailing list