The purpose of some components is to hide or show parts of the web page, which can include other components. Examples include tabs, collapsibles, and accordions. I’ll call these kinds of things hideables.
When a size managed component widget is inside a hideable widget and is initially hidden when it is initialized you can run into problems. (Think of a chart region inside a collapsible region that is initially collapsed.) This is because the size managed component has no idea what size it is. Depending on how robust the widget is it may throw an exception, or it may be sized in appropriately. A common situation is that it ends up with zero height and/or width so you can’t see it.
APEX has a very simple life cycle for its components (regions and items many of which are implemented with widgets). They are all initialized when the page loads and they are implicitly destroyed when the page unloads. This means for example that when an Interactive Grid was placed in a Tabs Container region it didn’t work and we had a bug.
Over time many bugs like this were entered and fixed. They were all very specific and of the form component X doesn’t work inside component Y. The fixes were likewise specific. By the time a specific bug for Interactive Grid was assigned to me there were hacks in the APEX tabs widget to handle charts, calendars and more. The trouble is that the problem is more general and adding another hack for Interactive Grid wasn’t a complete solution.
In general we have N kinds of size managed components (including ones created by our customers) that need to work inside M kinds of hideables (again they could be created by our customers). The hideables need to notify the size managed components when they become visible so that they can refresh/resize/reinitialize themselves. It is simply not possible to code every kind of hideable so that it knows specifically how to handle every kind of size managed component.
This leads to the new functionality added in 5.1.1. The solution is a new notification API you can find in
widget.util.js. It works like this: Size managed components call
apex.widget.util.onVisibilityChange when an instance is initialized passing in the widget element and a notification handler function. The notification handler function does whatever it needs to do to refresh or resize the component. (The widget can call
offVisibilityChange when it is destroyed.) Hideable components call
apex.widget.util.visibilityChange any time the visibility of an element it manages changes. It passes in the element that changed visibility and
true if it became visible and
false if it became hidden. In this way hideables can notify any components that need to know when they become visible (or invisible) without having to know anything about those components.
Note: do not use this API to detect when a tab is made active or a collapsible is expanded. There are events for those purposes.
So far this has been implemented for Interactive Reports, Interactive Grids, JET Charts, and Calendar and in apexTabs (used by Region Display Selector and Universal Theme Tabs Container region template), Collapsible region template and Show, Hide Dynamic Actions.
If you create a region plug-in (or region template) that can show and hide its contents then you should implement the necessary call(s) to
apex.widget.util.visibilityChange so that regions like Interactive Grid or JET Charts can be placed inside it.
If you create a region plug-in that is a size managed component then you should use
apex.widget.util.onVisibilityChange so that when the region is placed in a hideable region it can be notified when it is made visible. Keep in mind that the size of the containing hidable may have changed while the region was hidden so the region should resize itself every time it is made visible.
There is an oddity with the Region Display Selector (RDS) in how it handles visibility. Initially the RDS always had a Show All tab and would show all the regions when the page loads. In 5.0 when the options to not have a Show All tab and to remember the selected tab were added it was now possible for components to be initialized while they were hidden in an RDS tab. We started noticing problems with some item types so a partial last minute workaround was added where the RDS would show all the tabs for a brief moment when the page loads so that page items could be properly initialized. Now that we have the visibility change APIs this momentary visibility “solution” is regrettable. If you had a widget that is expensive to initialize you may implement it such that it doesn’t do much if it is invisible and only when it is first made visible does it do the full initialization. The current RDS behavior spoils this optimization. I don’t know what we will do about this.
Another thing to know about if you create size managed component plug-ins is the
updateResizeSensors APIs in the
apex.widget.util namespace. See the
widget.util.js file for details. A simple way to create a widget that dynamically resizes itself to fit the available space is to listen for window resize event (or better the
apexwindowresized event). But this doesn’t cover all the cases where the the region should be resized. For example the collapsible navigation side bar used in Universal Theme can leave the main content either too wide or too narrow. The solution is to use
onElementResize to be notified when the widget element container size changes. Currently the only example of this is in
Disclaimer: None of the above APIs are currently documented or supported. I don’t know if they will be documented and supported in the next APEX release.