DynamicBlock Redux
When I first started working with Tapestry I had
just completed a CMS style application with WebObjects. The whole application
consisted of a single page component with parts of the page marked as 'dynamic'
with logic applied to swap out the contents of these dynamic areas according to
some logic based on user navigation and some content scheduling. I wanted the
same type of feature in Tapestry without having to pre-declare Blocks containing
the components so I could just add components for different content types to a
project and get them to just 'show' up on existing
pages.I coded a DynamicBlock component
(RenderBlock without the Block) over a year ago for Tapestry 3. My original
posts:DYNAMICBLOCK - CHOOSING
TAPESTRY COMPONENTS AT RUNTIME
DYNAMICBLOCK
PART II - DYNAMICBLOCK NOW ALLOWS A
BODYI have a new
implementation for Tapestry 4 which I believe is cluster-safe since it does not
involve modifying the page component structure at run-time. To see the Tapestry
4 version in action click here.DynamicBlock
behaves much like RenderBlock, instead of a block parameter, DynamicBlock
accepts a
componentName
parameter:
<span jwcid="switchBlock@mjh:DynamicBlock"
componentName="ognl:selectedComponentName" />
The value passed to the
componentName
parameter can be computed via your own method, it's up to you how to determine
which component should be used.In
addition, DynamicBlock now passes it's informal parameters as parameters of the
component which replaces it in the rendered page. So, for
example:
<span jwcid="switchBlock@mjh:DynamicBlock"
componentName="ognl:selectedComponentName"
string="A string value" />
Passes the informal parameter named
string as a
parameter of the component rendered. The online example and the source code for
the example show this feature in
action.DynamicBlock works by
pulling a block from a page which wraps the required component. The page name is
generated using the
componentName
value and a custom ISpecificationResolverDelegate supplies the
page implementation. The delegate is automatically installed using Hivemind but
it honors the
org.apache.tapestry.specification-resolver-delegate
application extension point as described in the
Tapestry 4 Users Guide. The example application
includes an implementation of the ISpecificationResolverDelegate which is
installed using the application extension
mechanism.Since the components are, in
fact, declared in pages (even though the pages are created on-demand) other than
the page they are rendered in, these components, or any that they themselves
contain must not depend on methods in the PageRenderListener interface for
initialization. Since the page which contains them is never rendered, these
methods will not be called.The
component is available as a packaged Tapestry library here
, and the source code for the example application can be downloaded here.Declare
the library in your .application
file:
<library id="mjh" specification-path="/com/mjh/components/mjh-components.library" />
DISCLAIMER: This is fresh code, it seems to
work in the testing I have done but there may be issues, feedback is
welcome.
Posted: Thu - March 9, 2006 at 09:55 PM
|