ICEfaces-EE
  1. ICEfaces-EE
  2. IPCK-147

Nested Composite Component Columns Unrendered By Parent DataTable

    Details

    • Type: Bug Bug
    • Status: Closed
    • Priority: Major Major
    • Resolution: Fixed
    • Affects Version/s: None
    • Fix Version/s: EE-3.0.0.GA
    • Component/s: Facelet Components
    • Labels:
      None
    • Environment:
      JSF 2.x / IF 2.x
    • Workaround Exists:
      Yes
    • Workaround Description:
      Hide
      The only "work-around" I've seen online thus far is avoiding the issue by writing tables with h:column exposed:
      <h:dataTable>
        <h:column>#{data.one}</h:column>
        <h:column><cc:superColumn>#{data.two}</cc:superColumn></h:column>
      </h:dataTable>
      Show
      The only "work-around" I've seen online thus far is avoiding the issue by writing tables with h:column exposed: <h:dataTable>   <h:column>#{data.one}</h:column>   <h:column><cc:superColumn>#{data.two}</cc:superColumn></h:column> </h:dataTable>

      Description

      Columns in the EE components have their h:column tags wrapped within their composite components, occurring in tables like so:
      <h:dataTable value="#{someBean.someData}" var="data">
        <h:column>#{data.one}</h:column>
        <cc:superColumn>#{data.two}</cc:superColumn>
      </h:dataTable>
      Where it is expected that composite-component abstracted tags are visible to the parents.

      However, only the normal h:column displaying the #{data.one} binding will be rendered.
      1. Screen shot 2010-12-07 at 1.46.04 PM.png
        76 kB

        Issue Links

          Activity

          Hide
          Nils Lundquist added a comment -

          The attached example should render the numbers 0-29 in 3 columns and 10 rows, but one of the columns is defined by a composite component and isn't rendered.

          Show
          Nils Lundquist added a comment - The attached example should render the numbers 0-29 in 3 columns and 10 rows, but one of the columns is defined by a composite component and isn't rendered.
          Hide
          Nils Lundquist added a comment -

          Another version of my test case, noticed a typo in my xmlns for the composite comps, that would cause this test to fail even if the nested column problem didn't exist.

          Fixed the typo, nesting issue persists as expected.

          Show
          Nils Lundquist added a comment - Another version of my test case, noticed a typo in my xmlns for the composite comps, that would cause this test to fail even if the nested column problem didn't exist. Fixed the typo, nesting issue persists as expected.
          Hide
          Ted Goddard added a comment -

          Screenshot shows ui:debug output.

          Show
          Ted Goddard added a comment - Screenshot shows ui:debug output.
          Hide
          Ted Goddard added a comment -

          The composite component is a child of a UINamingContainer (likely part of the composite component implementation technique). Usually this would not be a problem, but h:dataTable is looking for immediate UIColumn children, not UIColumn ancestors, and it does not discover the columns. It would be possible to implement ice:dataTable to search for nested columns. Another option would be to implement this particular component using the Java API rather than Facelet composition.

          Show
          Ted Goddard added a comment - The composite component is a child of a UINamingContainer (likely part of the composite component implementation technique). Usually this would not be a problem, but h:dataTable is looking for immediate UIColumn children, not UIColumn ancestors, and it does not discover the columns. It would be possible to implement ice:dataTable to search for nested columns. Another option would be to implement this particular component using the Java API rather than Facelet composition.
          Hide
          Ted Goddard added a comment -

          Removing ICEfaces from the test case does not remove the undesired behavior – this is not an ICEfaces bug.

          Show
          Ted Goddard added a comment - Removing ICEfaces from the test case does not remove the undesired behavior – this is not an ICEfaces bug.
          Hide
          Ted Goddard added a comment -

          Assigning back to Nils – the only short term solution will be to use the h:column inline or use a different technique to implement the component (either Java implementation or a Facelet technique yet to be discovered).

          Show
          Ted Goddard added a comment - Assigning back to Nils – the only short term solution will be to use the h:column inline or use a different technique to implement the component (either Java implementation or a Facelet technique yet to be discovered).
          Hide
          Nils Lundquist added a comment -

          I'd read that there is an attribute "componentType="some.java.Class"" of composite:interface that can be used to define the type of the Facelet composed component, but I could never find an example of its use.

          If this exists wouldn't it be possible keep our current Facelet composite columns and change its componentType to a subclass of HtmlColumn?

          Show
          Nils Lundquist added a comment - I'd read that there is an attribute "componentType="some.java.Class"" of composite:interface that can be used to define the type of the Facelet composed component, but I could never find an example of its use. If this exists wouldn't it be possible keep our current Facelet composite columns and change its componentType to a subclass of HtmlColumn?
          Hide
          Nils Lundquist added a comment -

          Also on a similar topic was:
          http://weblogs.java.net/blog/cayhorstmann/archive/2010/01/30/composite-input-components-jsf

          Which may be useful as it demos implementing composite components using UIInput subclasses rather than UINamingContainer, could the same could be done with a UIColumn subclass?

          Show
          Nils Lundquist added a comment - Also on a similar topic was: http://weblogs.java.net/blog/cayhorstmann/archive/2010/01/30/composite-input-components-jsf Which may be useful as it demos implementing composite components using UIInput subclasses rather than UINamingContainer, could the same could be done with a UIColumn subclass?
          Hide
          Ted Goddard added a comment - - edited

          That looks like an excellent technique. Please try it out.

          Another approach would be to implement a TagHandler, but that will be more complex – the componentType attribute should allow the Renderer to remain a facelet while the backing component is the desired class. A custom TagHandler would require implementation of all three parts (tag, Component, and Renderer).

          Show
          Ted Goddard added a comment - - edited That looks like an excellent technique. Please try it out. Another approach would be to implement a TagHandler, but that will be more complex – the componentType attribute should allow the Renderer to remain a facelet while the backing component is the desired class. A custom TagHandler would require implementation of all three parts (tag, Component, and Renderer).
          Hide
          Nils Lundquist added a comment -

          After using a backing component to identify our composite component as UIColumn to the DataTable, our composite component appears to behave just a a regular h:column would.

          However for composite components to be worthwhile, we need to make use of the cc:insertChildren tag; the composite component tag responsible for the copying of using-page tag-children into the CC. This is performed by the RelocateChildrenListener (a RelocateListener subclass) listening for the PostAddToViewEvent.

          Unfortunately, UIColumn already performs a relocation like this by default, duplicating its contents repeatedly into the respective column of each row. This is performed by com.sun.faces.renderkit.html_basic.BaseTableRenderer during component encoding, which appears to occur after PostAddToViewEvent.

          These two events clash and cause the unpredictable encoding of column and CC contents. With cc:insertChildren removed, the default Column behaviour works. With it present, sometimes the default Column behaviour will display on a re-render (ex. after pressing a button), but normally nothing appear in the column cells.

          The children of the using page appear to be being blanked by the cc:insertChildren event, and when the Column encoding gets to them, there is nothing to render. This is judging from the firing order of the events and the many additional calls to getChildrenCount() (of my backing component) that all return 0, which aren't present when cc:insertChildren is absent.

          Show
          Nils Lundquist added a comment - After using a backing component to identify our composite component as UIColumn to the DataTable, our composite component appears to behave just a a regular h:column would. However for composite components to be worthwhile, we need to make use of the cc:insertChildren tag; the composite component tag responsible for the copying of using-page tag-children into the CC. This is performed by the RelocateChildrenListener (a RelocateListener subclass) listening for the PostAddToViewEvent. Unfortunately, UIColumn already performs a relocation like this by default, duplicating its contents repeatedly into the respective column of each row. This is performed by com.sun.faces.renderkit.html_basic.BaseTableRenderer during component encoding, which appears to occur after PostAddToViewEvent. These two events clash and cause the unpredictable encoding of column and CC contents. With cc:insertChildren removed, the default Column behaviour works. With it present, sometimes the default Column behaviour will display on a re-render (ex. after pressing a button), but normally nothing appear in the column cells. The children of the using page appear to be being blanked by the cc:insertChildren event, and when the Column encoding gets to them, there is nothing to render. This is judging from the firing order of the events and the many additional calls to getChildrenCount() (of my backing component) that all return 0, which aren't present when cc:insertChildren is absent.
          Hide
          Nils Lundquist added a comment -

          Failing that a solution can be found to the column issues, a workaround could be using two tag-libs in the ice-cc jar, one using the new composite component interface sans tables, and one using the older style table components.

          Show
          Nils Lundquist added a comment - Failing that a solution can be found to the column issues, a workaround could be using two tag-libs in the ice-cc jar, one using the new composite component interface sans tables, and one using the older style table components.
          Hide
          Patrick Corless added a comment -

          Moving to beta 2, doesn't effect the compat version.

          Show
          Patrick Corless added a comment - Moving to beta 2, doesn't effect the compat version.
          Hide
          Philip Breau added a comment -

          working as expected now with JSF 2.1

          Show
          Philip Breau added a comment - working as expected now with JSF 2.1

            People

            • Assignee:
              Patrick Corless
              Reporter:
              Nils Lundquist
            • Votes:
              0 Vote for this issue
              Watchers:
              0 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved: