Inspired by http://blog.bolkey.com/2009/06/tapestry-5-recursive-tree/, I
tried to develop a simple tree component that renders a tree of nodes as
nested ul/li lists. Always good to learn Tapestry behaviour.

I know that Tapestry doesn't support recursive components, but this can
be somewhat circumvented via the delegate mechanism. I wonder if this is
accidental or if this is supported and should work.

I proceeded as in the blog mentioned above, but used only one component
for all nodes for simplicity (no subclasses in dependance of the node
type). I have

t2tree.tml:
-----------------------
<?xml version="1.0" encoding="UTF-8" ?>
<ul xmlns:t="http://tapestry.apache.org/schema/tapestry_5_1_0.xsd";>
<li>root: ${currentNode.name}
     <t:if test="currentNode.hasChildren()">
         <t:delegate to="currentNodeBlock"/>
     </t:if>
     <t:block>
         <t:t2node t:id="node" node="currentNode">
             <li>${currentNode.name}
             <t:if test="currentNode.hasChildren()">
                 <ul>
                     <t:delegate to="currentNodeBlock"/>
                 </ul>
             </t:if>
             </li>
         </t:t2node>
     </t:block>
</li></ul>
-----------------------

I have to use two components for this, because the t:block cannot
contain a t2tree, even if it is not rendered.

The block is used to hide the definition of <t2node t:id="node"> so that
t2tree's template doesn't render it. t2tree's property
"currentNodeBlock" returns this component (<t2node t:id="node">).

This creates a recursive structure in the stack backtrace, but the
component t2node instance is re-used at every level and must take care
to modify and restore its state on nesting and denesting.

t2node changes the node (t2tree's currentNode) in the beforeRenderBody
and afterRenderBody methods to iterate through the tree. I'm omitting
the details here, it works when I generate the <ul>-Tags with a
MarkupWriter. However, to separate the markup from the code, I'm trying
to omit generating the markup in the code, so the body of t2node
contains a t:if and the opening and closing <ul> tags.

As far as I have observed, this fails for the reason that this t:if is
only evaluated once (in effect, twice, apparently because it appears
twice in t2tree.tml).

This is the point where I'm asking myself if this is/should be supported
by tapestry after all, because the evaluation result of the t:ifs seem
to be cached somewhere. Is this intentional? Can it be switched off?

I can't see why it should be intentional, because normally, the template
is evaluated only once and it doesn't make sense to cache the result
then. On the other hand, in a t:loop component body, there can be t:ifs
that are evaluated at every iteration (if not @Cached).

I hope this issue is comprehensible. Can please someone knowledgable
explain why this doesn't work or tell me if it can be made to work or
that it should work?

Thanks much,
Dirk


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to