You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@tapestry.apache.org by Richard Hoberman <ri...@sadalbari.com> on 2008/08/18 12:14:03 UTC

[T5] Injecting page into nested layouts

Hi

I'm getting the following exception:

Component TestPage:innerlayout is not assignable to field
test.components.Layout.page (of type test.BasePage).

The skeletons for my components are below.  Essentially, my page has an
(inner) layout, which in turn has an (outer) layout.  I try to inject the
page into both (inner and outer) layouts.

The page is successfully injected into the inner layout, but the outer
fails.  @InjectContainer seems to be selecting the wrong component in this
case.  It makes no difference if I remove the injection for the inner layout
(so it doesn't seem to be a conflict).

Should this work?

Richard Hoberman

Page template:
-----------------
<html t:type="InnerLayout" ...>

   //page contents
   
</html>

Inner layout template:
--------------------------

<html t:type="Layout" ...>

   //inner layout markup including <t:body />

</html>

Layout template:
--------------------

<html  ...>

   //layout markup including <t:body />

</html>

Inner Layout class:
----------------------
public class InnerLayout extends BaseComponent {
	
	@InjectContainer
	@Property
	private BasePage page; 

       //etc	
}

Layout class:
---------------
public class InnerLayout extends BaseComponent {
	
	@InjectContainer
	@Property
	private BasePage page; 

       //etc	
}
-- 
View this message in context: http://www.nabble.com/-T5--Injecting-page-into-nested-layouts-tp19028771p19028771.html
Sent from the Tapestry - User mailing list archive at Nabble.com.


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


Re: [T5] Injecting page into nested layouts

Posted by "Filip S. Adamsen" <fs...@fsadev.com>.
Hi,

> You're right - casting componentResources#getPage works fine.

ComponentResources is your friend. :)

>> @InjectContainer does indeed inject the "parent" of the component. For 
>> InnerLayout this is the page alright, but for Layout it's actually the 
>> InnerLayout because Layout is contained in InnerLayout.
> 
> Could you clarify the meaning of 'contained'?

I think ComponentResources#getContainer has the best explanation:

"Returns the component which contains this component, or null for the 
root component. For mixins, this returns the componet to which the mixin 
is attached."

I probably shouldn't have used the word "parent", it's a bit confusing 
in this context.

> From an html point of view
> (and I assume a component tree point of view), the hierarchy of my page is:
> 
> Page
>  +-- Layout
>   +-- InnerLayout

That is correct.

> However, if "Layout is contained in InnerLayout" means "InnerLayout.tml
> references Layout.tml" then the 'reference' hierarchy is:
> 
> Page
>  +-- InnerLayout
>   +-- Layout

Also correct.

> Should I be reading "InjectContainer" as
> "InjectTheComponentWhoseTemplateContainsTheContentsToBeInsertedAsBody"?  If
> so, perhaps @InjectContentProvider would be more intuitive?

No, just InjectTheComponentWhoseTemplateContainsThisComponent.

> Is there any documentation on @InjectContainer?  I've searched the Tapestry
> site and Wiki but found nothing.

Here are the relevant docs:

http://tapestry.apache.org/tapestry5/apidocs/org/apache/tapestry5/annotations/InjectContainer.html
http://tapestry.apache.org/tapestry5/apidocs/org/apache/tapestry5/ComponentResources.html#getContainer()

InjectContainer should probably have its description updated to match 
ComponentResources#getContainer. I'll file a JIRA issue.

Hope this helps. If not, you know what to do. ;)

-Filip

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


Re: [T5] Injecting page into nested layouts

Posted by Richard Hoberman <ri...@sadalbari.com>.
You're right - casting componentResources#getPage works fine.

> @InjectContainer does indeed inject the "parent" of the component. For 
> InnerLayout this is the page alright, but for Layout it's actually the 
> InnerLayout because Layout is contained in InnerLayout.

Could you clarify the meaning of 'contained'?  From an html point of view
(and I assume a component tree point of view), the hierarchy of my page is:

Page
 +-- Layout
  +-- InnerLayout

However, if "Layout is contained in InnerLayout" means "InnerLayout.tml
references Layout.tml" then the 'reference' hierarchy is:

Page
 +-- InnerLayout
  +-- Layout

Should I be reading "InjectContainer" as
"InjectTheComponentWhoseTemplateContainsTheContentsToBeInsertedAsBody"?  If
so, perhaps @InjectContentProvider would be more intuitive?

Is there any documentation on @InjectContainer?  I've searched the Tapestry
site and Wiki but found nothing.
-- 
View this message in context: http://www.nabble.com/-T5--Injecting-page-into-nested-layouts-tp19028771p19046282.html
Sent from the Tapestry - User mailing list archive at Nabble.com.


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


Re: [T5] Injecting page into nested layouts

Posted by "Filip S. Adamsen" <fs...@fsadev.com>.
Hi again,

> That's a typo.  The Layout class name should read 'Layout' and not
> 'InnerLayout' but the relevant code is the same.

Ah, okay.

>> A potential solution would be to use ComponentResources#getPage to get 
>> your page in a getter and just use that in your layout.
> 
> Unfortunately, that won't work.  CompontResources#getPage returns
> (org.apache.tapestry5.runtime.)Component, which doesn't expose the page's
> properties. (See Howard's post at:
> http://www.nabble.com/Re%3A--T5--Expansions---calling-page-methods-via-componentResources-p19006392.html)

It works if you cast it:

   @Inject
   private ComponentResources resources;

   public BasePage getPage() {
     return (BasePage) resources.getPage();
   }

It just doesn't work directly with property expressions like 
${resources.page}.

> I'm a bit confused by the terminology. I can't seem to find the docs on
> @InjectContainer, but I assumed it injected the 'parent' of the component,
> because the page is the root of the component tree.  Now now it seems that
> it injects the contents of the layout?

@InjectContainer does indeed inject the "parent" of the component. For 
InnerLayout this is the page alright, but for Layout it's actually the 
InnerLayout because Layout is contained in InnerLayout.

The exception states this as well, this is what I missed the first time 
through:

"Component TestPage:innerlayout is not assignable to field
test.components.Layout.page (of type test.BasePage)."

So the component innerlayout in the page TestPage is not assignable to 
the field page in Layout - because Layout expects page to be of type 
BasePage.

> There must be a way to do this...

See above. Just use ComponentResources and cast it, simple as that.

> Richard

-Filip

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


Re: [T5] Injecting page into nested layouts

Posted by Richard Hoberman <ri...@sadalbari.com>.
Hi Filip

That's a typo.  The Layout class name should read 'Layout' and not
'InnerLayout' but the relevant code is the same.

> A potential solution would be to use ComponentResources#getPage to get 
> your page in a getter and just use that in your layout.

Unfortunately, that won't work.  CompontResources#getPage returns
(org.apache.tapestry5.runtime.)Component, which doesn't expose the page's
properties. (See Howard's post at:
http://www.nabble.com/Re%3A--T5--Expansions---calling-page-methods-via-componentResources-p19006392.html)

I'm a bit confused by the terminology. I can't seem to find the docs on
@InjectContainer, but I assumed it injected the 'parent' of the component,
because the page is the root of the component tree.  Now now it seems that
it injects the contents of the layout?

There must be a way to do this...

Richard
-- 
View this message in context: http://www.nabble.com/-T5--Injecting-page-into-nested-layouts-tp19028771p19034207.html
Sent from the Tapestry - User mailing list archive at Nabble.com.


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


Re: [T5] Injecting page into nested layouts

Posted by "Filip S. Adamsen" <fs...@fsadev.com>.
Hi,

Looking over your code again I just noticed something's amiss. Where's 
the Java code for the Layout class? You seem to have posted the 
InnerLayout class twice.

Anyhow, I think I've figured out what's really going on. Your using 
InjectContainer in Layout, but that doesn't inject the page, it injects 
the InnerLayout. This, of course, fails.

A potential solution would be to use ComponentResources#getPage to get 
your page in a getter and just use that in your layout.

-Filip

On 2008-08-18 15:30, Filip S. Adamsen wrote:
> Hi,
> 
> Your BasePage should be in the base subpackage, that's test.base in your 
> case. What happens is that Tapestry tries to cast BasePage to Component, 
> which fails because it hasn't been enhanced by Tapestry - this only 
> happens for components in the base, components, and page subpackages.
> 
> That's my (more or less informed) guess having checked the source of 
> InjectContainerWorker, anyhow.
> 
> -Filip
> 
> On 2008-08-18 12:14, Richard Hoberman wrote:
>> Hi
>>
>> I'm getting the following exception:
>>
>> Component TestPage:innerlayout is not assignable to field
>> test.components.Layout.page (of type test.BasePage).
>>
>> The skeletons for my components are below.  Essentially, my page has an
>> (inner) layout, which in turn has an (outer) layout.  I try to inject the
>> page into both (inner and outer) layouts.
>>
>> The page is successfully injected into the inner layout, but the outer
>> fails.  @InjectContainer seems to be selecting the wrong component in 
>> this
>> case.  It makes no difference if I remove the injection for the inner 
>> layout
>> (so it doesn't seem to be a conflict).
>>
>> Should this work?
>>
>> Richard Hoberman
>>
>> Page template:
>> -----------------
>> <html t:type="InnerLayout" ...>
>>
>>    //page contents
>>    </html>
>>
>> Inner layout template:
>> --------------------------
>>
>> <html t:type="Layout" ...>
>>
>>    //inner layout markup including <t:body />
>>
>> </html>
>>
>> Layout template:
>> --------------------
>>
>> <html  ...>
>>
>>    //layout markup including <t:body />
>>
>> </html>
>>
>> Inner Layout class:
>> ----------------------
>> public class InnerLayout extends BaseComponent {
>>     
>>     @InjectContainer
>>     @Property
>>     private BasePage page;
>>        //etc   
>> }
>>
>> Layout class:
>> ---------------
>> public class InnerLayout extends BaseComponent {
>>     
>>     @InjectContainer
>>     @Property
>>     private BasePage page;
>>        //etc   
>> }
> 
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe@tapestry.apache.org
> For additional commands, e-mail: users-help@tapestry.apache.org
> 

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


Re: [T5] Injecting page into nested layouts

Posted by "Filip S. Adamsen" <fs...@fsadev.com>.
Hi,

Your BasePage should be in the base subpackage, that's test.base in your 
case. What happens is that Tapestry tries to cast BasePage to Component, 
which fails because it hasn't been enhanced by Tapestry - this only 
happens for components in the base, components, and page subpackages.

That's my (more or less informed) guess having checked the source of 
InjectContainerWorker, anyhow.

-Filip

On 2008-08-18 12:14, Richard Hoberman wrote:
> Hi
> 
> I'm getting the following exception:
> 
> Component TestPage:innerlayout is not assignable to field
> test.components.Layout.page (of type test.BasePage).
> 
> The skeletons for my components are below.  Essentially, my page has an
> (inner) layout, which in turn has an (outer) layout.  I try to inject the
> page into both (inner and outer) layouts.
> 
> The page is successfully injected into the inner layout, but the outer
> fails.  @InjectContainer seems to be selecting the wrong component in this
> case.  It makes no difference if I remove the injection for the inner layout
> (so it doesn't seem to be a conflict).
> 
> Should this work?
> 
> Richard Hoberman
> 
> Page template:
> -----------------
> <html t:type="InnerLayout" ...>
> 
>    //page contents
>    
> </html>
> 
> Inner layout template:
> --------------------------
> 
> <html t:type="Layout" ...>
> 
>    //inner layout markup including <t:body />
> 
> </html>
> 
> Layout template:
> --------------------
> 
> <html  ...>
> 
>    //layout markup including <t:body />
> 
> </html>
> 
> Inner Layout class:
> ----------------------
> public class InnerLayout extends BaseComponent {
> 	
> 	@InjectContainer
> 	@Property
> 	private BasePage page; 
> 
>        //etc	
> }
> 
> Layout class:
> ---------------
> public class InnerLayout extends BaseComponent {
> 	
> 	@InjectContainer
> 	@Property
> 	private BasePage page; 
> 
>        //etc	
> }

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