To clarify:
I'm trying to use a .page component inside a @Foreach in my HTML.
This component happens to be a contrib:table.
The tables source is bound to the same ognl expression that my @Foreach is
setting as its "value". My design goal is to produce a table that looks
similar to the following with multiple tables of the same type on the same
page:
CATEGORY NAME
CATEGORY ITEM TABLE
CATEGORY NAME
CATEGORY ITEM TABLE
My @Foreach "source" is a collection of categories, the @Foreach "value" is
the category's collection of items. Again, I have the tableView component
used multiple times on a single page, with the "source" bound to different
collections via iterations of a @Foreach.
This all works fine on the first page rendering. However, when I try an
click on a table column header (to sort) it no longer has the source
availabe for the table. The ognl expression fails... When I examine all
the column header links they are exactly the same for all tables, this leads
me to believe that what I'm trying to do is not easily accomplished in the
manner I'm trying.
Any ideas or other methods to accomplish this type of display would be
greatly appreciated.
Thanks,
Joe
-----Original Message-----
From: Joe Goldwasser [mailto:[EMAIL PROTECTED]
Sent: Monday, July 25, 2005 11:10 AM
To: 'Tapestry users'
Subject: RE: Tapestry4 contrib:Table format & sort
Hi,
Thanks again for your assistance, it's invaluable...
I implemented some dynamic tables which was rather easy using your comments.
They render as expected, however I'm having an issue with sorting.
I get an error when sorting because the tableView's source can't be
evaluated properly.
Here's my .html code:
<span jwcid="@Foreach" source="ognl:segmentCategories"
value="ognl:segmentCategory">
<table class="bodyText" jwcid="segmentTableView" width="100%"
cellpadding="0" cellspacing="3">
<span jwcid="segmentTableColumns" />
<span jwcid="segmentTableRows" class="bodyText">
... ROW DETAIL HERE...
</table>
</span>
My .page code:
<component id="segmentTableView" type="contrib:TableView">
<binding name="source" value="ognl:segmentCategory.segments" />
<binding name="columns">'segmentName, totalCnt'</binding>
<binding name="pageSize" value="5" />
</component>
Ther error when sorting is:
Unable to read OGNL expression '<parsed OGNL expression>' of
[EMAIL PROTECTED]: source is null for getProperty(null,
"segments")
So, it seems that the tables are rendering fine when the page is built,
iterating over the "segmentCategories" list and populating the value for
"segmentCategory"... However, when sorting, the property "segmentCategory"
is no longer available...
How should I construct the ognl expression to keep the reference working
while sorting?
Thanks,
Joe
-----Original Message-----
From: Mind Bridge [mailto:[EMAIL PROTECTED]
Sent: Sunday, July 24, 2005 10:01 PM
To: Tapestry users
Subject: Re: Tapestry4 contrib:Table format & sort
Hi,
Thank you for your comments...
Here are the answers:
Alignment -- there was a thread about this recently. For a sortable column
please use the following CSS:
.actualWinColumnHeader table {
text-align: right;
}
This would work up to beta3. In beta4 and further you would no longer need
to put 'table' in -- your previous code would work, as the alignment
mechanism is now done differently (although it is not checked in yet, as it
is being verified against different browsers).
Dynamic contents -- there is absolutely no problem for 'source' and
'columns' to be dynamic (ognl) expressions and come from a map, for example,
in which the key is the page name. Basically, all tables in the Foreach (or
For) would have different columns and contents as a result.
You are not limited to having only 'static' tables at all.
Here is also another "advanced" solution: Another approach that you may
consider is getting a Block with a particular name located on the relevant
page, and rendering it in the Foreach using RenderBlock. What is placed in
the Block depends entirely on the page itself -- it could be a Table, a
static page, or something else. In that way each listed page could place a
very different description of itself, specific to what it represents. This
would be slower than the above, but it would offer an additional flexibility
that may be needed in some cases.
Joe Goldwasser wrote:
>Thanks mb...
>
>I determined that I needed to declare the column list as:
><binding name="columns">
> accountNumber:accountNumber, firstName:firstName, amount:amount
></binding>
>
>I think T4 requires that you have the id:expression, so when I just had
>the expression it was complaining about the improper ognl expression.
>
>Anyway, I now have the table working with the sorting and formatting.
>Great component you built!
>
>I have a couple more questions about the table. I'm not sure if either
>features I'm looking for are supported, but I figured you would be the
>best to ask.
>
>FIRST QUESTION:
>
>In my table I have some row values right justified, so that number line
>up properly. The columns headers, however, are all centered which
>makes them look a bit "off". I was wondering how I would go about
>changing how the column headers are rendered.
>
>Right now I have:
><table jwcid="membersTableView" width="100%" cellpadding="0"
cellspacing="3"
>border="0">
> <tr>
> <td class="bodyText" jwcid="membersTableColumns" />
> </tr>
>...
></table>
>
>I've tried to put an align="right" in the tr and td, however the
>rendering always ends up building a <table> tag that is centered to
>show the column name and sort image, etc. Do I need to use a @Block
>tag again here for the columnHeaders? Basically I'm trying to
>determine how to line up the row values with the column headers when
>they
are not centered.
>
>SECOND QUESTION:
>
>I have a few pages in my application that display a list of categories
>and the corresponding items in each category. I would like to use the
>table component to display the category's items and their properties.
>The problem I have is that number of categories is dynamic, and as far
>as I can tell the table component requires that it has a declaration in
>the .page/.jwc file for each table that will be rendered. Is there a
>way to dynamically set the properties, etc for an unknown number of
>tables
during runtime?
>
>If not, I would like to know if this would be a feasible add-on to the
>table component...
>
>Again, thanks for you help, it's been a great assistance to me in
>getting my momentum in the right direction. I'm very new to Tapestry
>and the contrib library, but so far I can see that it will be well
>worth the effort to learn the framework.
>
>-- Joe
>
>-----Original Message-----
>From: Mind Bridge [mailto:[EMAIL PROTECTED]
>Sent: Saturday, July 23, 2005 12:36 AM
>To: Tapestry users
>Subject: Re: Tapestry4 contrib:Table format & sort
>
>Hi,
>
>The reason is that the OGNL expressions are evaluated against the row
>object when sorting, but the expressions in the Block are evaluated
>against the page/component in which that block resides (this is to be
>expected as Block is a generic component).
>
>Thus, I am guessing that you have a Block that uses the 'lastPurchase'
>expression, but without the prefix
>'components.membersTableView.tableRow' that ensures that the expression
>is evaluated against the row object rather than the page.
>
>
>There are several options to avoid that problem:
>
>1) In all cases in the Blocks where an expression has to be evaluated
>against the row object, preprend it with
>'components.membersTableView.tableRow'.
>For example, 'lastPurchase' should become
>'components.membersTableView.tableRow.lastPurchase'
>
>2) Make a shortcut -- define a 'row' property in your page by adding
>the following to your .page file
> <property name="row"/>
>
>and then have the table store the current row object in it by adding
>the following line:
> <component id="membersTableFormRows" type="contrib:TableRows">
> <binding name="row" value="row"/>
> </component>
>
>The above expression can then become:
> row.lastPurchase
>
>In addition, the blocks that I wrote about also become shorter:
>
><span jwcid="[EMAIL PROTECTED]">
> <span jwcid="@Insert" value="row.formatDate(row.lastDate)"/>
></span>
>
>etc...
>
>I would suggest (2) as that would make the code much cleaner.
>
>I hope that helps...
>-mb
>
>
>Joe Goldwasser wrote:
>
>
>
>>Mind Bridge - Thanks for you reply.
>>
>>I updated my code to the follow the pattern you outlined.
>>
>>I'm getting an "ognl.NoSuchPropertyException" when it tries to load
>>the columns. It shows "$SegmentDetail_14.lastPurchase" with the error...
>>SegmentDetail is my page, the lastPurchase should be coming from the
>>items in the "members" list from the page, not the page directly.
>>
>>It seems to be trying to load the column from my page, instead of the
>>
>>
>>from the source (ie, <binding name="source" value="ognl:members" />)
>
>
>>Any ideas? I wonder if it's related to the fact that I'm using this
>>in a page and not a component.
>>
>>Thanks,
>>
>>Joe
>>
>>
>>
>>-----Original Message-----
>>From: Mind Bridge [mailto:[EMAIL PROTECTED]
>>Sent: Friday, July 22, 2005 6:20 PM
>>To: Tapestry users
>>Subject: Re: Tapestry4 contrib:Table format & sort
>>
>>Hi,
>>
>>The below explanation is also related to another message that appeared
>>on the list a bit earlier.
>>It is important to remember the below principle when working with
>>contrib:Table (and I am making a point to emphasize it in the docs).
>>
>>There are two distinct aspects of a table column:
>>
>>- The first one is the value used for sorting. This is the OGNL
>>expression given in the 'columns' string.
>>
>>- The second one is the visual representation of the column. By
>>default that is simply the string representation of the value used for
>>sorting, as the two often coincide. Nevertheless, it is possible to
>>define a more elaborate representation by declaring a Block with a
>>name
>>
>>
><column_id>ColumnValue.
>
>
>>To apply those principles, here is how I would approach what you want
>>to
>>
>>
>do:
>
>
>>In the .page/.jwc:
>>
>> <binding name="columns">
>> accountNumber, firstName, lastPurchase:amount, visitCnt,
>>
>>
>lastDate
>
>
>> </binding>
>>
>>
>>In the .html:
>>
>><span jwcid="[EMAIL PROTECTED]">
>> $<span jwcid="@Insert"
>>value="formatCurrency(components.membersTableView.tableRow.amount)"/>
>></span>
>>
>><span jwcid="[EMAIL PROTECTED]">
>> <span jwcid="@Insert"
>>value="formatNumber(components.membersTableView.tableRow.visitCnt)"/>
>></span>
>>
>><span jwcid="[EMAIL PROTECTED]">
>> <span jwcid="@Insert"
>>value="formatDate(components.membersTableView.tableRow.lastDate)"/>
>></span>
>>
>>
>>In .properties:
>>
>>accountNumber=Account Number
>>firstName=First Name
>>lastPurchase=Last Avg Purchase
>>visitCnt=Number Visits
>>lastDate=Last Date
>>
>>
>>In that way the columns will be sorted properly, there is more freedom
>>to make them look like it is needed, and column titles can contain
>>random symbols and are internationalizable.
>>
>>Please note that the code has not been tested and may contain bugs
>>here and there -- best to just extract the principles from it. There
>>are other less verbose ways to do the above (e.g. with a 'row'
>>property), but that is an optimization.
>>
>>-mb
>>
>>
>>Joe Goldwasser wrote:
>>
>>
>>
>>
>>
>>>I'm trying to get the contrib:table to format my data (date,
>>>currency, numbers, etc) then be able to sort it.
>>>
>>>I'm using Tapestry 4 beta 2.
>>>
>>>I'm able to get it to format properly, probably not the "correct" way
>>>- I use a method from my bean that is being rendered in my table to
>>>format the value and return it as a String. The problem I have now
>>>is that when I sort, I'm sorting strings, when it really needs to be
>>>sorting number, dates, etc.
>>>
>>>Here's what I have in my .page file:
>>>
>>><component id="membersTableView" type="contrib:TableView">
>>> <binding name="source" value="ognl:members" />
>>> <binding name="columns">
>>> Account Number:accountNumber, First Name:firstName, Last
>>> Avg Purchase:"$" + formatCurrency(amount), Number
>>>Visits:formatNumber(visitCnt),
>>> Last Date:formatDate(lastDate)
>>> </binding>
>>></component>
>>>
>>><component id="membersTableColumns" type="contrib:TableColumns" />
>>><component id="membersTablePages" type="contrib:TablePages" />
>>><component id="membersTableFormRows"
>>>type="contrib:TableRows"></component>
>>>
>>><component id="membersTableValues" type="contrib:TableValues" />
>>>
>>>The methods (formatCurrency, formatNumber, formatDate) are in my "Member"
>>>bean that the table is rendering. So this works for the format, but
>>>when I sort by clicking on the column headers they are now strings,
>>>which doesn't work as needed.
>>>
>>>Any advice is greatly appreciated.
>>>
>>>Thanks,
>>>Joe
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>---------------------------------------------------------------------
>>To unsubscribe, e-mail: [EMAIL PROTECTED]
>>For additional commands, e-mail: [EMAIL PROTECTED]
>>
>>
>>
>>---------------------------------------------------------------------
>>To unsubscribe, e-mail: [EMAIL PROTECTED]
>>For additional commands, e-mail: [EMAIL PROTECTED]
>>
>>
>>
>>
>>
>>
>
>---------------------------------------------------------------------
>To unsubscribe, e-mail: [EMAIL PROTECTED]
>For additional commands, e-mail: [EMAIL PROTECTED]
>
>
>
>---------------------------------------------------------------------
>To unsubscribe, e-mail: [EMAIL PROTECTED]
>For additional commands, e-mail: [EMAIL PROTECTED]
>
>
>
>
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]