-
Notifications
You must be signed in to change notification settings - Fork 71
Embedding Subcomponents
It is common for a component to display instances of other components while rendering itself. It does this by passing them into the #render:
method of WAHtmlCanvas
. For example, this #renderContentOn:
method simply renders a heading and then displays a counter component immediately below it:
renderContentOn: html
html heading level3; with: 'My Counter'.
html render: myCounter
It’s important that you use #render:
, rather than directly calling the #renderContentOn:
method of the subcomponent. The following is not a supported technique:
renderContentOn: html
html heading level3; with: 'My Counter'.
myCounter renderContentOn: html "DON'T DO THIS".
These instances, or "subcomponents" are usually instance variables of the component that is "embedding" them. They are commonly created as part of the parent’s #initialize
method:
initialize
super initialize.
myCounter := WACounter new
They may also be stored in a collection. One fairly common pattern is to keep a lazily initialized dictionary of subcomponents that match a collection of model items. For example, if you wanted a BudgetItemRow subcomponent for each member of budgetItems, you might do something like this:
initialize
super initialize.
budgetRows := Dictionary new
rowForItem: anItem
^ budgetRows at: anItem ifAbsentPut: [ BudgetItemRow item: anItem ]
renderContentOn: html
self budgetItems
do: [:each | html render: (self rowForItem: each) ]
separatedBy: [ html horizontalRule ]
Each parent component must implement a #children
method that returns a collection of all of the subcomponents that it might display on the next render. For the above two examples, #children
might look like this:
children
^ Array with: myCounter
or this:
children
^ self budgetItems collect: [ :each | self rowForItem: each ]
If a subcomponent makes a #call:
to another component, that component will appear in place of the subcomponent. In the first example, if myCounter made a #call:
to DateSelector, that DateSelector would appear in the context of the counter’s parent, with the ’My Counter’ heading above it.
Since a subcomponent has not been #call:
’d, in general #answer:
is a no-op. However, the parent may attach an #onAnswer:
block to the subcomponent to be notified if it sends #answer:
. This allows one component to be used both from #call:
and through embedding. For example:
initialize
super initialize.
dateSelector := WADateSelector new onAnswer: [ :date | self dateChosen: date ]
Changelogs
- (newer changelogs, see https://github.com/SeasideSt/Seaside/releases)
- 3.4.0
- 3.3.0
- 3.2.4
- 3.2.2
- 3.2.1
- 3.2.0
- 3.1.3
- 3.1.2
- 3.1.1
- 3.1.0
- 3.0.11
- 3.0.9
- 3.0.8
- 3.0.7
- 3.0.6
- 3.0.5
- 3.0.4
- 3.0.3
- 3.0.2
- 2.8
- 2.7
- Past Releases
Development
Documentation
- Configuration and Preferences
- Embedding Subcomponents
- Maintaining State
- Generating HTML
- CSS and Javascript
- Debugging Seaside Applications
- Links, Forms and Callbacks
- Development Tools
- Call and Answer
- Naming URLs
- Security Features
- Securing Seaside Applications
- Seaside-REST
- Add-On Libraries
- Persistence
- Gettext
- FileLibrary
- The Render Tree
- PDF Generation
- Long-Term Issues
- Ajaxification
- Web Components
- Big Issues
Sprints