[Seaside] Menu component - communicating with root component
keith_hodges at yahoo.co.uk
Sat Apr 19 17:25:00 UTC 2008
Edward Stow wrote:
> On Sat, Apr 19, 2008 at 6:41 PM, Philippe Marschall
> <philippe.marschall at gmail.com> wrote:
> Thanks -- that confirms my approach as being ok. Perhaps its a good
> time to brush up on announcements.
I keep coming up against this one, AND I have to figure it out by next
Thursday. Last time I said this I hacked a workaround instead.
Essentially seaside is architected so that for components, children do
not know their parents. The rationale for this is that it enables
children to be more reusable if there are no explicit interfaces to
However I have always found it essential to have children be able to
"look around" and know their position in the world. After a year of
using seaside and pier seriously, I have constantly had to find
work-arounds, for what I know should be really simple.
My workarounds are not particularly elegant, and the code has smelt bad
from the beginning. They have involved using some form of global as a
holder for information that a child and a parent want to share.
In my pier-shop the WACurrentSession or the PRCurrentContext ends up
holding the "current product being viewed", and all the components look
to the current context as a kind of "global" data structure as to what
to display. This has significant limitations, since you cannot have more
than one current product at a time, and it violates the whole
I implemented an Announcements helper in Seaside28Jetsam, which simply
makes an instance of Announcer available via "WACurrentSession
announcer". This appears to me to be a more complex and flexible form of
the "put the communication in a global place, so parents and children
What I want to do is to click on a product and have that call: the
product display, which is a pier page, a template which has been
assembled out of content and components, giving the pier page the
current product, or the current users cart-model as a property, and have
the child components be able to query the parents as to what product to
This would allow an administrator to have a side by side view of all the
current carts of the currently logged in users. The cart displays would
be generic container components, pier pages, with specialised children
components, and the users' carts-models would be a property of outer
page of each individual cart display. The inner cart display components
would need to be able to query their containers as to what is in their
cart that is to be displayed. This then allows components to be more
granular, e.g. "Total cost" component, which could appear anywhere in
the template. In contrast to the monolthic, Cart display, with tax
calulations, and totals etc... component.
Example 2) (a simpler one)
In migrating a complex Magritte form to use Magritte-scriptaculous, I
successfully wire up the models so that a change in one select drop
down, changes items in other fields in the same form. The child field
which has changed needs to trigger its form, so that all of changes in
all of the the relevant fields are received by the model, and then
scriptaculous update rendering, of not just its own component, but one
of its parents (at some level). Since it is the components onChanged:
event and callback: which is triggered when the user has changed the
select box, it is the component which needs to trigger the form and the
update. But as per usual, the inner component has no means for
dynamically discovering "what is the form id that I am in", or asking
the relevant parent to update.
I have modelled complex physical assemblies before. The case that comes
to mind was that of physical telecomunications equipment, where a card
gets put in a slot or pulled out of a slot. Some cards specifically
handle the alarms generated by all of the cards in their part of the
rack, and they also translate the physical events into alarms which are
sent up to the management interface.
The important concept I adopted in modelling physical heirarchies, was
to allow the actual structure to influence behaviour. For example a lone
card generating an alarm, would have no effect on the rest of the system
if it is not physically plugged in.
To achieve this, I always had the child know its parent. But, in keeping
with the loose-coupling principle I did not have any hard wired interface.
Instead I had an announcements like approach, called a SemanticMessage.
A SemanticMessage when triggered would walk up the hierarchy, calling
#smParent on each component and if it found either...
a) someone able to respond to the message, the message would be sent and
the response value returned to the triggerer.
b) someone who had registered an interest in the message at some point
in the hierarchy.
The Alarm card is sent a #cardInserted:intoSlot: SemanticMessage by the
rack, it responds to this by registering an interest in any alarm events
which arrive at the rack, from any card. Alarm events migrate up the
heirarchy from the source card to the rack where the dependant is informed.
I present this in an effort to dispel what I believe is a myth, that
children should not have any explicit knowledge their parents. I am sure
enough to say that it is essential that this knowledge be there, the
child should have a direct instVar (or property) to its parent. What is
more important is how you use that instVar. Direct usage of the parents
interface creates the inflexibility that we are trying to avoid.
So out use of the #parent instVar should be event or query based, rather
than being a direct use of the parents interface. e.g. A child can
trigger "I have Changed", and it is up to the parent to respond
appropriately. Or a child can seek information #lookupContainingFormId,
as long as it can handle the case that a heirarchy of parent which
doesnt contain a form may not respond appropriately.
I am really looking forward to solving this one
More information about the seaside