This is a complete analysis of all the possible options to solve this JIRA.
There are two distinct issues in this JIRA that can be summarized as follows:
1. When collapsible=true, the paneChangeListener is not fired when collapsing the active pane, but the ace:ajax event is.
2. When dynamic=true, ace:ajax events aren't fired when changing panes, but the paneChangeListener is.
For the first issue, it is a matter of deciding how we want the component to behave. There are three options:
1. Do not fire the ace:ajax event, when collapsible=true and all panes are collapsed.
2. Do fire the paneChangeListener, but set the pane argument to null when all panes are collapsed and document this behaviour.
3. Define a separate event to fire when all panes are collapsed and create a new ace:ajax event and a new listener attribute for this event.
The second issue is more complex and cannot be easily fixed. The reason is that the dynamic pane-loading request and the ajax request are fundamentally different, and their operations cannot be combined in a single request. When using dynamic loading, a request is sent to the server with the 'ice.customUpdate' parameter and a callback is passed to be executed when the response arrives. In the server side, the component simply renders the content of the pane to be loaded – instead of its original markup. Since this is a custom update, back in the client, the callback that was passed takes the response body and puts it as the content of the active pane. Therefore, an ace:ajax event that tries to be processed in the same request would cause problems, especially if rendering @all, @form, @this, or any children of the accordion component, because it would be necessary to render the accordion component normally in order to correctly determine what needs to be updated in the client, and as mentioned before, the normal rendering of the component is manipulated when using the dynamic loading functionality.
These are our options:
1. Make two separate requests, instead of just one: one to load the pane dynamically and another for the ajax event.
2. Remove the dynamic loading functionality altogether and let the app developer control when the panes are loaded/rendered, by using 'rendered' attributes for each of the panes and using ace:ajax events to specify when to load/update the panes.
3. Keep the dynamic loading functionality and simply document that ace:ajax events cannot be fired when using dynamic loading.
4. Modify the dynamic loading functionality to work in a more "natural" way. Basically, it would consist of avoiding all this custom handling, and simply render the component normally without rendering the contents of all panes, but only the contents of the active pane. This might not have the exact same effect as the current dynamic loading functionality, as the whole component would be rendered this time (i.e. the component's skeleton markup and script, which would be executed again).
Here are some remarks about the feasibility of solving this issue.
When dynamic=true, a request to the server is made every time a pane is opened in order to load its content. To accomplish this, it is necessary to do an custom update (i.e. with the ice.customUpdate parameter) and pass an onSucess callback to the ajax request. Meanwhile, the ace ajax request is rendered as a function that must be called in the client as it is (with some optional parameters). For this reasons, it is not readily feasible to fire both the dynamic tab loading request and the ajax request. We could fire both events, but that would require two requests to be made. This would be easier if instead of rendering a function for ace ajax, we rendered instead a JSON object with all the data needed to make the ajax request. This object could be manipulated in the client side to satisfy different scenarios.
When collapsible=true, the paneChangeListener method binding is not invoked because the active index is now -1, and there's no value in the '_newTab' parameter, so a pane object can't be resolved and sent to the AccordionPaneChangeEvent event. This is more a matter of deciding whether we want to consider collapsing all panes as a pane change event or not. It would be easier to consider this a separate ajax event, let's say 'allPanesCollapsed'.