You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@myfaces.apache.org by Brökelmann, Mathias <MB...@PSI.DE> on 2005/03/23 11:50:37 UTC

Contribute a columns component to create crosstables

Hi,

I have developed a jsf component which allows to have n-columns in a datatable to make cross tables. That component is currently implemented using the myfaces components as a base which is working fine.

The component is working like this:

<x:dataTable value="#{data.rows}" var="row" >
  <!-- just a column -->
  <h:column>
    <f:facet name="header">
	<h:outputText value="fixed column" />
    </f:facet>
    <h:outputText value="#{row.attributeName}" />
  </h:column>
  <!-- new columns component renders a column for each element in data.columns -->
  <x:columns value="#{data.columns}" var="column">
    <f:facet name="header">
	<!-- row is not available! -->
	<h:outputText value="#{column.label}" />
    </f:facet>
    <!-- row is also available -->
    <h:outputText value="#{data.columnValue}" />
    <f:facet name="footer">
	<!-- row is not available! -->
	<h:outputText value="#{column.footer}" />
    </f:facet>
  </x:columns>
</x:dataTable>

The x:columns component is based on UIData. The parent datatable must have a fixed count of columns so it is not possible to use <x:columns value="#{row.columns}" var="column">.
To get the value for the column in the row a managed bean must be used which calls DataModel.getRowData() from the rows datamodel and the columns datamodel to determine the current row and column.

I would like to contribute this component to myfaces.

Now to the tricky part which is the reason why I've not contributed the component yet.

Currently the parent datatable component (which is doing the most work) contains a lot of code copied from the UIData class which handles the processing of the columns through private methods. The best place to integrate the new columns component would be the UIData class but that would generate dependencies to non standard components. I've also noticed that die myfaces HtmlDataTable uses a HtmlDataTableHack class which copies the code from UIData to make extended components work. I do not think that copying code is the best solution since the last change in UIData was not applied to HtmlDataTableHack. 

To prevent inconsistent code I suggest to introduce an abstract UIDataBase class in share which contains the implementation of UIData and make the private methods protected. UIData extends the UIDataBase with an empty implementation. Some of the renderers do that already. I don't think it violates the spec.

Mathias

Re: Contribute a columns component to create crosstables

Posted by Manfred Geiler <ma...@gmail.com>.
Mathias,
Thanks for your interest and proposed contribution.
Yes, HtmlDataTableHack is not nice. I'm not at all a friend of such
hacks but in this case there is no alternative. You cannot derive
UIData from a proprietary UIDataBase because:
1. The API documentation of the javax.faces.* classes is part of the
JSR-127 specification. Therefore the signature of our UIData must
exactly match the specified UIData.
2. UIDataBase would make dependencies even worse. HtmlDataTable would
be derived from UIData (it must be according to the spec) and would
use methods from UIDataBase. So, every component derived from
HtmlDataTable or our extended HtmlDataTable itself would depend on the
MyFaces javax.faces.* classes and would no longer be compatible to
other JSR-127 APIs!

Well, the reason for the HtmlDataTableHack is, that we otherwise would
not have (protected) access to the internal DataModel. But our
extended HtmlDataTable needs access to it to be able to save the state
of the DataModel and restore it.

The good news is: we are working on this issue in the JSR-252 expert
group (= JSF 1.2) and there will a simple solution for this.  ;-)

Regarding code redundancy: Yes, I hate it too. And even though I'm a
blooded java developer, sometimes an #include would be a nice thing. 
;-)
Hope there is no C guy listening...  :-)

-MG