[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