Custom data tips in stacked Flex charts

The number of frustrating decisions in Flex's charting API is minimal, but high up on my list is a strange decision that prevents developers from accessing information that is frequently desirable for custom data tips in stacked area, bar and column charts. The default data tips for stacked charts display, amongst other things, the total of the values for all the series at a specific point along the x-axis and the percentage the highlighted segment forms of this total, as shown in the following example (source code):

If you wanted to customise the data tips and still include information such as the total and percentage values then you would be out of luck. This why I consider the decision to give the necessary information protected scope in the relevant classes in the charting API as strange. Fortunately circumnavigating this issue only requires a little bit of dirty work...

But first, a brief diversion to provide a little background...The code used to create a stacked column chart generally takes the following form:

<mx:ColumnChart type="stacked">
    <mx:series>
        <mx:ColumnSeries />
        ...
    </mx:series>
</mx:ColumnChart>

This is in fact a shortcut syntax. The ColumnChart automatically wraps the array of series into a ColumnSet with type "stacked", as it is the ColumnSet class that takes care of the stacking and associated behaviour rather than the ColumnChart class. The same pattern occurs in stacked AreaChart or BarChart. Consequently, the following MXML produces the same end result:

<mx:ColumnChart>
    <mx:series>
        <mx:ColumnSet type="stacked">
            <mx:ColumnSeries />
            ...
        </mx:ColumnSet>
    </mx:series>
</mx:ColumnChart>

When wanting to create more complex combinations of stacking, clustering and overlaying in charts, this can only be achieved by explicitly introducing (and nesting) sets - as in the second code snippet.

To be able to display customised data tips that include information relating to the stacking in a stacked ColumnChart, BarChart or AreaChart we can take one of two approaches. Both approaches involve extending the ColumnSet, BarSet or AreaSet class (depending on the desired chart type) as it is the protected-scoped negTotalsByPrimaryAxis, posTotalsByPrimaryAxis, stackedMaximum and stackedMinimum properties that contain the interesting information. The first approach is to override the formatDataTip method in the extended class, resulting in something along the following lines:

/**
 * ColumnSet extension to introduce custom data tips.
 */
public class ColumnSet extends mx.charts.series.ColumnSet
{
    /**
     * @inheritDoc
     */
    override protected function formatDataTip(hd:HitData):String
    {
        // build up the custom data tip
        var tip:String = "";
        ...
        return tip;
    }
}

However, I think that this approach is slightly short-sighted because it means that for every customisation of the data tips you would create a new extension. The other, and in my opinion more reusable, approach is to expose the aforementioned properties publicly in extensions to the ColumnSet, BarSet and AreaSet classes. By creating these extensions, the standard approach to customising data tips can be used, i.e. a method with the appropriate signature is passed to the chart's dataTipFunction property. The classes resulting from this approach would be something along the following lines:

/**
 * ColumnSet extension to expose the stack totals for public
 * use, e.g. in a data tip function.
 */
public class ColumnSet extends mx.charts.series.ColumnSet
{
    /**
     * @see StackedSeries.posTotalsByPrimaryAxis
     */
    public function get positiveTotalsByAxis():Dictionary
    {
        return posTotalsByPrimaryAxis;
    }

    ...
}

The minor downside to this approach is that the shortcut syntax for achieving stacked series, as used in the first example and explained above, cannot be used. The explicit syntax must be used to ensure that the extended version of the relevant StackedSeries extension is used.

The following example uses the approach presented above to provide customised data tips in the chart. The source code for the example includes the necessary extensions to the ColumnSet, BarSet and AreaSet classes, so feel free to use them.

MORE BY GRAHAM

Do You Need A Conversational UI?

The Catch 22 of Conversational UIs

blog comments powered by Disqus