Details

    • Type: Bug Bug
    • Status: Open
    • Priority: Minor Minor
    • Resolution: Unresolved
    • Affects Version/s: 2.0
    • Fix Version/s: None
    • Component/s: Ajax/JavaScript
    • Labels:
      None
    • Environment:

      Operating System: All
      Platform: All

    • Issuezilla Id:
      865
    • Status Whiteboard:
      Hide

      size_medium importance_large draft

      Show
      size_medium importance_large draft

      Description

      Comments from [jsr-314-open] Ajax inside a DataTable:

      Cagatay Civici

      I've faced with an issue in our app I'd like to share when trying to update the
      datatable itself from a command element located inside a column. Case is to
      select a row, execute logic and update the datatable. Basic code:

      <h:dataTable id="cars" var="car" value="#

      {tableBean.carsSmall}

      ">
      <h:column>
      <f:facet name="header">
      Model
      </f:facet>
      <h:outputText value="#

      {car.model}

      " />
      </h:column>

      <h:column>
      <f:facet name="header">
      Action
      </f:facet>
      <h:commandButton value="Some Action"
      actionListener="#

      {tableBean.handleRowAction(car)}

      ">
      <f:ajax render="cars" />
      </h:commandButton>
      </h:column>
      </h:dataTable>

      As datatable has a rowIndex >= 0 during rendering of commandButton f:ajax
      defines the component id to render as cars:

      {rowIndex}

      where I should expect
      "cars" only. This is due to UIData.getClientId implementation as UIData
      adds rowIndex for unique row ids. This causes an issue with a nested f:ajax case.

      Andy Schwartz

      Ids specified by <f:ajax> are relative to containing component - in this case,
      relative to the <h:commandButton>. This makes is easy to specify
      execute/render ids for components within the same NamingContainer (which is by
      far the most common case). In the case of iterating components like
      <h:dataTable> or <ui:repeat>, this means that execute/render ids refer to
      components within the same row.

      There is a way out of this... You can specify an absolute id by prefixing the id
      with ":". At that point the id starts from the root of the component tree and
      you can specify any number of colon-separated segments to descend into each
      naming container. (This matches the syntax used by findComponent().)

      Of course, specifying absolute paths is at a minimum difficult, and in some
      cases, just plain impossible to do (eg. when reusing content across multiple
      pages). In Trinidad we use a double-colon prefix ("::") to reference up one
      level in the NamingContainer hierarchy - similar to ".." in file system paths.
      I suggested exposing this when we were working on the <f:ajax> spec, but this
      topic got shelved until 2.1.

      Dan has captured some of our thinking here:

      http://seamframework.org/Documentation/JSF21#H-ReevaluateComponentReferencingMechanismP2

      More here:

      http://seamframework.org/Documentation/JSFEnhancementComponentReferencing

      Oh, and... for the particular use case that you describe above, I think that it
      is very important that the JSF implementations give some warning when a
      referenced component is not found, at least when running in development project
      stage. Not sure which implementation you are testing, but it might make sense
      to log bugs against MyFaces/Mojarra if this is failing silently in development mode.

      Martin Marinschek

      > Ids specified by <f:ajax> are relative to containing component - in this
      > case, relative to the <h:commandButton>. This makes is easy to specify
      > execute/render ids for components within the same NamingContainer (which is
      > by far the most common case). In the case of iterating components like
      > <h:dataTable> or <ui:repeat>, this means that execute/render ids refer to
      > components within the same row.

      Yes, but what Cagatay totally correctly refers to is that the table is
      certainly not in a row - how can the table be in a row of itself? This
      is semantical nonsense.

      We should never include the row-index in the client-id of the table
      itself. For this, we need to revise the client-id generation
      algorithm.

      Without actually having tried it, I think that it is easy to do so, as
      we have a UIComponentBase.getContainerClientId() to create the
      client-id of the children - when this method is called, we append the
      row-index, if getClientId() itself is called, we don´t. Does this
      sound reasonable to you guys?

      I think we can regard this as an implementation bug - Catagay, can you
      open issues for Mojarra and MyFaces?

      Leonardo Uribe

      I just want to note a side effect of this change: getContainerClientId() was
      introduced
      in jsf 1.2, but code written in jsf 1.1 uses getClientId(). If we apply this change,
      all libraries for jsf 1.2 needs to be updated. I think we can do this for jsf
      2.0 but my
      question is if we should apply this change on jsf 1.2 branch. Components written for
      jsf 1.1 that extends from UIData will not work correctly with this change.

      Martin Marinscheck

      > Components
      > written for
      > jsf 1.1 that extends from UIData will not work correctly with this change.

      ah, well - if they override the UIData functionality. Yes, you are
      right. Well, not sure how we should handle this properly. Maybe we
      should leave this for 2.0.

      Andy Schwartz

      Yes, but what Cagatay totally correctly refers to is that the table is
      certainly not in a row - how can the table be in a row of itself? This
      is semantical nonsense.

      Ugh, yes, of course. For a moment there it slipped my mind that the UIData
      component is indeed found as part of the relative id search. I was thinking
      that only the stamped components would be considered valid execute/render
      targets when a row index is set. But, since we spec'ed findComponent()
      semantics for execute/render, the UIData would indeed be found, and, yes, we
      should use the correct client id.

      Leonardo Uribe

      Added issue on myfaces:

      MYFACES-2744 UIData.getClientId() should not append rowIndex, instead use
      UIData.getContainerClientId()

        Activity

        Hide
        rogerk added a comment -

        triaged

        Show
        rogerk added a comment - triaged
        Hide
        rogerk added a comment -

        triage

        Show
        rogerk added a comment - triage
        Hide
        cipriandobra added a comment -

        A simple workaround is to place the dataTable inside a h:panelGroup and use its id.

        Show
        cipriandobra added a comment - A simple workaround is to place the dataTable inside a h:panelGroup and use its id.
        Hide
        Ed Burns added a comment -

        Set priority to baseline ahead of JSF 2.3 triage. Priorities will be assigned accurately after this exercise.

        Show
        Ed Burns added a comment - Set priority to baseline ahead of JSF 2.3 triage. Priorities will be assigned accurately after this exercise.
        Hide
        Manfred Riem added a comment -

        Setting priority to Minor

        Show
        Manfred Riem added a comment - Setting priority to Minor

          People

          • Assignee:
            Unassigned
            Reporter:
            lu4242
          • Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

            Dates

            • Created:
              Updated: