dev@jsftemplating.java.net

Re: JSFTemplating: Enhancement #10: Dynamic table

From: Ken Paulsen <Ken.Paulsen_at_Sun.COM>
Date: Fri, 10 Aug 2007 13:20:41 -0700

I forgot the attachment... here it is.

ken

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}"} ); />