You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@tapestry.apache.org by Bill Holloway <bi...@peoplepad.com> on 2008/05/02 05:47:36 UTC

T5: Passing (looped) component blocks to layout for (looped) rendering

Hi All,

I have a component Foo in a loop on my TestPage.  Foo has a block on it
which Foo's template renders and which Foo's page class also picks up and
adds to a list of blocks on the TestPage's surrounding Layout component.
Layout loops over these blocks and renders them just before the </body>
tag.   Problem is that the layout-rendered blocks are all the same -- namely
the last block added to Layout by Foo.  What am I doing wrong?  Code and and
rendering results:

Foo.java
------------
@Property (write = false)
private int _ref;

@Inject
private ComponentResources _resources;

void beginRender () {
    _ref = (new Object()).hashCode(); // For a pretty reliably random int.
    Layout layout = (Layout)
_resources.getPage().getComponentResources().getEmbeddedComponent( "layout"
);
    layout.addPostWrapperBlock( _resources.findBlock( "tester" ));
}

Foo.tml
----------
<t:container xmlns:t="http://tapestry.apache.org/schema/tapestry_5_0_0.xsd">
    <t:block t:id="tester">
        <p>Ref: ${ref}</p>
    </t:block>
    <t:delegate to="block:tester" />
</t:container>

TestPage.tml
------------------
<t:layout t:id="layout" xmlns:t="
http://tapestry.apache.org/schema/tapestry_5_0_0.xsd">
    <t:loop source="0..2"><t:test.foo /></t:loop>
</t:layout>

Layout.tml (partial)
-------------------------
...
<t:loop source="postWrapperBlocks" value="var:pwb"><t:delegate to="var:pwb"
/></t:loop>
</body>
</html>

When Foo renders in TestPage's template, no problem:
Ref: 16084489
Ref: 736239
Ref: 9163575

But the rendering at the bottom of Layout is
Ref: 9163575
Ref: 9163575
Ref: 9163575

-- 
Bill @ PeoplePad

Re: T5: Passing (looped) component blocks to layout for (looped) rendering

Posted by Chris Lewis <ch...@bellsouth.net>.
I guess the question is, how does one get at blocks which have
framework-generated ids? You can't just getBlock("id"), but maybe if
they were generated with a component (like BlockContainer?) and then you
could just enumerate of that component's contained blocks. I don't know
if that infrastructure exists, but it's a thought.

chris

Bill Holloway wrote:
> I agree, Chris.  _resources.findBlock has got to be where the trouble is.
> Somehow the rendering order on Layout winds up only looking at the last
> rendering of the block.
>
> Bill
>
> On Fri, May 2, 2008 at 2:19 AM, Chris Lewis <ch...@bellsouth.net>
> wrote:
>
>   
>> Hi Bill,
>>
>> You normally have some interesting questions :-) - I don't see
>> t:delegate et al used often and am still trying to digest how they can
>> be used effectively. For your issue, unfortunately I don't know how to
>> fix it at the moment, but the problem exactly here (in Foo.java):
>>
>> layout.addPostWrapperBlock( _resources.findBlock( "tester" ));
>>
>> You've assumed that on each loop iteration, the block by id 'tester'
>> will exist in its own microcosm and therefore be accessible by that id.
>> In reality what I think is happening is that tapestry knows what block
>> has id 'tester', and in subsequent loop iterations over your blocks I'm
>> guessing that all but the last block will be replaced because of the
>> hardcoded block id.
>>
>> Because you're looping you need to let tapestry generate the ids, but
>> then of course there's the question of how to get at them. Now how to
>> fix it...
>>
>> chris
>>
>> Bill Holloway wrote:
>>     
>>> Hi All,
>>>
>>> I have a component Foo in a loop on my TestPage.  Foo has a block on it
>>> which Foo's template renders and which Foo's page class also picks up
>>>       
>> and
>>     
>>> adds to a list of blocks on the TestPage's surrounding Layout component.
>>> Layout loops over these blocks and renders them just before the </body>
>>> tag.   Problem is that the layout-rendered blocks are all the same --
>>>       
>> namely
>>     
>>> the last block added to Layout by Foo.  What am I doing wrong?  Code and
>>>       
>> and
>>     
>>> rendering results:
>>>
>>> Foo.java
>>> ------------
>>> @Property (write = false)
>>> private int _ref;
>>>
>>> @Inject
>>> private ComponentResources _resources;
>>>
>>> void beginRender () {
>>>     _ref = (new Object()).hashCode(); // For a pretty reliably random
>>>       
>> int.
>>     
>>>     Layout layout = (Layout)
>>> _resources.getPage().getComponentResources().getEmbeddedComponent(
>>>       
>> "layout"
>>     
>>> );
>>>     layout.addPostWrapperBlock( _resources.findBlock( "tester" ));
>>> }
>>>
>>> Foo.tml
>>> ----------
>>> <t:container xmlns:t="
>>>       
>> http://tapestry.apache.org/schema/tapestry_5_0_0.xsd">
>>     
>>>     <t:block t:id="tester">
>>>         <p>Ref: ${ref}</p>
>>>     </t:block>
>>>     <t:delegate to="block:tester" />
>>> </t:container>
>>>
>>> TestPage.tml
>>> ------------------
>>> <t:layout t:id="layout" xmlns:t="
>>> http://tapestry.apache.org/schema/tapestry_5_0_0.xsd">
>>>     <t:loop source="0..2"><t:test.foo /></t:loop>
>>> </t:layout>
>>>
>>> Layout.tml (partial)
>>> -------------------------
>>> ...
>>> <t:loop source="postWrapperBlocks" value="var:pwb"><t:delegate
>>>       
>> to="var:pwb"
>>     
>>> /></t:loop>
>>> </body>
>>> </html>
>>>
>>> When Foo renders in TestPage's template, no problem:
>>> Ref: 16084489
>>> Ref: 736239
>>> Ref: 9163575
>>>
>>> But the rendering at the bottom of Layout is
>>> Ref: 9163575
>>> Ref: 9163575
>>> Ref: 9163575
>>>
>>>
>>>       
>> --
>> http://thegodcode.net
>>
>>
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: users-unsubscribe@tapestry.apache.org
>> For additional commands, e-mail: users-help@tapestry.apache.org
>>
>>
>>     
>
>
>   

-- 
http://thegodcode.net


Re: T5: Passing (looped) component blocks to layout for (looped) rendering

Posted by Bill Holloway <bi...@gmail.com>.
I agree, Chris.  _resources.findBlock has got to be where the trouble is.
Somehow the rendering order on Layout winds up only looking at the last
rendering of the block.

Bill

On Fri, May 2, 2008 at 2:19 AM, Chris Lewis <ch...@bellsouth.net>
wrote:

> Hi Bill,
>
> You normally have some interesting questions :-) - I don't see
> t:delegate et al used often and am still trying to digest how they can
> be used effectively. For your issue, unfortunately I don't know how to
> fix it at the moment, but the problem exactly here (in Foo.java):
>
> layout.addPostWrapperBlock( _resources.findBlock( "tester" ));
>
> You've assumed that on each loop iteration, the block by id 'tester'
> will exist in its own microcosm and therefore be accessible by that id.
> In reality what I think is happening is that tapestry knows what block
> has id 'tester', and in subsequent loop iterations over your blocks I'm
> guessing that all but the last block will be replaced because of the
> hardcoded block id.
>
> Because you're looping you need to let tapestry generate the ids, but
> then of course there's the question of how to get at them. Now how to
> fix it...
>
> chris
>
> Bill Holloway wrote:
> > Hi All,
> >
> > I have a component Foo in a loop on my TestPage.  Foo has a block on it
> > which Foo's template renders and which Foo's page class also picks up
> and
> > adds to a list of blocks on the TestPage's surrounding Layout component.
> > Layout loops over these blocks and renders them just before the </body>
> > tag.   Problem is that the layout-rendered blocks are all the same --
> namely
> > the last block added to Layout by Foo.  What am I doing wrong?  Code and
> and
> > rendering results:
> >
> > Foo.java
> > ------------
> > @Property (write = false)
> > private int _ref;
> >
> > @Inject
> > private ComponentResources _resources;
> >
> > void beginRender () {
> >     _ref = (new Object()).hashCode(); // For a pretty reliably random
> int.
> >     Layout layout = (Layout)
> > _resources.getPage().getComponentResources().getEmbeddedComponent(
> "layout"
> > );
> >     layout.addPostWrapperBlock( _resources.findBlock( "tester" ));
> > }
> >
> > Foo.tml
> > ----------
> > <t:container xmlns:t="
> http://tapestry.apache.org/schema/tapestry_5_0_0.xsd">
> >     <t:block t:id="tester">
> >         <p>Ref: ${ref}</p>
> >     </t:block>
> >     <t:delegate to="block:tester" />
> > </t:container>
> >
> > TestPage.tml
> > ------------------
> > <t:layout t:id="layout" xmlns:t="
> > http://tapestry.apache.org/schema/tapestry_5_0_0.xsd">
> >     <t:loop source="0..2"><t:test.foo /></t:loop>
> > </t:layout>
> >
> > Layout.tml (partial)
> > -------------------------
> > ...
> > <t:loop source="postWrapperBlocks" value="var:pwb"><t:delegate
> to="var:pwb"
> > /></t:loop>
> > </body>
> > </html>
> >
> > When Foo renders in TestPage's template, no problem:
> > Ref: 16084489
> > Ref: 736239
> > Ref: 9163575
> >
> > But the rendering at the bottom of Layout is
> > Ref: 9163575
> > Ref: 9163575
> > Ref: 9163575
> >
> >
>
> --
> http://thegodcode.net
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe@tapestry.apache.org
> For additional commands, e-mail: users-help@tapestry.apache.org
>
>


-- 
Those who can make you believe absurdities can make you commit atrocities.

Voltaire

Re: T5: Passing (looped) component blocks to layout for (looped) rendering

Posted by Chris Lewis <ch...@bellsouth.net>.
Hi Bill,

You normally have some interesting questions :-) - I don't see
t:delegate et al used often and am still trying to digest how they can
be used effectively. For your issue, unfortunately I don't know how to
fix it at the moment, but the problem exactly here (in Foo.java):

layout.addPostWrapperBlock( _resources.findBlock( "tester" ));

You've assumed that on each loop iteration, the block by id 'tester'
will exist in its own microcosm and therefore be accessible by that id.
In reality what I think is happening is that tapestry knows what block
has id 'tester', and in subsequent loop iterations over your blocks I'm
guessing that all but the last block will be replaced because of the
hardcoded block id.

Because you're looping you need to let tapestry generate the ids, but
then of course there's the question of how to get at them. Now how to
fix it...

chris

Bill Holloway wrote:
> Hi All,
>
> I have a component Foo in a loop on my TestPage.  Foo has a block on it
> which Foo's template renders and which Foo's page class also picks up and
> adds to a list of blocks on the TestPage's surrounding Layout component.
> Layout loops over these blocks and renders them just before the </body>
> tag.   Problem is that the layout-rendered blocks are all the same -- namely
> the last block added to Layout by Foo.  What am I doing wrong?  Code and and
> rendering results:
>
> Foo.java
> ------------
> @Property (write = false)
> private int _ref;
>
> @Inject
> private ComponentResources _resources;
>
> void beginRender () {
>     _ref = (new Object()).hashCode(); // For a pretty reliably random int.
>     Layout layout = (Layout)
> _resources.getPage().getComponentResources().getEmbeddedComponent( "layout"
> );
>     layout.addPostWrapperBlock( _resources.findBlock( "tester" ));
> }
>
> Foo.tml
> ----------
> <t:container xmlns:t="http://tapestry.apache.org/schema/tapestry_5_0_0.xsd">
>     <t:block t:id="tester">
>         <p>Ref: ${ref}</p>
>     </t:block>
>     <t:delegate to="block:tester" />
> </t:container>
>
> TestPage.tml
> ------------------
> <t:layout t:id="layout" xmlns:t="
> http://tapestry.apache.org/schema/tapestry_5_0_0.xsd">
>     <t:loop source="0..2"><t:test.foo /></t:loop>
> </t:layout>
>
> Layout.tml (partial)
> -------------------------
> ...
> <t:loop source="postWrapperBlocks" value="var:pwb"><t:delegate to="var:pwb"
> /></t:loop>
> </body>
> </html>
>
> When Foo renders in TestPage's template, no problem:
> Ref: 16084489
> Ref: 736239
> Ref: 9163575
>
> But the rendering at the bottom of Layout is
> Ref: 9163575
> Ref: 9163575
> Ref: 9163575
>
>   

-- 
http://thegodcode.net


---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tapestry.apache.org
For additional commands, e-mail: users-help@tapestry.apache.org


Re: T5: Passing (looped) component blocks to layout for (looped) rendering

Posted by Josh Canfield <jo...@thedailytube.com>.
Hi Bill,

Because you are rendering your foo component in a loop you only have
one instance of it. Each time through the loop it's going through the
rendering phase and setting it's ref property to the new value. Then
you are adding a Block from within that component to your list.

When your layout renders the block foo.setupRender is not called
because it's not the component that is rendering, it's the block from
within the component. Since foo.setupRender doesn't get a chance to
update the ref property you get the same value again.

If you were to include several instances of foo in your page then you
would get a different value for each because you would have multiple
instances.

Moving blocks to the end of the page is a problem I've had to solve
recently. I ended up adding an afterRender handler that grabs the
Document from the MarkupWriter, grabs the component from the DOM by id
and append it to the body elements children. It's not perfect because
the document model doesn't have all the setters required (there's a
jira ticket to fix that) but it works great when I have a popup form
that gets created in the middle of another form.

I'd be happy to hear if someone else has come up with a better solution.

Josh

On Thu, May 1, 2008 at 8:47 PM, Bill Holloway <bi...@peoplepad.com> wrote:
> Hi All,
>
> I have a component Foo in a loop on my TestPage.  Foo has a block on it
> which Foo's template renders and which Foo's page class also picks up and
> adds to a list of blocks on the TestPage's surrounding Layout component.
> Layout loops over these blocks and renders them just before the </body>
> tag.   Problem is that the layout-rendered blocks are all the same -- namely
> the last block added to Layout by Foo.  What am I doing wrong?  Code and and
> rendering results:
>
> Foo.java
> ------------
> @Property (write = false)
> private int _ref;
>
> @Inject
> private ComponentResources _resources;
>
> void beginRender () {
>    _ref = (new Object()).hashCode(); // For a pretty reliably random int.
>    Layout layout = (Layout)
> _resources.getPage().getComponentResources().getEmbeddedComponent( "layout"
> );
>    layout.addPostWrapperBlock( _resources.findBlock( "tester" ));
> }
>
> Foo.tml
> ----------
> <t:container xmlns:t="http://tapestry.apache.org/schema/tapestry_5_0_0.xsd">
>    <t:block t:id="tester">
>        <p>Ref: ${ref}</p>
>    </t:block>
>    <t:delegate to="block:tester" />
> </t:container>
>
> TestPage.tml
> ------------------
> <t:layout t:id="layout" xmlns:t="
> http://tapestry.apache.org/schema/tapestry_5_0_0.xsd">
>    <t:loop source="0..2"><t:test.foo /></t:loop>
> </t:layout>
>
> Layout.tml (partial)
> -------------------------
> ...
> <t:loop source="postWrapperBlocks" value="var:pwb"><t:delegate to="var:pwb"
> /></t:loop>
> </body>
> </html>
>
> When Foo renders in TestPage's template, no problem:
> Ref: 16084489
> Ref: 736239
> Ref: 9163575
>
> But the rendering at the bottom of Layout is
> Ref: 9163575
> Ref: 9163575
> Ref: 9163575
>
> --
> Bill @ PeoplePad
>



-- 
--
TheDailyTube.com. Sign up and get the best new videos on the internet
delivered fresh to your inbox.

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tapestry.apache.org
For additional commands, e-mail: users-help@tapestry.apache.org