You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@tapestry.apache.org by Erik Hatcher <er...@ehatchersolutions.com> on 2003/10/07 19:49:41 UTC

Custom table component cell rendering

Does anyone have an example of doing custom rendering of a cell using 
the contrib table component?

I want one column to be an external hyperlink (with the link text being 
the current cell value) and a parameter based on row value.  I'm sure I 
can use ComponentTableRendererSource somehow, but just wondering if 
anyone has an example that I could leverage.

Thanks,
	Erik


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


Re: Custom table component cell rendering

Posted by Jamie Orchard-Hays <ja...@dang.com>.
Just wanted to echo Erik's sentiments below. (I worked with him a bit on
this stuff today.) It's going to save us a lot of work going forward.

Jamie


----- Original Message ----- 
From: "Erik Hatcher" <er...@ehatchersolutions.com>
>
> You have done a fantastic job with the Table component and all the
> pieces.  It was not "Simple" at all though :)  But a lot of that has to
> do with my learning curve with Tapestry in general as well as my
> inexperience in similar concepts from Swing.  But I was able, thanks to
> the list help, to get a quite elegant solution to our needs done making
> future use of the table component in our system quite streamlined.
>
> Erik
>


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


Re: Custom table component cell rendering

Posted by Erik Hatcher <er...@ehatchersolutions.com>.
On Wednesday, October 15, 2003, at 12:10  PM, Mind Bridge wrote:
> If you have access to a RequestCycle, you can load a page and get a
> particular component from it. ITableColumn tries to provide a 
> RequestCycle
> in the methods you may need it, so you should be all set.

Excellent... just the pointer I needed to get this working.

So, I got this working by implementing a BeanTableColumn, 
BeanTableColumnModel, and a BeanTableModel (all subclassing the 
SimpleTable* stuff).  The magic in the BeanTableColumn is that the 
value renderer looks up a Block and uses it if its there, otherwise 
delegates to super which is the StringRenderer stuff.  I wasn't happy 
about getComponent throwing an exception rather than returning null if 
its not there, as catching ApplicationRuntimeException seemed bad to 
do, but it worked.

Also, interestingly, for the column renderer, I look up a message 
resource (PageName.columnName format) and setDisplayName with that 
value, making our column header text be pulled from a database.

So, I'm quite pleased with how it has turned out.

I think my next step will make a Table component subclass that allows 
us to specify the columns (i.e. the OGNL expressions to get to the 
column values really) in the .page file rather than in .java making it 
even more decoupled.

> It appears that some concepts used by Table component are more 
> confusing
> than I had anticipated. Flexibility is not always appreciated 
> ("defaults!
> defaults!"). To reduce the complexity perhaps we should allow things 
> like
> the column model to be defined in XML and have code that reads that and
> automatically creates the Java objects needed. Perhaps this will be 
> easier?

You have done a fantastic job with the Table component and all the 
pieces.  It was not "Simple" at all though :)  But a lot of that has to 
do with my learning curve with Tapestry in general as well as my 
inexperience in similar concepts from Swing.  But I was able, thanks to 
the list help, to get a quite elegant solution to our needs done making 
future use of the table component in our system quite streamlined.

	Erik


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


RE: Custom table component cell rendering

Posted by Mind Bridge <mi...@yahoo.com>.
Hi Erik,

> My main bottleneck is more with grasping how to do things with the
> Tapestry API here.  In this case, how do I get a Block from within a
> ITableColumnModel implementing class?  I hacked it by getting it from
> my Page and passing it in from there currently, but I'm sure there is a
> cleaner way.  How?

If you have access to a RequestCycle, you can load a page and get a
particular component from it. ITableColumn tries to provide a RequestCycle
in the methods you may need it, so you should be all set.

You cannot at the moment directly load a component without it being embedded
in a page. The reason is that the page provides a lot of services that the
component and its included components neeed. We have been playing around
with the concept of 'proxy page' here that would allow 'standalone'
components to be used efficiently but this is not official yet, so I guess
it is another topic.


It appears that some concepts used by Table component are more confusing
than I had anticipated. Flexibility is not always appreciated ("defaults!
defaults!"). To reduce the complexity perhaps we should allow things like
the column model to be defined in XML and have code that reads that and
automatically creates the Java objects needed. Perhaps this will be easier?

-mb


-----Original Message-----
From: Erik Hatcher [mailto:erik@ehatchersolutions.com]
Sent: Thursday, October 09, 2003 5:01 PM
To: Tapestry users
Subject: Re: Custom table component cell rendering


On Thursday, October 9, 2003, at 04:23  AM, Michael Kolmodin wrote:
> Erik Hatcher wrote:
>>
>> But now I want to generalize what I've done so I can reuse this type
>> of thing for all of the list-linking-to-detail types of pages we'll
>> have in our system.  I'll be working through how to do this - which I
>> presume will entail using a custom Table component piece somehow, as
>> well as a custom model to address the cell renderer setting.  *whew
>> my brain hurts!*
>>     Erik
>
> My solution was to create a new class implementing  ITableColumnModel.
> Basically, my column model takes a list of column names and creates an
> instance of SimpleTableColumn for each of those. But it also checks if
> there is a Block with the same name as the column available, and in
> that case uses that Block to render the column. Just a few lines of
> code actually, and it automagically picks up whatever Block present in
> the Table page template.

My main bottleneck is more with grasping how to do things with the
Tapestry API here.  In this case, how do I get a Block from within a
ITableColumnModel implementing class?  I hacked it by getting it from
my Page and passing it in from there currently, but I'm sure there is a
cleaner way.  How?

Thanks,
	Erik


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


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


Re: Custom table component cell rendering

Posted by Erik Hatcher <er...@ehatchersolutions.com>.
On Thursday, October 9, 2003, at 04:23  AM, Michael Kolmodin wrote:
> Erik Hatcher wrote:
>>
>> But now I want to generalize what I've done so I can reuse this type 
>> of thing for all of the list-linking-to-detail types of pages we'll 
>> have in our system.  I'll be working through how to do this - which I 
>> presume will entail using a custom Table component piece somehow, as 
>> well as a custom model to address the cell renderer setting.  *whew 
>> my brain hurts!*
>>     Erik
>
> My solution was to create a new class implementing  ITableColumnModel. 
> Basically, my column model takes a list of column names and creates an 
> instance of SimpleTableColumn for each of those. But it also checks if 
> there is a Block with the same name as the column available, and in 
> that case uses that Block to render the column. Just a few lines of 
> code actually, and it automagically picks up whatever Block present in 
> the Table page template.

My main bottleneck is more with grasping how to do things with the 
Tapestry API here.  In this case, how do I get a Block from within a 
ITableColumnModel implementing class?  I hacked it by getting it from 
my Page and passing it in from there currently, but I'm sure there is a 
cleaner way.  How?

Thanks,
	Erik


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


Re: Custom table component cell rendering

Posted by Erik Hatcher <er...@ehatchersolutions.com>.
On Thursday, October 9, 2003, at 04:23  AM, Michael Kolmodin wrote:
> Erik Hatcher wrote:
>>
>> But now I want to generalize what I've done so I can reuse this type 
>> of thing for all of the list-linking-to-detail types of pages we'll 
>> have in our system.  I'll be working through how to do this - which I 
>> presume will entail using a custom Table component piece somehow, as 
>> well as a custom model to address the cell renderer setting.  *whew 
>> my brain hurts!*
>>     Erik
>
> My solution was to create a new class implementing  ITableColumnModel. 
> Basically, my column model takes a list of column names and creates an 
> instance of SimpleTableColumn for each of those. But it also checks if 
> there is a Block with the same name as the column available, and in 
> that case uses that Block to render the column. Just a few lines of 
> code actually, and it automagically picks up whatever Block present in 
> the Table page template.

Wow... I was actually just thinking of this very thing since, depending 
on the page, each column may render differently.

Could you share the code you have done to do this and jump start me on 
this path?  I'm pretty sure I could hack through this myself, but it'd 
speed me up to see the code.

Thanks,
	Erik


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


Re: Custom table component cell rendering

Posted by Michael Kolmodin <Mi...@kolmodin.net>.
Erik Hatcher wrote:
>
> 
> 
> But now I want to generalize what I've done so I can reuse this type of 
> thing for all of the list-linking-to-detail types of pages we'll have in 
> our system.  I'll be working through how to do this - which I presume 
> will entail using a custom Table component piece somehow, as well as a 
> custom model to address the cell renderer setting.  *whew my brain hurts!*
> 
>     Erik

My solution was to create a new class implementing  ITableColumnModel. 
Basically, my column model takes a list of column names and creates an 
instance of SimpleTableColumn for each of those. But it also checks if 
there is a Block with the same name as the column available, and in that 
case uses that Block to render the column. Just a few lines of code 
actually, and it automagically picks up whatever Block present in the 
Table page template.

-- michael


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


Re: Custom table component cell rendering

Posted by Erik Hatcher <er...@ehatchersolutions.com>.
On Tuesday, October 7, 2003, at 05:28  PM, Mindbridge wrote:
>> Doesn't this make every cell be a hyperlink?  I'm just interested in
>> one column being a hyperlink.
>
> No, not really. The key is in the Java code:

Got it.  I think (?)  :)

Thank you again for all your help and patience.  I got it working with 
a unique column rendering for one of the columns with an ExternalLink.

> P.S. If this would be of interest, note that the block used can be in a
> completely different page as well. In fact, this is how the column 
> headers
> work -- they are defined in a separate page in the
> org.apache.tapestry.contrib.table.components.inserted package, but are
> rendered where you want them. This trick might be helpful for what you 
> are
> doing.

But now I want to generalize what I've done so I can reuse this type of 
thing for all of the list-linking-to-detail types of pages we'll have 
in our system.  I'll be working through how to do this - which I 
presume will entail using a custom Table component piece somehow, as 
well as a custom model to address the cell renderer setting.  *whew my 
brain hurts!*

	Erik


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


Re: Custom table component cell rendering

Posted by Erik Hatcher <er...@ehatchersolutions.com>.
On Tuesday, October 7, 2003, at 05:28  PM, Mindbridge wrote:
>>     // set the renderer of the exampleColumn
>>     Block exampleBlock = (Block) getComponent("exampleBlock");
>>     exampleColumn.setValueRendererSource(new
>> BlockTableRendererSource(exampleBlock));
>
> This essentially tells the program to use 'exampleBlock' to render the 
> value
> of exampleColumn (i.e. it applies only to the cells in that column).

thanks again!

> P.S. If this would be of interest, note that the block used can be in a
> completely different page as well. In fact, this is how the column 
> headers
> work -- they are defined in a separate page in the
> org.apache.tapestry.contrib.table.components.inserted package, but are
> rendered where you want them. This trick might be helpful for what you 
> are
> doing.

Yes, I saw that you had a separate "dummy" page placeholder for those.  
But that seemed odd to me.

I presume I can just use my own @DetailLink component somehow which is 
just a .html/.jwc (no Java needed, I don't think) that wraps an 
ExternalLink.  Could I do that without having to use a block within the 
current page or having a placeholder page?  If so, how?

Thanks,
	Erik


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


Re: Custom table component cell rendering

Posted by Mindbridge <mi...@yahoo.com>.
Hi,

> Doesn't this make every cell be a hyperlink?  I'm just interested in
> one column being a hyperlink.

No, not really. The key is in the Java code:

>     // set the renderer of the exampleColumn
>     Block exampleBlock = (Block) getComponent("exampleBlock");
>     exampleColumn.setValueRendererSource(new
> BlockTableRendererSource(exampleBlock));

This essentially tells the program to use 'exampleBlock' to render the value
of exampleColumn (i.e. it applies only to the cells in that column).

You can either create the column and configure it as shown above, or if you
create the columns using the ExpressionColumnModel, you can get the column
from the model using getColumn(<column name>) and then configure it.

Hope this helps...

Best regards,
-mb

P.S. If this would be of interest, note that the block used can be in a
completely different page as well. In fact, this is how the column headers
work -- they are defined in a separate page in the
org.apache.tapestry.contrib.table.components.inserted package, but are
rendered where you want them. This trick might be helpful for what you are
doing.


----- Original Message ----- 
From: "Erik Hatcher" <er...@ehatchersolutions.com>
To: "Tapestry users" <ta...@jakarta.apache.org>
Sent: Tuesday, October 07, 2003 10:48 PM
Subject: Re: Custom table component cell rendering


> Thanks for that info.  I haven't tried this yet, but will soon.  But
> some questions inline below...
>
> On Tuesday, October 7, 2003, at 03:01  PM, Mindbridge wrote:
> > .html file:
> > ---------
> >
> > ....
> > <span jwcid="table@contrib:Table" row="ognl:currentRow"
> > column="ognl:currentColumn"/>
> > ....
> >
> > <!-- this is the Block defining the column appearance -->
> > <span jwcid="exampleBlock@Block">
> >     <a jwcid="@DirectLink" listener="ognl:listeners.someListener"
> > parameters="ognl:currentRow">
> >         <span jwcid="@Insert"
> > value="ognl:currentColumn.getColumnValue(currentRow)"/>
> >     </a>
> > </span>
>
> Doesn't this make every cell be a hyperlink?  I'm just interested in
> one column being a hyperlink.
>
>
>
> > .java file
> > --------
> >
> >     // set the renderer of the exampleColumn
> >     Block exampleBlock = (Block) getComponent("exampleBlock");
> >     exampleColumn.setValueRendererSource(new
> > BlockTableRendererSource(exampleBlock));
>
> I'll have to give this a try, but this looks promising.  I'm after
> making a general-purpose customized table component that we can re-use
> across multiple pages, but with different types of data (master lists,
> hyperlinking to detail pages), so I'm going to have to generalize
> things a lot more, but first I'm trying to get one working with this
> nicely.  Again, the table component rocks.... I just haven't figured
> out how to use it well enough yet :)
>
> Erik
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: tapestry-user-unsubscribe@jakarta.apache.org
> For additional commands, e-mail: tapestry-user-help@jakarta.apache.org


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


Re: Custom table component cell rendering

Posted by Erik Hatcher <er...@ehatchersolutions.com>.
Thanks for that info.  I haven't tried this yet, but will soon.  But 
some questions inline below...

On Tuesday, October 7, 2003, at 03:01  PM, Mindbridge wrote:
> .html file:
> ---------
>
> ....
> <span jwcid="table@contrib:Table" row="ognl:currentRow"
> column="ognl:currentColumn"/>
> ....
>
> <!-- this is the Block defining the column appearance -->
> <span jwcid="exampleBlock@Block">
>     <a jwcid="@DirectLink" listener="ognl:listeners.someListener"
> parameters="ognl:currentRow">
>         <span jwcid="@Insert"
> value="ognl:currentColumn.getColumnValue(currentRow)"/>
>     </a>
> </span>

Doesn't this make every cell be a hyperlink?  I'm just interested in 
one column being a hyperlink.



> .java file
> --------
>
>     // set the renderer of the exampleColumn
>     Block exampleBlock = (Block) getComponent("exampleBlock");
>     exampleColumn.setValueRendererSource(new
> BlockTableRendererSource(exampleBlock));

I'll have to give this a try, but this looks promising.  I'm after 
making a general-purpose customized table component that we can re-use 
across multiple pages, but with different types of data (master lists, 
hyperlinking to detail pages), so I'm going to have to generalize 
things a lot more, but first I'm trying to get one working with this 
nicely.  Again, the table component rocks.... I just haven't figured 
out how to use it well enough yet :)

	Erik


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


Re: Custom table component cell rendering

Posted by Mindbridge <mi...@yahoo.com>.
For the current version, perhaps something along the lines of this:

.jwc/.page file:
---------------

<property-specification name="currentRow" type="...."/>
<property-specification name="currentColumn"
type="org.apache.tapestry.contrib.model.simple.SimpleTableColumn"/>
....

.html file:
---------

....
<span jwcid="table@contrib:Table" row="ognl:currentRow"
column="ognl:currentColumn"/>
....

<!-- this is the Block defining the column appearance -->
<span jwcid="exampleBlock@Block">
    <a jwcid="@DirectLink" listener="ognl:listeners.someListener"
parameters="ognl:currentRow">
        <span jwcid="@Insert"
value="ognl:currentColumn.getColumnValue(currentRow)"/>
    </a>
</span>


.java file
--------

    // set the renderer of the exampleColumn
    Block exampleBlock = (Block) getComponent("exampleBlock");
    exampleColumn.setValueRendererSource(new
BlockTableRendererSource(exampleBlock));



This is similar to the LocaleSelection example. I will see if I can simplify
it more.

Best regards,
-mb


----- Original Message ----- 
From: "Erik Hatcher" <er...@ehatchersolutions.com>
To: "Tapestry users" <ta...@jakarta.apache.org>
Sent: Tuesday, October 07, 2003 8:49 PM
Subject: Custom table component cell rendering


> Does anyone have an example of doing custom rendering of a cell using
> the contrib table component?
>
> I want one column to be an external hyperlink (with the link text being
> the current cell value) and a parameter based on row value.  I'm sure I
> can use ComponentTableRendererSource somehow, but just wondering if
> anyone has an example that I could leverage.
>
> Thanks,
> Erik
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: tapestry-user-unsubscribe@jakarta.apache.org
> For additional commands, e-mail: tapestry-user-help@jakarta.apache.org


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