Search code examples
apache-flexflex4flex4.5

Flex's AreaChart bug


What's up with Flex's AreaChart bug, does anybody know how to fix it? It causes ones tooltips to display the wrong value for minFields.

I.e. for:

<mx:AreaSeries yField="TotalVariableCost" minField="TotalFixedCost" displayName="Total Cost">

It will show:

Total Cost
high: TotalVariableCost
low: TotalVariableCost

As opposed to:

Total Cost
high: TotalVariableCost
low: TotalFixedCost

This bug is suppose to be in lines 2058 to 2083 of AreaSeries.as - but that stuff is way beyond my comprehension.

--Stephen


Solution

  • Yep, it's a bug in AreaSeries. Due to the stupid way that flex charts are designed, the only real way to fix it is to set a custom dataTipFunction on the AreaChart.

    Here's a copy of the relevant code with the bug fixed:

    /**
     * Create a data tip function for the given AreaSeries. Uses a copy of
     * the formatDataTip code from AreaSeries with the minValue bug fixed.
     * 
     * @param series
     * @return a data tip function
     * 
     */
    private function createAreaSeriesTipFunc(series:AreaSeries):Function {
       var displayName:String = series.displayName;
       var dataTransform:DataTransform = series.dataTransform;
       var xField:String = series.xField;
       var minField:String = series.minField;
    
       // formatDataTip relies on AreaSeries member data so simulate that
       // with a closure to minimize code modifications
    
       return function(hd:HitData):String {
          var dt:String = "";
          var n:String = displayName;
          if (n && n != "")
             dt += "<b>"+ n + "</b><BR/>";
    
          var xName:String = dataTransform.getAxis(CartesianTransform.HORIZONTAL_AXIS).displayName;
          if (xName == "")
             xName = xField;
          if (xName != "")
             dt += "<i>" + xName + ": </i>";
    
          var item:AreaSeriesItem = AreaSeriesItem(hd.chartItem);
          var lowItem:AreaSeriesItem = (minField != "") ?
             item :
             null;
          dt += dataTransform.getAxis(CartesianTransform.HORIZONTAL_AXIS).formatForScreen(item.xValue) + "\n";
    
          var yName:String = dataTransform.getAxis(CartesianTransform.VERTICAL_AXIS).displayName;
    
          if (!lowItem)
          {
             if (yName != "")
                dt += "<i>" + yName + ":</i> ";
             dt += dataTransform.getAxis(CartesianTransform.VERTICAL_AXIS).formatForScreen(item.yValue) + "\n";
          }
          else
          {
             if (yName != "")
                dt += "<i>" + yName + " (high):</i> ";
             else
                dt += "<i>high: </i>";
             dt += dataTransform.getAxis(CartesianTransform.VERTICAL_AXIS).formatForScreen(item.yValue) + "\n";
    
             if (yName != "")
                dt += "<i>" + yName + " (low):</i> ";
             else
                dt += "<i>low:</i> ";
             dt += dataTransform.getAxis(CartesianTransform.VERTICAL_AXIS).formatForScreen(lowItem.minValue) + "\n";
          }
    
          return dt;
       };
    }
    

    I just changed formatForScreen(lowItem.yValue) to formatForScreen(lowItem.minValue) in one place. You can use it like this:

    <mx:AreaChart dataProvider="{chartData}" showDataTips="true" dataTipFunction="{createAreaSeriesTipFunc(areaSeries)}">
          <mx:series>
             <mx:AreaSeries id="areaSeries" yField="TotalVariableCost" minField="TotalFixedCost" displayName="Total Cost" />
          </mx:series>
    </mx:AreaChart>