dev@jsftemplating.java.net

Re: JSFTemplating: Enhancement #10: Dynamic table

From: Ken Paulsen <Ken.Paulsen_at_Sun.COM>
Date: Tue, 28 Aug 2007 16:14:11 -0700

Hi Karam,

I changed the DynamicColumnTableRowGroupFactory.java file to fire a
"createChild" event. This will allow you to manipulate what is created
in the columns. I wrote an example handler (very primitive) that
creates Hyperlinks with the value in each column as part of it's url.
This should be sufficient to demonstrate how to do what you are trying
to do. The event gets fired for every column... so if you only want a
hyperlink in the 1st column and something else (i.e. static text) in
other columns, your event handler will need to be smart enough to do this.

Attached:

  * DynamicColumnHandlers.java -- File w/ a handler that creates
Hyperlink's to google w/ a search string
  * table.jsf -- The table.jsf file I sent before (I think) with the
added <!createChild> event & handler.

You will also need the to checkout & build the latest
jsftemplating.jar... or wait for a nightly build which has the new
factory w/ the createChild event.

I hope this helps!

Ken


Karam Singh Badesha wrote:
> Ken,
> Is it possible to support the hyperlink for the columnValue as well.
> This is what I use in my tables where I need a dynamic table.
>
> thanks
> Karam
>
> Ken Paulsen wrote:
>>
>> Hi Karam,
>>
>> I am very sorry for my slow response time lately. I had a conference
>> then vacation, then lots of email. :(
>>
>> I just spent some time implementing this feature. Attached is a
>> sample .jsf page which includes all the data in the page. You
>> (obviously) would want to retrieve this from your database, backend
>> logic, or managed bean instead. However, I think it clearly shows
>> how to use the component.
>>
>> The table is the same. The table row group has a new name, the same
>> old properties, and all the column properties. The column properties
>> are prefixed with "column". All properties supported by the
>> Woodstock "tableColumn" component should work. Each column property
>> must be specified as a List (this is done in the .jsf page using
>> {"list element #1", "list element #2", ...} -- however, you can use a
>> #{} expression to resolve to your data which must be a List). There
>> is 1 additional property called "columnValue". This also must be a
>> List which contains the content for each column. Only staticText is
>> supported.
>>
>> Let me know if you have any questions or problems! You will need to
>> checkout/build JSFTemplating to get this feature... or wait until
>> tomorrow to get the nightly build.
>>
>> Thanks!
>>
>> Ken
>>
>> Karam Singh Badesha wrote:
>>> Ken,
>>> Any status?
>>>
>>> thanks
>>> Karam
>>>
>>> Ken Paulsen wrote:
>>>>
>>>> Hi Karam,
>>>>
>>>> I'm sorry I haven't made any progress. I will make an effort to
>>>> get something for you to look at this week.
>>>>
>>>> Ken
>>>>
>>>> Karam.Badesha_at_Sun.COM wrote:
>>>>> Ken,
>>>>> Any updates?
>>>>>
>>>>> thanks
>>>>> -Karam
>>>>>
>>>>> Ken Paulsen wrote:
>>>>>
>>>>>>
>>>>>> The foreach that I currently have is a component itself. So it
>>>>>> won't create multiple TableColumn components. Also the tree
>>>>>> doesn't allow non-tree UIComponents inside it.
>>>>>>
>>>>>> If we add a foreach that is executed during the creation time,
>>>>>> then yes... it would work. In JSFT, it wouldn't be too hard to do
>>>>>> this since the descriptors (LayoutElement) already exist for
>>>>>> looping, they'd just have to be used during the tree creation...
>>>>>> which amounts to 1 extra condition. We'd probably need a flag
>>>>>> indicating that it is intended for tree-creation time... or
>>>>>> perhaps a subclass of the existing while/foreach layoutelements.
>>>>>>
>>>>>> Ken
>>>>>>
>>>>>> Imre Oßwald wrote:
>>>>>>
>>>>>>> Couldn't that be done with some kind of foreach? (I think i have
>>>>>>> done that in facelets that way)
>>>>>>>
>>>>>>> Imre
>>>>>>>
>>>>>>> On 04.07.2007, at 03:17, Karam Singh Badesha wrote:
>>>>>>>
>>>>>>>> Ok great.
>>>>>>>>
>>>>>>>> thanks
>>>>>>>> Karam
>>>>>>>>
>>>>>>>> Ken Paulsen wrote:
>>>>>>>>
>>>>>>>>>
>>>>>>>>> I think I have enough to go on. I'm going to try to make this
>>>>>>>>> generic and put it in the JSFT code. Although when I get into
>>>>>>>>> it, I may change my mind. ;)
>>>>>>>>>
>>>>>>>>> Thanks!
>>>>>>>>>
>>>>>>>>> Ken
>>>>>>>>>
>>>>>>>>> Karam Singh Badesha wrote:
>>>>>>>>>
>>>>>>>>>> Ken,
>>>>>>>>>> This should be fine. Let me know if you are going to deliver
>>>>>>>>>> this directly to the jsftemplating repository or release as
>>>>>>>>>> separate jar file. I am out of the office until July11 so
>>>>>>>>>> might not be able to respond any questions that you send
>>>>>>>>>> later. If there is anything else you want to know, please let
>>>>>>>>>> me know now.
>>>>>>>>>>
>>>>>>>>>> thanks
>>>>>>>>>> Karam
>>>>>>>>>>
>>>>>>>>>> Ken Paulsen wrote:
>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> Hi Karam,
>>>>>>>>>>>
>>>>>>>>>>> Supporting the attributes you need on the column could look
>>>>>>>>>>> something like this:
>>>>>>>>>>>
>>>>>>>>>>> <sun:table ...>
>>>>>>>>>>> <sun:dynamicColumnTableRowGroup data="#{dataOnly}"
>>>>>>>>>>> columnId="#{listOfIds}"
>>>>>>>>>>> columnHeaderText="#{listOfHeaderText}"
>>>>>>>>>>> columnFooterText="#{listOfFooterText}"
>>>>>>>>>>> columnRowHeader="#{listOf...}"
>>>>>>>>>>> columnSort="#{listOf...}"
>>>>>>>>>>> columnAlign="#{listOf...}"
>>>>>>>>>>> columnWidth="#{listOf...}"
>>>>>>>>>>> columnSpacerColumn="#{listOf...}"
>>>>>>>>>>> [TableRowGroup properties here]
>>>>>>>>>>> />
>>>>>>>>>>> </sun:table>
>>>>>>>>>>>
>>>>>>>>>>> It is necessary to pass in a List of values because each
>>>>>>>>>>> column needs a value for each of these properties.
>>>>>>>>>>>
>>>>>>>>>>> There are other ways (including passing in a data structure
>>>>>>>>>>> that contains all the info in one EL expression), I'd like
>>>>>>>>>>> to know what you'd prefer. I'd also probably want to support
>>>>>>>>>>> all the other TRG properties to make it generally useful.
>>>>>>>>>>>
>>>>>>>>>>> Ken
>>>>>>>>>>>
>>>>>>>>>>> Karam Singh Badesha wrote:
>>>>>>>>>>>
>>>>>>>>>>>> Ken,
>>>>>>>>>>>> Actually TableRowGroup is ok to stay on the jsf page, all I
>>>>>>>>>>>> need is a way to pass the various columns (tableColumn) to
>>>>>>>>>>>> the page. Currently on tableColumn I only use following
>>>>>>>>>>>> properties:
>>>>>>>>>>>> id headerText
>>>>>>>>>>>> footerText
>>>>>>>>>>>> rowHeader
>>>>>>>>>>>> sort
>>>>>>>>>>>> align
>>>>>>>>>>>> width
>>>>>>>>>>>> spacerColumn
>>>>>>>>>>>>
>>>>>>>>>>>> In the following example:
>>>>>>>>>>>> <sun:table ...>
>>>>>>>>>>>> <sun:dynamicColumnTableRowGroup data="#{dataOnly}"
>>>>>>>>>>>> columnVisible="#{listOfVisibleValuesOneForEachColumn}"
>>>>>>>>>>>> columnSortIcon="#{listOfSortIconValuesOneForEachColumn}"
>>>>>>>>>>>> ...
>>>>>>>>>>>> [TableRowGroup properties here] />
>>>>>>>>>>>> </sun:table>
>>>>>>>>>>>>
>>>>>>>>>>>> What does columnVisible and columnSortIcon do? In this
>>>>>>>>>>>> approach where do I specify the columnHeaders? If this
>>>>>>>>>>>> approach is straight forward and I can get the column
>>>>>>>>>>>> headers etc from a resource file, its fine with me.
>>>>>>>>>>>>
>>>>>>>>>>>> thanks
>>>>>>>>>>>> Karam
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>> Ken Paulsen wrote:
>>>>>>>>>>>>
>>>>>>>>>>>>>
>>>>>>>>>>>>> Hi Karam,
>>>>>>>>>>>>>
>>>>>>>>>>>>> We need to work out what tableData's data structure looks
>>>>>>>>>>>>> like. The table component could have all it's properties
>>>>>>>>>>>>> as as it normally does (no need to worry about them).
>>>>>>>>>>>>> However, you're hiding the tableRowGroup and tableColumn
>>>>>>>>>>>>> components... so they'll need to be created from the data.
>>>>>>>>>>>>>
>>>>>>>>>>>>> TableRowGroup supports the following properties:
>>>>>>>>>>>>>
>>>>>>>>>>>>> tableDataSorter
>>>>>>>>>>>>> onDblClick
>>>>>>>>>>>>> onKeyPress
>>>>>>>>>>>>> sourceData
>>>>>>>>>>>>> aboveColumnFooter
>>>>>>>>>>>>> extraFooterHtml
>>>>>>>>>>>>> onKeyUp
>>>>>>>>>>>>> onMouseUp
>>>>>>>>>>>>> extraHeaderHtml
>>>>>>>>>>>>> footerText
>>>>>>>>>>>>> align
>>>>>>>>>>>>> selectMultipleToggleButton
>>>>>>>>>>>>> onClick
>>>>>>>>>>>>> groupToggleButton
>>>>>>>>>>>>> toolTip
>>>>>>>>>>>>> onMouseDown
>>>>>>>>>>>>> tableDataFilter
>>>>>>>>>>>>> multipleColumnFooters
>>>>>>>>>>>>> rows
>>>>>>>>>>>>> sourceVar
>>>>>>>>>>>>> valign
>>>>>>>>>>>>> first
>>>>>>>>>>>>> onMouseOut
>>>>>>>>>>>>> multipleTableColumnFooters
>>>>>>>>>>>>> onMouseOver
>>>>>>>>>>>>> onMouseMove
>>>>>>>>>>>>> emptyDataMsg
>>>>>>>>>>>>> selected
>>>>>>>>>>>>> collapsed
>>>>>>>>>>>>> visible
>>>>>>>>>>>>> aboveColumnHeader
>>>>>>>>>>>>> onKeyDown
>>>>>>>>>>>>> headerText
>>>>>>>>>>>>> styleClasses
>>>>>>>>>>>>> aboveColumnHeader
>>>>>>>>>>>>> onKeyDown
>>>>>>>>>>>>> headerText
>>>>>>>>>>>>> styleClasses
>>>>>>>>>>>>>
>>>>>>>>>>>>> TableRowGroup also supports these facets:
>>>>>>>>>>>>>
>>>>>>>>>>>>> header
>>>>>>>>>>>>> footer
>>>>>>>>>>>>>
>>>>>>>>>>>>> TableColumn supports these properties:
>>>>>>>>>>>>>
>>>>>>>>>>>>> spacerColumn
>>>>>>>>>>>>> width
>>>>>>>>>>>>> onDblClick
>>>>>>>>>>>>> sort
>>>>>>>>>>>>> selectedId
>>>>>>>>>>>>> onKeyPress
>>>>>>>>>>>>> severity
>>>>>>>>>>>>> rendered
>>>>>>>>>>>>> rowHeader
>>>>>>>>>>>>> extraTableFooterHtml
>>>>>>>>>>>>> extraFooterHtml
>>>>>>>>>>>>> onKeyUp
>>>>>>>>>>>>> onMouseUp
>>>>>>>>>>>>> styleClass
>>>>>>>>>>>>> descending
>>>>>>>>>>>>> embeddedActions
>>>>>>>>>>>>> height
>>>>>>>>>>>>> extraHeaderHtml
>>>>>>>>>>>>> align
>>>>>>>>>>>>> footerText
>>>>>>>>>>>>> scope
>>>>>>>>>>>>> style
>>>>>>>>>>>>> sortImageURL
>>>>>>>>>>>>> onClick
>>>>>>>>>>>>> sortIcon
>>>>>>>>>>>>> toolTip
>>>>>>>>>>>>> onMouseDown
>>>>>>>>>>>>> alignKey
>>>>>>>>>>>>> tableFooterText
>>>>>>>>>>>>> valign
>>>>>>>>>>>>> noWrap
>>>>>>>>>>>>> onMouseOut
>>>>>>>>>>>>> onMouseOver
>>>>>>>>>>>>> emptyCell
>>>>>>>>>>>>> visible
>>>>>>>>>>>>> onMouseOut
>>>>>>>>>>>>> onMouseOver
>>>>>>>>>>>>> onMouseMove
>>>>>>>>>>>>> emptyCell
>>>>>>>>>>>>> visible
>>>>>>>>>>>>> onKeyDown
>>>>>>>>>>>>> headerText
>>>>>>>>>>>>>
>>>>>>>>>>>>> TableColumn defines these facets:
>>>>>>>>>>>>>
>>>>>>>>>>>>> footer
>>>>>>>>>>>>> header
>>>>>>>>>>>>> tableFooter
>>>>>>>>>>>>>
>>>>>>>>>>>>> So as you can see, the data structure is non-trivial.
>>>>>>>>>>>>> However, it may not be as bad as it seems either. If we
>>>>>>>>>>>>> can agree to not try to generate TableRowGroup, we can
>>>>>>>>>>>>> leave its definition in the .jsf file. I don't think it
>>>>>>>>>>>>> adds a lot of value to try to eliminate it. As for all the
>>>>>>>>>>>>> properties on TableColumn... we could decide to support
>>>>>>>>>>>>> only a subset. And/or we could create a naming pattern to
>>>>>>>>>>>>> cause the factory to apply the values correctly -- this is
>>>>>>>>>>>>> made more difficult, however, b/c there are multiple
>>>>>>>>>>>>> TableColumns and the values may vary between the
>>>>>>>>>>>>> TableColumns.
>>>>>>>>>>>>>
>>>>>>>>>>>>> So we need to know what properties will be supported
>>>>>>>>>>>>> directly by your proposed "data" property (if any), and
>>>>>>>>>>>>> which will require additional properties in the jsf file
>>>>>>>>>>>>> delegate. For example:
>>>>>>>>>>>>>
>>>>>>>>>>>>> <sun:table ...>
>>>>>>>>>>>>> <sun:dynamicColumnTableRowGroup
>>>>>>>>>>>>> data="#{dataPlusPropertiesForAllTableColumns}"
>>>>>>>>>>>>> [tableRowGroup properties here] />
>>>>>>>>>>>>> </sun:table>
>>>>>>>>>>>>>
>>>>>>>>>>>>> OR:
>>>>>>>>>>>>>
>>>>>>>>>>>>> <sun:table ...>
>>>>>>>>>>>>> <sun:dynamicColumnTableRowGroup data="#{dataOnly}"
>>>>>>>>>>>>> columnVisible="#{listOfVisibleValuesOneForEachColumn}"
>>>>>>>>>>>>> columnSortIcon="#{listOfSortIconValuesOneForEachColumn}"
>>>>>>>>>>>>> ...
>>>>>>>>>>>>> [TableRowGroup properties here] />
>>>>>>>>>>>>> </sun:table>
>>>>>>>>>>>>>
>>>>>>>>>>>>> As you can see, the first approach requires a complex data
>>>>>>>>>>>>> structure that you must populate. The 2nd approach
>>>>>>>>>>>>> requires you to create the same order of complexity,
>>>>>>>>>>>>> however, it is distributed among multiple List objects
>>>>>>>>>>>>> which contain the properties to set for each column.
>>>>>>>>>>>>>
>>>>>>>>>>>>> What do you think?
>>>>>>>>>>>>>
>>>>>>>>>>>>> A 1-off solution wouldn't have to be so generic and could
>>>>>>>>>>>>> be more specific to your data and needs. You could use
>>>>>>>>>>>>> either the "binding" attribute, or a custom factory (like
>>>>>>>>>>>>> above), but it would allow to only do the work you need
>>>>>>>>>>>>> for your use case.
>>>>>>>>>>>>>
>>>>>>>>>>>>> Ken
>>>>>>>>>>>>>
>>>>>>>>>>>>> Karam Singh Badesha wrote:
>>>>>>>>>>>>>
>>>>>>>>>>>>>> Here is example of how it might look like in .jsf file:
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> <sun:table data="#{pageSession.tableData}"
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> .../>
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> tableData will have all the column tag information and in
>>>>>>>>>>>>>> the .jsf page there will be no column tags. Please
>>>>>>>>>>>>>> suggest a way to take care of this. It is not really my
>>>>>>>>>>>>>> app specific, it can be used by anyone.
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> thanks
>>>>>>>>>>>>>> Karam
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> Karam Singh Badesha wrote:
>>>>>>>>>>>>>>
>>>>>>>>>>>>>>> Ken,
>>>>>>>>>>>>>>> Here is an example of what I am trying to do:
>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>> Right now in the .jsf page I have to list the column tag
>>>>>>>>>>>>>>> with header etc. I have the situation where I have drop
>>>>>>>>>>>>>>> down boxes and depending upon different selections,
>>>>>>>>>>>>>>> number of columns and column headers could change. And I
>>>>>>>>>>>>>>> want the control to be defined in the Resources file,
>>>>>>>>>>>>>>> etc number of columns, column headers etc. I am not sure
>>>>>>>>>>>>>>> how it will work myself, as the jsf code is changing
>>>>>>>>>>>>>>> (when number of columns change). I think when we talked
>>>>>>>>>>>>>>> last time, you suggested that I somehow create the table
>>>>>>>>>>>>>>> object in java code (handler) and pass it to the page.
>>>>>>>>>>>>>>> What do you suggest? Let me know if this is clear or not.
>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>> thanks
>>>>>>>>>>>>>>> Karam
>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>> Ken Paulsen wrote:
>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>> Hi Karam,
>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>> I can look into doing this... however, after reading
>>>>>>>>>>>>>>>> the issue more closely, I need some more information
>>>>>>>>>>>>>>>> from you. How do you want to specify the table columns
>>>>>>>>>>>>>>>> from the page?
>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>> TableColumns typically have children, so they'd also
>>>>>>>>>>>>>>>> have to be created. Do you want those to just be
>>>>>>>>>>>>>>>> staticText? Or do you want control over what type they
>>>>>>>>>>>>>>>> are also? Which TableColumn attribute do you want
>>>>>>>>>>>>>>>> control over? Perhaps you can provide an example of
>>>>>>>>>>>>>>>> what you'd like it to look like in the .jsf file?
>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>> After looking at this more closely, I suspect this may
>>>>>>>>>>>>>>>> end up being custom for your needs. However, if I can
>>>>>>>>>>>>>>>> keep it generic and useful for others as well, I will.
>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>> Ken
>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>> Karam Singh Badesha wrote:
>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>> Hi Ken,
>>>>>>>>>>>>>>>>> Is it possible to get a solution for issue #10 in
>>>>>>>>>>>>>>>>> jsftemplating? I really need some solution for this so
>>>>>>>>>>>>>>>>> that create dynamic tables. Please let me know.
>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>> thanks
>>>>>>>>>>>>>>>>> Karam
>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>
>>>>>

$attribute{row1}); mapPut(map="$attribute{row1}" key="a" value="Row1 Col A"); mapPut(map="$attribute{row1}" key="b" value="Row1 Col B"); mapPut(map="$attribute{row1}" key="c" value="Row1 Col C"); // Row 2 createMap(result=>$attribute{row2}); mapPut(map="$attribute{row2}" key="a" value="Row2 Col A"); mapPut(map="$attribute{row2}" key="b" value="Row2 Col B"); mapPut(map="$attribute{row2}" key="c" value="Row2 Col C"); // Row 3 createMap(result=>$attribute{row3}); mapPut(map="$attribute{row3}" key="a" value="Row3 Col A"); mapPut(map="$attribute{row3}" key="b" value="Row3 Col B"); mapPut(map="$attribute{row3}" key="c" value="Row3 Col C"); // Create List of Map (List of the rows) setAttribute(key='listOfRows' value={"$attribute{row1}" "${row2}" "${row3}"} ); // Row 1 (again, different obj.) createMap(result=>$attribute{rowA}); mapPut(map="$attribute{rowA}" key="foo" value="Other Obj: A - foo"); mapPut(map="$attribute{rowA}" key="bar" value="Other Obj: A - bar"); // Row 2 (again, different obj.) createMap(result=>$attribute{rowB}); mapPut(map="$attribute{rowB}" key="foo" value="Other Obj: B - foo"); mapPut(map="$attribute{rowB}" key="bar" value="Other Obj: B - bar"); // Row 3 (again, different obj.) createMap(result=>$attribute{rowC}); mapPut(map="$attribute{rowC}" key="foo" value="Other Obj: C - foo"); mapPut(map="$attribute{rowC}" key="bar" value="Other Obj: C - bar"); // Create List of Map (List of more rows) setAttribute(key='moreRows' value={"$attribute{rowA}" "${rowB}" "${rowC}"} ); />