ICEfaces
  1. ICEfaces
  2. ICE-11391

ace:list doesn't reflect modifications in the model made in the Invoke Application phase

    Details

    • Type: Bug Bug
    • Status: Closed
    • Priority: Major Major
    • Resolution: Fixed
    • Affects Version/s: 4.2
    • Fix Version/s: 4.3
    • Component/s: ACE-Components
    • Labels:
      None
    • Environment:
      Any

      Description

      ace:list components with ajax listeners fail to display modifications made to the underlying model during the Invoke Appliation phase. This is more clearly seen on migrate events. Other components bound to the same underlying model, such as ace:dataTable and ui:repeat do display the correct order.

        Activity

        Hide
        Arturo Zambrano added a comment -

        Attached test case, showing the issue. It needs to be put under the /samples folder in the ICEfaces project.

        Show
        Arturo Zambrano added a comment - Attached test case, showing the issue. It needs to be put under the /samples folder in the ICEfaces project.
        Hide
        Arturo Zambrano added a comment -

        It seems like the issue is related to having to reset or rebuild the model after the modifications are done in the Invoke Application phase.

        Show
        Arturo Zambrano added a comment - It seems like the issue is related to having to reset or rebuild the model after the modifications are done in the Invoke Application phase.
        Hide
        Arturo Zambrano added a comment -

        The issue is actually related to incorrect client IDs. The underlying model is correct throughout the lifecycle in the list. What's wrong are the client IDs of the <h:outputText>'s. All of them have the same index in the response, so only the first item gets updated in the client. A workaround is to simply avoid using the <h:panelGroup> inside the list (or ano other container component) and only have one level of components inside the list. This way the client IDs are calculated correctly.

        Show
        Arturo Zambrano added a comment - The issue is actually related to incorrect client IDs. The underlying model is correct throughout the lifecycle in the list. What's wrong are the client IDs of the <h:outputText>'s. All of them have the same index in the response, so only the first item gets updated in the client. A workaround is to simply avoid using the <h:panelGroup> inside the list (or ano other container component) and only have one level of components inside the list. This way the client IDs are calculated correctly.
        Hide
        Arturo Zambrano added a comment - - edited

        r52394: fix to recalculate the client IDs of all the nested children in the ace:list component, in order to assign IDs with the correct indexes

        Show
        Arturo Zambrano added a comment - - edited r52394: fix to recalculate the client IDs of all the nested children in the ace:list component, in order to assign IDs with the correct indexes
        Hide
        Arturo Zambrano added a comment - - edited

        As mentioned before, the underlying model was always correct, reflecting the changes made programmatically. What was wrong was that the index in all client IDs of the nested components was always 0. So, whenever there was a dynamic update, only the first element with this ID got updated (multiple times). Now, with all inner components having distinct client IDs, the dynamic updates are performed normally.

        This solves the issue in the attached test app when modifying the model programmatically in a reordering (move) event request. However, after working on this issue, it was noticed that there hasn't never been support for programmatically modifying the model in a migrate event request. What happens right now in the test app in a migrate operation is that the model is modified programmatically, and it is updated correctly in the client, but the item that was migrated from the source list to the desitination list stays there in the destination list, even if the model was modified not to have that item. This is so, because in a dynamic update, the list items are updated individually, and not the whole list.

        Since the beginning of this component, it was designed to have a significant amount of logic in the client, for efficiency purposes. So, in a migrate request, the markup of the migrated item in the client stays in the destination list, without having to update the markup from the server, because in the vast majority of use cases, a migrated item is meant to stay in the destination list and not be removed. If it's desired that a migrated item be removed programmatically in a migrate request, then the following workaround can be used:

        In order to remove all items from the source list in the destination list, add the following ajax tag in the destination list:

        <ace:ajax event="migrate" listener="#{bean.listener}" render="@all" onSuccess="ice.ace.jq(ice.ace.escapeClientId('<this list client ID>')).find('> ul > li').filter(function(){return this.id.indexOf('<this list client ID>') != 0;}).remove();"/>
        

        This code (onSuccess) is executed after the response arrives to the client and before the markup is updated. What this code does is to remove all list items that don't start with the client ID of this list. If another result is desired, then it can be accomplished with some javascript code in the onSuccess attribute of the migrate ajax event.

        Another possible workaround is to force a full markup update of the component on a migrate request that programmatically modifies the model. This can be accomplished by rendering a different style class name in the list component in the same listener that programmatically modifies the model. This style class can just be a number, like the current server time in milliseconds, and, of course, it doesn't have to be a style class defined in the client. This is just treated as a string for the domdiff to send a full markup update of the component.

        Show
        Arturo Zambrano added a comment - - edited As mentioned before, the underlying model was always correct, reflecting the changes made programmatically. What was wrong was that the index in all client IDs of the nested components was always 0. So, whenever there was a dynamic update, only the first element with this ID got updated (multiple times). Now, with all inner components having distinct client IDs, the dynamic updates are performed normally. This solves the issue in the attached test app when modifying the model programmatically in a reordering (move) event request. However, after working on this issue, it was noticed that there hasn't never been support for programmatically modifying the model in a migrate event request. What happens right now in the test app in a migrate operation is that the model is modified programmatically, and it is updated correctly in the client, but the item that was migrated from the source list to the desitination list stays there in the destination list, even if the model was modified not to have that item. This is so, because in a dynamic update, the list items are updated individually, and not the whole list. Since the beginning of this component, it was designed to have a significant amount of logic in the client, for efficiency purposes. So, in a migrate request, the markup of the migrated item in the client stays in the destination list, without having to update the markup from the server, because in the vast majority of use cases, a migrated item is meant to stay in the destination list and not be removed. If it's desired that a migrated item be removed programmatically in a migrate request, then the following workaround can be used: In order to remove all items from the source list in the destination list, add the following ajax tag in the destination list: <ace:ajax event="migrate" listener="#{bean.listener}" render="@all" onSuccess="ice.ace.jq(ice.ace.escapeClientId('< this list client ID>')).find('> ul > li').filter( function (){ return this .id.indexOf('< this list client ID>') != 0;}).remove();"/> This code (onSuccess) is executed after the response arrives to the client and before the markup is updated. What this code does is to remove all list items that don't start with the client ID of this list. If another result is desired, then it can be accomplished with some javascript code in the onSuccess attribute of the migrate ajax event. Another possible workaround is to force a full markup update of the component on a migrate request that programmatically modifies the model. This can be accomplished by rendering a different style class name in the list component in the same listener that programmatically modifies the model. This style class can just be a number, like the current server time in milliseconds, and, of course, it doesn't have to be a style class defined in the client. This is just treated as a string for the domdiff to send a full markup update of the component.

          People

          • Assignee:
            Arturo Zambrano
            Reporter:
            Arturo Zambrano
          • Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved: