Table of Contents Previous Section

Intercomponent Communication

Reusable components can vary widely in scope, from as extensive as an entire HTML page to as limited as a single character or graphic on a page. They can even serve as building blocks for other reusable components. When a reusable component is nested within another component, be it a page or something smaller, the containing component is known as the parent component, and the contained component is known as the child component. This section examines the interaction between parent and child components.

In the AlertPanel example above, you saw how the parent component, in its declarations file, sets the attributes of the child component:

ALERT: AlertPanel {
    alertString = alertTitle;
    alertFontColor = "#A00000";
    alertFontSize = 6;
    infoString = alertDescription;
    infoFontSize = 4;
    infoFontColor = "#500000";
    tableWidth = "50%";
};

Each of the AlertPanel's attributes is set either statically (for example, alertFontSize = 6) or dynamically, by tying the attribute's value to a variable or method invocation in the parent's script file (for example, alertString = alertTitle). Communication from the parent to the child is quite straightforward.

But for reusable components to be truly versatile, there must also be a mechanism for the child component to interact with the parent, either by setting the parent's variables or invoking its methods, or both. This mechanism must be flexible enough that a given child component can be reused by various parent components without having to be modified in any way. WebObjects provides just such a mechanism, as illustrated by the following example.

Consider an AlertPanel component like the one described above, but with the added ability to accept user input and relay that input to a parent component. The panel might look like this:

Figure 3. Alert Panel That Allows User Input

As in the earlier example, you use this component by simply declaring its position within the HTML page:

Parent's Template File


<HTML>
<HEAD>
    <TITLE>Alert</TITLE>
</HEAD>
<BODY>
<WEBOBJECT NAME = "ALERT"></WEBOBJECT>
</BODY>
</HTML>

The corresponding declarations file reveals two new attributes (indicated in bold):

Parent's Declarations File (excerpt)


ALERT: AlertPanel {
    infoString = message;
    infoFontSize = 4;
    infoFontColor = "#500000";
    alertString = "New Release";
    alertFontColor = "#A00000";
    alertFontSize = 6;
    tableWidth = "50%";
    parentAction = userInput;
    exitStatus = usersChoice;
};

The parentAction attribute identifies a callback method, one that the child component invokes in the parent when the user clicks the Yes or No link. The exitStatus attribute identifies a variable that the parent can check to discover which of the two links was clicked. This attribute passes state information from the child to the parent. A reusable component can have any number of callback and state attributes , and they can have any name you choose.

Now let's look at the revised child component. The template file for the AlertPanel component has to declare the positions of the added Yes and No hyperlinks. (Only excerpts of the implementation files are shown here.)

Child Component's Template File (excerpt)


  <TD>
    <WEBOBJECT name=NOCHOICE></WEBOBJECT>
  </TD>
  <TD>
    <WEBOBJECT name=YESCHOICE></WEBOBJECT>
   </TD>

The corresponding declarations file binds these declarations to scripted methods:

Child Component's Declarations File (excerpt)


NOCHOICE: WOHyperlink {
    action = rejectChoice;
    string = "No";
};
YESCHOICE: WOHyperlink {
    action = acceptChoice;
    string = "Yes";
};

And the script file reveals the implementation the rejectChoice and acceptChoice methods:

Child Component's Script File (excerpt)


id exitStatus;
action parentAction;
- rejectChoice
{
    exitStatus = NO;
    return [parentAction invoke];
}
- acceptChoice
{
    exitStatus = YES;

    return [parentAction invoke];
}

Note that exitStatus is simply a transaction variable. Depending on the method invoked, exitStatus can have the values YES or NO. On the other hand, the parentAction variable is of type action.

In WebScript, the action type indicates that a variable represents a WOAction object. A WOAction object stores the name of a method that can be invoked by sending the WOAction object an invoke message. In this example the parentAction object stores the method named userInput, as specified in the parent's declarations file.

Now, looking at the rejectChoice and acceptChoice method implementations, you can see that they are identical except for the assignment to exitStatus. Note that after a value is assigned to exitStatus, the parentAction object is sent an invoke message, causing the parent's userInput method to be invoked. Since the parent's usersChoice variable is bound to the value of the child's exitStatus variable (see the parent's declaration file above), the parent script can determine which of the two links was clicked and respond accordingly. The following diagram illustrates the connections between the child and parent components.

Figure 4. Parent and Child Component Interconnections

The WOAction object (parentAction, in the preceding example) provides a separation between a user action (such as a click on a hyperlink) within a reusable component and the method it ultimately invokes in the parent. Because of this separation, the same child component can be used by multiple parents to invoke a different method in them:

Parent1's Declarations File (excerpt)


ALERT: AlertPanel {
    ...
    parentAction = userInput;
    exitStatus = usersChoice;
};

Parent2's Declarations File (excerpt)


ALERT: AlertPanel {
    ...
    parentAction = okCancel;
    exitStatus = result;
};

Parent3's Declarations File (excerpt)


ALERT: AlertPanel {
    ...
    parentAction = alertAction;
    exitStatus = choice;
};

In summary, parent and child components communicate in these ways:

A parent component can, in its declarations file, set child component attributes by:

A child component can communicate actions and values to a parent component by:

Table of Contents Next Section