Defining chart data

The chart controls have a dataProvider property that defines the data for the chart.

The data provider creates a level of abstraction between Flex components and the data that you use to populate them. You can populate multiple charts from the same data provider, switch data providers for a chart at run time, and modify the data provider so that changes are reflected by all charts using the data provider.

You can set the data provider on the chart, in which case all series inherit that data provider. Or you can set the data provider on each series in the chart.

Using chart data

To use the data from a data provider in your chart control, you map the xField and yField properties of the chart series to the fields in the data provider. The xField property defines the data for the horizontal axis, and the yField property defines the data for the vertical axis.

In ActionScript object syntax, assume your data provider has the following structure:

{month: "Feb", profit: 1000, expenses: 200, amount: 60}
In XML, the data might appear like the following:
<data> 
    <result month="Feb"> 
        <profit>1000</profit> 
        <expenses>200</expenses> 
        <amount>60</amount> 
    </result> 
</data>

You can use the profit and expenses fields and ignore the month field by mapping the xField property of the series object to one field and the yField property of the series object to another field, as the following example shows:

<mx:PlotSeries xField="profit" yField="expenses"/>

The result is that each data point is the intersection of the profit and expenses fields from the data provider.

To place the data points into a meaningful grouping, you can choose a separate property of the data provider as the categoryField. In this case, to sort each data point by month, you map the month field to the categoryField property of the horizontal axis:

<mx:horizontalAxis> 
    <mx:CategoryAxis 
        dataProvider="{srv.lastResult.data.result}" 
        categoryField="month" 
    /> 
</mx:horizontalAxis>

In some cases, depending on the type of chart and the type of data you are representing, you use either the xField property or the yField property to define the data series. In a ColumnChart control, for example, the yField property defines the height of the column. You do not have to specify an xField property. To get an axis label for each column, you specify a categoryField property for the horizontalAxis.

The data provider can contain complex objects, or objects within objects. For example, a data provider object can have the following structure:

{month: "Aug", close: {High:45.87,Low:12.2}, open:25.19}

In this case, you cannot simply refer to the field of the data provider by using a categoryField, xField, or similar flat naming convention. Rather, you use the dataFunction of the series or axis to drill down into the data provider. For more information on working with complex data, see Structure of chart data.

When you use chart data, keep the following in mind:

  • You usually match a series with a data provider field if you want to display that series. However, this is not always true. If you do not specify an xField for a ColumnSeries, Flex assumes the index is the value. If you do not specify a yField, Flex assumes the data provider is a collection of y values, rather than a collection of objects that have y values. For example, the following series renders correctly for a ColumnChart control:

    <mx:ColumnSeries dataProvider="{[1,2,3,4,5]}"/>
  • Some series use only one field from the data provider, while others can use two or more. For example, you specify only a field property for a PieSeries object, but you can specify an xField and a yField for a PlotSeries object and an xField, yField, and radiusField for a BubbleSeries object.

  • Most of the series can determine suitable defaults for their nonprimary dimensions if no field is specified. For example, if you do not explicitly set an xField for the ColumnSeries, LineSeries, and AreaSeries, Flex maps the data to the chart’s categories in the order in which the data appears in the data provider. Similarly, a BarSeries maps the data to the categories if you do not set a yField.

For a complete list of the fields that each data series can use, see the data series’s class entry in ActionScript 3.0 Reference for the Adobe Flash Platform. For more information on data providers, see Data provider controls.

Sources of chart data

You can supply data to a data provider in the following ways:

  • Define it in a <fx:Script> block.

  • Define it in an external XML, ActionScript, or text file.

  • Return it by using a WebService call.

  • Return it by using a RemoteObject component.

  • Return it by using an HTTPService component.

  • Define it in MXML.

There are some limitations on the structure of the chart data, and how to reference chart data if it is constructed with complex objects. For more information, see Structure of chart data.

For more information on data providers, see Data providers and collections.

Using static Arrays as data providers

Using a static Array of objects for the data provider is the simplest approach. You typically create an Array of objects, as the following example shows:

<?xml version="1.0"?>
<!-- charts/ArrayOfObjectsDataProvider.mxml -->
<s:Application 
    xmlns:fx="http://ns.adobe.com/mxml/2009" 
    xmlns:mx="library://ns.adobe.com/flex/mx" 
    xmlns:s="library://ns.adobe.com/flex/spark"
    height="600">
    
  <fx:Script><![CDATA[
     [Bindable]
     private var expenses:Array = [
        {Month:"January",Profit:2000,Expenses:1500,Amount:450},
        {Month:"February",Profit:1000,Expenses:200,Amount:600},
        {Month:"March",Profit:1500,Expenses:500,Amount:300},
        {Month:"April",Profit:500,Expenses:300,Amount:500},
        {Month:"May",Profit:1000,Expenses:450,Amount:250},
        {Month:"June",Profit:2000,Expenses:500,Amount:700}
     ];

  ]]></fx:Script>
  
    <s:layout>
        <s:VerticalLayout/>
    </s:layout>

  <s:Panel title="Column Chart">
        <s:layout>
            <s:VerticalLayout/>
        </s:layout>
     <mx:ColumnChart id="myChart" 
        dataProvider="{expenses}" 
        showDataTips="true">
        <mx:horizontalAxis>
           <mx:CategoryAxis 
                dataProvider="{expenses}" 
                categoryField="Month"/>
        </mx:horizontalAxis>
        <mx:series>
           <mx:ColumnSeries 
                xField="Month" 
                yField="Profit"
                displayName="Profit"/>
           <mx:ColumnSeries 
                xField="Month" 
                yField="Expenses"
                displayName="Expenses"/>
        </mx:series>
     </mx:ColumnChart>
     <mx:Legend dataProvider="{myChart}"/>
  </s:Panel>
</s:Application>

The executing SWF file for the previous example is shown below:

You can also use MXML to define the content of an Array, as the following example shows:

<?xml version="1.0"?>
<!-- charts/ArrayOfMXMLObjectsDataProvider.mxml -->
<s:Application 
    xmlns:fx="http://ns.adobe.com/mxml/2009" 
    xmlns:mx="library://ns.adobe.com/flex/mx" 
    xmlns:s="library://ns.adobe.com/flex/spark"
    height="600">

  <fx:Declarations>
      <fx:Array id="expenses">
         <fx:Object
            Month="January"
            Profit="2000"
            Expenses="1500"
            Amount="450"
         />
         <fx:Object
            Month="February"
            Profit="1000"
            Expenses="200"
            Amount="600"
         />
         <fx:Object
            Month="March"
            Profit="1500"
            Expenses="500"
            Amount="300"
         />
         <fx:Object
            Month="April"
            Profit="500"
            Expenses="300"
            Amount="500"
         />
         <fx:Object
            Month="May"
            Profit="1000"
            Expenses="450"
            Amount="250"
         />
         <fx:Object
            Month="June"
            Profit="2000"
            Expenses="500"
            Amount="700"
         />
      </fx:Array>
  </fx:Declarations>

    <s:layout>
        <s:VerticalLayout/>
    </s:layout>

  <s:Panel title="Column Chart">
        <s:layout>
            <s:VerticalLayout/>
        </s:layout>
     <mx:ColumnChart id="myChart" 
        dataProvider="{expenses}" 
        showDataTips="true">
        <mx:horizontalAxis>
           <mx:CategoryAxis 
                dataProvider="{expenses}" 
                categoryField="Month"/>
        </mx:horizontalAxis>
        <mx:series>
           <mx:ColumnSeries 
                xField="Month" 
                yField="Profit"
                displayName="Profit"/>
           <mx:ColumnSeries 
                xField="Month" 
                yField="Expenses"
                displayName="Expenses"/>
        </mx:series>
     </mx:ColumnChart>
     <mx:Legend dataProvider="{myChart}"/>
  </s:Panel>
</s:Application>

The executing SWF file for the previous example is shown below:

When defining data in an Array in MXML, be sure to wrap it in a <fx:Declarations> tag.

You can also define objects in MXML with a more verbose syntax, as the following example shows:

<?xml version="1.0"?>
<!-- charts/ArrayOfVerboseMXMLObjects.mxml -->
<s:Application 
    xmlns:fx="http://ns.adobe.com/mxml/2009" 
    xmlns:mx="library://ns.adobe.com/flex/mx" 
    xmlns:s="library://ns.adobe.com/flex/spark"
    height="600">

  <fx:Declarations>
      <fx:Array id="expenses">
         <fx:Object>
           <fx:Month>January</fx:Month>
           <fx:Profit>2000</fx:Profit>
           <fx:Expenses>1500</fx:Expenses>
           <fx:Amount>450</fx:Amount>
         </fx:Object>
         <fx:Object>
           <fx:Month>February</fx:Month>
           <fx:Profit>1000</fx:Profit>
           <fx:Expenses>200</fx:Expenses>
           <fx:Amount>600</fx:Amount>
         </fx:Object>
         <fx:Object>
           <fx:Month>March</fx:Month>
           <fx:Profit>1500</fx:Profit>
           <fx:Expenses>500</fx:Expenses>
           <fx:Amount>300</fx:Amount>
         </fx:Object>
         <fx:Object>
           <fx:Month>April</fx:Month>
           <fx:Profit>500</fx:Profit>
           <fx:Expenses>300</fx:Expenses>
           <fx:Amount>300</fx:Amount>
         </fx:Object>
         <fx:Object>
           <fx:Month>May</fx:Month>
           <fx:Profit>1000</fx:Profit>
           <fx:Expenses>450</fx:Expenses>
           <fx:Amount>250</fx:Amount>
         </fx:Object>
         <fx:Object>
           <fx:Month>June</fx:Month>
           <fx:Profit>2000</fx:Profit>
           <fx:Expenses>500</fx:Expenses>
           <fx:Amount>700</fx:Amount>
         </fx:Object>
      </fx:Array>
  </fx:Declarations>

    <s:layout>
        <s:VerticalLayout/>
    </s:layout>

  <s:Panel title="Column Chart">
        <s:layout>
            <s:VerticalLayout/>
        </s:layout>
     <mx:ColumnChart id="myChart" dataProvider="{expenses}" showDataTips="true">
        <mx:horizontalAxis>
           <mx:CategoryAxis
                dataProvider="{expenses}"
                categoryField="Month"/>
        </mx:horizontalAxis>
        <mx:series>
           <mx:ColumnSeries 
                xField="Month" 
                yField="Profit"
                displayName="Profit"/>
           <mx:ColumnSeries 
                xField="Month" 
                yField="Expenses"
                displayName="Expenses"/>
        </mx:series>
     </mx:ColumnChart>
     <mx:Legend dataProvider="{myChart}"/>
  </s:Panel>
</s:Application>

The executing SWF file for the previous example is shown below:

A disadvantage of using a simple Array as a chart’s data provider is that you can use only the methods of the Array class to manipulate the data. In addition, when you use an Array as a data provider, the data in it must be static. Even if you make the Array bindable, when data in an Array changes, the chart does not reflect those changes. For more robust data manipulation and data binding, you can use a collection for the chart data provider, as described in Using collections as data providers.

Using collections as data providers

Collections are a more robust data provider mechanism than Arrays. They provide operations that include the insertion and deletion of objects as well as sorting and filtering. Collections also support change notification. An ArrayCollection object provides an easy way to expose an Array as an ICollectionView or IList interface.

As with Arrays, you can use MXML to define the contents of a collection, as the following example shows:

<?xml version="1.0"?>
<!-- charts/ArrayCollectionOfMXMLObjectsDataProvider.mxml -->
<s:Application 
    xmlns:fx="http://ns.adobe.com/mxml/2009" 
    xmlns:mx="library://ns.adobe.com/flex/mx" 
    xmlns:s="library://ns.adobe.com/flex/spark"
    height="600">
    
    <fx:Declarations>
        <s:ArrayCollection id="expenses">
             <fx:Object
                Month="January"
                Profit="2000"
                Expenses="1500"
                Amount="450"/>
             <fx:Object
                Month="February"
                Profit="1000"
                Expenses="200"
                Amount="600"/>
             <fx:Object
                Month="March"
                Profit="1500"
                Expenses="500"
                Amount="300"/>
             <fx:Object
                Month="April"
                Profit="500"
                Expenses="300"
                Amount="500"/>
             <fx:Object
                Month="May"
                Profit="1000"
                Expenses="450"
                Amount="250"/>
             <fx:Object
                Month="June"
                Profit="2000"
                Expenses="500"
                Amount="700"/>
          </s:ArrayCollection>
    </fx:Declarations>

    <s:layout>
        <s:VerticalLayout/>
    </s:layout>

  <s:Panel title="Column Chart">
        <s:layout>
            <s:VerticalLayout/>
        </s:layout>
     <mx:ColumnChart id="myChart" 
        dataProvider="{expenses}" 
        showDataTips="true">
        <mx:horizontalAxis>
           <mx:CategoryAxis 
                dataProvider="{expenses}" 
                categoryField="Month"/>
        </mx:horizontalAxis>
        <mx:series>
           <mx:ColumnSeries 
                xField="Month" 
                yField="Profit"
                displayName="Profit"/>
           <mx:ColumnSeries 
                xField="Month" 
                yField="Expenses"
                displayName="Expenses"/>
        </mx:series>
     </mx:ColumnChart>
     <mx:Legend dataProvider="{myChart}"/>
  </s:Panel>
</s:Application>

The executing SWF file for the previous example is shown below:

Or you can define an object in MXML using child tags rather than attributes:

<?xml version="1.0"?>
<!-- charts/ArrayCollectionOfVerboseMXMLObjects.mxml -->
<s:Application 
    xmlns:fx="http://ns.adobe.com/mxml/2009" 
    xmlns:mx="library://ns.adobe.com/flex/mx" 
    xmlns:s="library://ns.adobe.com/flex/spark"
    height="600">

    <fx:Declarations>
      <s:ArrayCollection id="expenses">
         <fx:Object>
           <fx:Month>January</fx:Month>
           <fx:Profit>2000</fx:Profit>
           <fx:Expenses>1500</fx:Expenses>
           <fx:Amount>450</fx:Amount>
         </fx:Object>
         <fx:Object>
           <fx:Month>February</fx:Month>
           <fx:Profit>1000</fx:Profit>
           <fx:Expenses>200</fx:Expenses>
           <fx:Amount>600</fx:Amount>
         </fx:Object>
         <fx:Object>
           <fx:Month>March</fx:Month>
           <fx:Profit>1500</fx:Profit>
           <fx:Expenses>500</fx:Expenses>
           <fx:Amount>300</fx:Amount>
         </fx:Object>
         <fx:Object>
           <fx:Month>April</fx:Month>
           <fx:Profit>500</fx:Profit>
           <fx:Expenses>300</fx:Expenses>
           <fx:Amount>300</fx:Amount>
         </fx:Object>
         <fx:Object>
           <fx:Month>May</fx:Month>
           <fx:Profit>1000</fx:Profit>
           <fx:Expenses>450</fx:Expenses>
           <fx:Amount>250</fx:Amount>
         </fx:Object>
         <fx:Object>
           <fx:Month>June</fx:Month>
           <fx:Profit>2000</fx:Profit>
           <fx:Expenses>500</fx:Expenses>
           <fx:Amount>700</fx:Amount>
         </fx:Object>
      </s:ArrayCollection>
    </fx:Declarations>

    <s:layout>
        <s:VerticalLayout/>
    </s:layout>

  <s:Panel title="Column Chart">
        <s:layout>
            <s:VerticalLayout/>
        </s:layout>
     <mx:ColumnChart id="myChart" 
        dataProvider="{expenses}" 
        showDataTips="true">
        <mx:horizontalAxis>
           <mx:CategoryAxis
                dataProvider="{expenses}"
                categoryField="Month"/>
        </mx:horizontalAxis>
        <mx:series>
           <mx:ColumnSeries 
                xField="Month" 
                yField="Profit"
                displayName="Profit"/>
           <mx:ColumnSeries 
                xField="Month" 
                yField="Expenses"
                displayName="Expenses"/>
        </mx:series>
     </mx:ColumnChart>
     <mx:Legend dataProvider="{myChart}"/>
  </s:Panel>
</s:Application>

The executing SWF file for the previous example is shown below:

You can create an ArrayCollection object in ActionScript. If you define an ArrayCollection in this way, ensure that you import the mx.collections.ArrayCollection class, as the following example shows:

<?xml version="1.0"?>
<!-- charts/ArrayCollectionOfObjects.mxml -->
<s:Application 
    xmlns:fx="http://ns.adobe.com/mxml/2009" 
    xmlns:mx="library://ns.adobe.com/flex/mx" 
    xmlns:s="library://ns.adobe.com/flex/spark"
    height="600">
    
    <s:layout>
        <s:VerticalLayout/>
    </s:layout>

  <fx:Script><![CDATA[
     import mx.collections.ArrayCollection;
     [Bindable]
     private var expenses:ArrayCollection = new ArrayCollection([
        {Month:"January", Profit:2000, Expenses:1500, Amount:450},
        {Month:"February", Profit:1000, Expenses:200, Amount:600},
        {Month:"March", Profit:1500, Expenses:500, Amount:300},
        {Month:"April", Profit:500, Expenses:300, Amount:500},
        {Month:"May", Profit:1000, Expenses:450, Amount:250},
        {Month:"June", Profit:2000, Expenses:500, Amount:700}
     ]);
  ]]></fx:Script>
  
  <s:Panel title="Column Chart">
        <s:layout>
            <s:VerticalLayout/>
        </s:layout>
     <mx:ColumnChart id="myChart" 
        dataProvider="{expenses}" 
        showDataTips="true">
        <mx:horizontalAxis>
           <mx:CategoryAxis
                dataProvider="{expenses}"
                categoryField="Month"/>
        </mx:horizontalAxis>
        <mx:series>
           <mx:ColumnSeries 
                xField="Month" 
                yField="Profit"
                displayName="Profit"/>
           <mx:ColumnSeries 
                xField="Month" 
                yField="Expenses"
                displayName="Expenses"/>
        </mx:series>
     </mx:ColumnChart>
     <mx:Legend dataProvider="{myChart}"/>
  </s:Panel>
</s:Application>

The executing SWF file for the previous example is shown below:

If your data is in an Array, you can pass the Array to the ArrayCollection’s constructor to convert it to an ArrayCollection. The following example creates an Array, and then converts it to an ArrayCollection:

<?xml version="1.0"?>
<!-- charts/ArrayConvertedToArrayCollection.mxml -->
<s:Application 
    xmlns:fx="http://ns.adobe.com/mxml/2009" 
    xmlns:mx="library://ns.adobe.com/flex/mx" 
    xmlns:s="library://ns.adobe.com/flex/spark"
    height="600">
  
  <fx:Script><![CDATA[
     import mx.collections.ArrayCollection;

     private var expenses:Array = [
        {Month:"January", Profit:2000, Expenses:1500, Amount:450},
        {Month:"February", Profit:1000, Expenses:200, Amount:600},
        {Month:"March", Profit:1500, Expenses:500, Amount:300},
        {Month:"April", Profit:500, Expenses:300, Amount:500},
        {Month:"May", Profit:1000, Expenses:450, Amount:250},
        {Month:"June", Profit:2000, Expenses:500, Amount:700}
     ];

     [Bindable]
     public var expensesAC:ArrayCollection = 
        new ArrayCollection(expenses);
  ]]></fx:Script>

    <s:layout>
        <s:VerticalLayout/>
    </s:layout>

  <s:Panel title="Column Chart">
        <s:layout>
            <s:VerticalLayout/>
        </s:layout>
     <mx:ColumnChart id="myChart" 
        dataProvider="{expensesAC}" 
        showDataTips="true">
        <mx:horizontalAxis>
           <mx:CategoryAxis
                dataProvider="{expensesAC}"
                categoryField="Month"/>
        </mx:horizontalAxis>
        <mx:series>
           <mx:ColumnSeries
                xField="Month"
                yField="Profit"
                displayName="Profit"/>
           <mx:ColumnSeries
                xField="Month"
                yField="Expenses"
                displayName="Expenses"/>
        </mx:series>
     </mx:ColumnChart>
     <mx:Legend dataProvider="{myChart}"/>
  </s:Panel>
</s:Application>

The executing SWF file for the previous example is shown below:

Similarly, you can use an <s:ArrayCollection> tag to perform the conversion:

<?xml version="1.0"?>
<!-- charts/ArrayConvertedToArrayCollectionMXML.mxml -->
<s:Application 
    xmlns:fx="http://ns.adobe.com/mxml/2009" 
    xmlns:mx="library://ns.adobe.com/flex/mx" 
    xmlns:s="library://ns.adobe.com/flex/spark"
    height="600">
  
  <fx:Script><![CDATA[
     import mx.collections.ArrayCollection;

     [Bindable]
     private var expenses:Array = [
        {Month:"January", Profit:2000, Expenses:1500, Amount:450},
        {Month:"February", Profit:1000, Expenses:200, Amount:600},
        {Month:"March", Profit:1500, Expenses:500, Amount:300},
        {Month:"April", Profit:500, Expenses:300, Amount:500},
        {Month:"May", Profit:1000, Expenses:450, Amount:250},
        {Month:"June", Profit:2000, Expenses:500, Amount:700}
     ];
  ]]></fx:Script>

  <fx:Declarations>
      <s:ArrayCollection id="expensesAC" source="{expenses}"/>
  </fx:Declarations>

    <s:layout>
        <s:VerticalLayout/>
    </s:layout>

  <s:Panel title="Column Chart">
        <s:layout>
            <s:VerticalLayout/>
        </s:layout>
     <mx:ColumnChart id="myChart" 
        dataProvider="{expensesAC}" 
        showDataTips="true">
        <mx:horizontalAxis>
           <mx:CategoryAxis 
                dataProvider="{expensesAC}" 
                categoryField="Month"/>
        </mx:horizontalAxis>
        <mx:series>
           <mx:ColumnSeries 
                xField="Month" 
                yField="Profit"
                displayName="Profit"/>
           <mx:ColumnSeries 
                xField="Month" 
                yField="Expenses"
                displayName="Expenses"/>
        </mx:series>
     </mx:ColumnChart>
     <mx:Legend dataProvider="{myChart}"/>
  </s:Panel>
</s:Application>

The executing SWF file for the previous example is shown below:

The data in ArrayCollections can be bound to the chart’s data provider so that the data can be updated in real-time. The following example creates an object with elapsed time and total memory usage every second. It then pushes that new object onto an ArrayCollection that is used as the data provider for a line chart. As a result, the chart itself updates every second showing memory usage of Adobe® Flash® Player or Adobe® AIR™ over time.

<?xml version="1.0"?>
<!-- charts/RealTimeArrayCollection.mxml -->
<s:Application 
    xmlns:fx="http://ns.adobe.com/mxml/2009" 
    xmlns:mx="library://ns.adobe.com/flex/mx" 
    xmlns:s="library://ns.adobe.com/flex/spark" 
    initialize="initTimer()"
    height="600">
  
  <fx:Script><![CDATA[
      import flash.utils.Timer;
      import flash.events.TimerEvent;
      import mx.collections.ArrayCollection;

      [Bindable]
      public var memoryUsage:ArrayCollection = new ArrayCollection();

      public function initTimer():void {
         // The first parameter in the Timer constructor
         // is the interval, in milliseconds.
         // The second parameter is how many times to run (0 is
         // infinity).
         var myTimer:Timer = new Timer(1000, 0);

         // Add the listener for the timer event.
         myTimer.addEventListener("timer", timerHandler);
         myTimer.start();
      }

      public function timerHandler(event:TimerEvent):void {
         var o:Object = new Object();

         // Get the number of milliseconds since Flash Player or AIR started.
         o.time = getTimer();

         // Get the total memory Flash Player or AIR is using.
         o.memory = flash.system.System.totalMemory;
         trace(o.time + ":" + o.memory);

         // Add new object to the ArrayCollection, which is bound 
         // to the chart's data provider.
         memoryUsage.addItem(o);
      }
  ]]></fx:Script>

    <s:layout>
        <s:VerticalLayout/>
    </s:layout>

  <s:Panel title="Memory Usage">
     <s:layout>
         <s:VerticalLayout/>
     </s:layout>
      <mx:LineChart id="chart" 
        dataProvider="{memoryUsage}"
         showDataTips="true">
         <mx:horizontalAxis>
            <mx:LinearAxis/>
         </mx:horizontalAxis>
         <mx:verticalAxis>
            <mx:LinearAxis minimum="5000000"/>
         </mx:verticalAxis>
         <mx:series>
            <mx:LineSeries yField="memory"/>
         </mx:series>
      </mx:LineChart>
    </s:Panel>
</s:Application>

The executing SWF file for the previous example is shown below:

Data collections can be paged, which means that data is sent to the client in chunks as the application requests it. But Flex charting controls display all of the data all of the time, by default. As a result, when you use data collections with charts, you should disable the paging features or use non-paged views of the data collection for chart data.

For more information on using collections, see Data providers and collections.

Using an XML file as a data provider

You can define data provider data in a structured file. The following example shows the contents of the data.xml file:

<data>
    <result month="Jan-04">
        <apple>81768</apple>
        <orange>60310</orange>
        <banana>43357</banana>
    </result>
    <result month="Feb-04">
        <apple>81156</apple>
        <orange>58883</orange>
        <banana>49280</banana>
    </result>
</data>

You can load the file directly as a source of a Model, as the following example shows:

<?xml version="1.0"?>
<!-- charts/XMLFileDataProvider.mxml -->
<s:Application 
    xmlns:fx="http://ns.adobe.com/mxml/2009" 
    xmlns:mx="library://ns.adobe.com/flex/mx" 
    xmlns:s="library://ns.adobe.com/flex/spark"
    height="600">

    <fx:Declarations>    
        <fx:Model id="results" source="../assets/data.xml"/>
    </fx:Declarations>

    <s:layout>
        <s:VerticalLayout/>
    </s:layout>

  <s:Panel title="Line Chart">
     <s:layout>
         <s:HorizontalLayout/>
     </s:layout>
     <mx:LineChart id="myChart" 
        dataProvider="{results.result}" showDataTips="true">
        <mx:horizontalAxis>
           <mx:CategoryAxis categoryField="month"/>
        </mx:horizontalAxis>
        <mx:series>
           <mx:LineSeries yField="banana" displayName="Banana"/>
           <mx:LineSeries yField="apple" displayName="Apple"/>
           <mx:LineSeries yField="orange" displayName="Orange"/>
        </mx:series>
     </mx:LineChart>
     <mx:Legend dataProvider="{myChart}"/>     
  </s:Panel>
</s:Application>

The executing SWF file for the previous example is shown below:

You can use more complex XML to define the data provider’s data. For example, an XML-based data provider can have nested tags. In that case, however, you must use a dataFunction to define the fields that the chart uses. For more information, see Structure of chart data.

To use an ArrayCollection as the chart’s data provider, you convert the Model to an ArrayCollection, as the following example shows:

<?xml version="1.0"?>
<!-- charts/XMLFileToArrayCollectionDataProvider.mxml -->
<s:Application 
    xmlns:fx="http://ns.adobe.com/mxml/2009" 
    xmlns:mx="library://ns.adobe.com/flex/mx" 
    xmlns:s="library://ns.adobe.com/flex/spark"
    height="600">
    
    <fx:Declarations>
        <fx:Model id="results" source="../assets/data.xml"/>
        <s:ArrayCollection id="myAC" 
            source="{ArrayUtil.toArray(results.result)}"/>
    </fx:Declarations>

    <fx:Script>
        import mx.utils.ArrayUtil;
    </fx:Script>

    <s:layout>
        <s:VerticalLayout/>
    </s:layout>

  <s:Panel title="Line Chart">
     <s:layout>
         <s:HorizontalLayout/>
     </s:layout>
     <mx:LineChart id="myChart" 
        dataProvider="{myAC}" showDataTips="true">
        <mx:horizontalAxis>
           <mx:CategoryAxis categoryField="month"/>
        </mx:horizontalAxis>
        <mx:series>
           <mx:LineSeries yField="banana" displayName="Banana"/>
           <mx:LineSeries yField="apple" displayName="Apple"/>
           <mx:LineSeries yField="orange" displayName="Orange"/>
        </mx:series>
     </mx:LineChart>
     <mx:Legend dataProvider="{myChart}"/>     
  </s:Panel>
</s:Application>

The executing SWF file for the previous example is shown below:

Using HTTPService as a data provider

You can define an XML file or any page that returns an XML result as a URL for an HTTPService component. You then bind the HTTPService result directly to the chart’s data provider, as the following example shows:

<?xml version="1.0"?>
<!-- charts/HTTPServiceDataProvider.mxml -->
<s:Application 
    xmlns:fx="http://ns.adobe.com/mxml/2009" 
    xmlns:mx="library://ns.adobe.com/flex/mx" 
    xmlns:s="library://ns.adobe.com/flex/spark" 
    creationComplete="srv.send()"
    height="600">

    <fx:Declarations>
        <!-- View source of the following page to see the structure of the data that Flex uses in this example. -->
        <mx:HTTPService id="srv" url="http://aspexamples.adobe.com/chart_examples/expenses-xml.aspx"/>
        <!-- To see data in an HTML table, go to http://aspexamples.adobe.com/chart_examples/expenses.aspx -->  
    </fx:Declarations>

    <s:layout>
        <s:VerticalLayout/>
    </s:layout>

  <s:Panel title="Line Chart">
        <s:layout>
            <s:VerticalLayout/>
        </s:layout>
     <mx:LineChart id="myChart" 
        dataProvider="{srv.lastResult.data.result}"
        showDataTips="true">
        <mx:horizontalAxis>
           <mx:CategoryAxis categoryField="month"/>
        </mx:horizontalAxis>
        <mx:series>
          <mx:LineSeries 
                yField="profit" 
                displayName="Profit"/>
           <mx:LineSeries 
                yField="expenses" 
                displayName="Expenses"/>
         </mx:series>
     </mx:LineChart>
     <mx:Legend dataProvider="{myChart}"/>     
  </s:Panel>   
</s:Application>

The executing SWF file for the previous example is shown below:

As with most other non-visual components, be sure to wrap the <mx:HTTPService> tag in a <fx:Declarations> tag.

In this example, the target URL returns the following XML:
<data> 
    <result month="Jan"> 
        <profit>2000</profit> 
        <expenses>1500</expenses> 
        <amount>450</amount> 
    </result> 
    <result month="Feb"> 
        <profit>1000</profit> 
        <expenses>200</expenses> 
        <amount>600</amount> 
    </result> 
    <result month="Mar"> 
        <profit>1500</profit> 
        <expenses>500</expenses> 
        <amount>300</amount> 
    </result> 
</data>

To use an ArrayCollection, you cast the HTTPService result, as the following example shows:

<?xml version="1.0"?>
<!-- charts/HTTPServiceToArrayCollectionDataProvider.mxml -->
<s:Application 
    xmlns:fx="http://ns.adobe.com/mxml/2009" 
    xmlns:mx="library://ns.adobe.com/flex/mx" 
    xmlns:s="library://ns.adobe.com/flex/spark" 
    creationComplete="srv.send()"
    height="600">

    <fx:Declarations>
        <!-- View source of the following page to see the structure of the data that Flex uses in this example. -->
        <!-- To see data in an HTML table, go to http://aspexamples.adobe.com/chart_examples/expenses.aspx -->  
        <mx:HTTPService id="srv" 
            url="http://aspexamples.adobe.com/chart_examples/expenses-xml.aspx" 
            useProxy="false" 
            result="myData=ArrayCollection(srv.lastResult.data.result)"
        />
    </fx:Declarations>

  <fx:Script><![CDATA[
     import mx.collections.ArrayCollection;
     [Bindable]
     public var myData:ArrayCollection;
  ]]></fx:Script>

    <s:layout>
        <s:VerticalLayout/>
    </s:layout>

  <s:Panel title="Line Chart">
        <s:layout>
            <s:VerticalLayout/>
        </s:layout>
     <mx:LineChart id="myChart" 
        dataProvider="{myData}" showDataTips="true">
        <mx:horizontalAxis>
           <mx:CategoryAxis categoryField="month"/>
        </mx:horizontalAxis>
        <mx:series>
          <mx:LineSeries 
                yField="profit" 
                displayName="Profit"/>
           <mx:LineSeries 
                yField="expenses" 
                displayName="Expenses"/>
        </mx:series>
     </mx:LineChart>
     <mx:Legend dataProvider="{myChart}"/>     
  </s:Panel>
</s:Application>

The executing SWF file for the previous example is shown below:

You can also set the result format of the HTTPService to E4X, and then use it as a source for an XMLListCollection object, as the following example shows:

<?xml version="1.0"?>
<!-- charts/HTTPServiceToXMLListCollection.mxml -->
<s:Application 
    xmlns:fx="http://ns.adobe.com/mxml/2009" 
    xmlns:mx="library://ns.adobe.com/flex/mx" 
    xmlns:s="library://ns.adobe.com/flex/spark" 
    creationComplete="srv.send()"
    height="600">

    <fx:Declarations>
        <!-- View source of the following page to see the structure of the data that Flex uses in this example. -->
        <!-- To see data in an HTML table, go to http://aspexamples.adobe.com/chart_examples/expenses.aspx -->  
        <mx:HTTPService id="srv" 
            url="http://aspexamples.adobe.com/chart_examples/expenses-xml.aspx" 
            resultFormat="e4x"
        />

        <mx:XMLListCollection id="myAC" 
            source="{srv.lastResult.result}"
        />

    </fx:Declarations>
  <fx:Script><![CDATA[

     import mx.utils.ArrayUtil;

  ]]></fx:Script>

    <s:layout>
        <s:VerticalLayout/>
    </s:layout>

  <s:Panel title="Line Chart">
        <s:layout>
            <s:VerticalLayout/>
        </s:layout>
     <mx:LineChart id="myChart" 
        dataProvider="{myAC}" showDataTips="true">
        <mx:horizontalAxis>
           <mx:CategoryAxis categoryField="@month"/>
        </mx:horizontalAxis>
        <mx:series>
          <mx:LineSeries 
                yField="profit" 
                displayName="Profit"/>
           <mx:LineSeries 
                yField="expenses" 
                displayName="Expenses"/>
        </mx:series>
     </mx:LineChart>
     <mx:Legend dataProvider="{myChart}"/>     
  </s:Panel>
</s:Application>

The executing SWF file for the previous example is shown below:

Another approach is to define the target URL of the HTTPService component as an HTML page that contains data. For example, you might have an HTML page with source that looks like the following:

<html> 
<body> 
<h1>This is a data page</h1> 
<!-- data starts here --> 
<entry>  
    <month>Jan</month>  
    <misc>15300</misc>   
</entry> 
<entry>  
    <month>Feb</month>  
    <misc>17800</misc>   
</entry> 
<entry>  
    <month>Mar</month>  
    <misc>20000</misc>   
</entry> 
<!-- data ends here --> 
</body> 
</html>

In your application, you can extract the data from the HTML page by using regular expressions. You can then assign the resulting string to an XMLList and use it as a data provider, as the following example shows:

<?xml version="1.0"?>
<!-- charts/HTMLDataProvider.mxml -->
<s:Application 
    xmlns:fx="http://ns.adobe.com/mxml/2009" 
    xmlns:mx="library://ns.adobe.com/flex/mx" 
    xmlns:s="library://ns.adobe.com/flex/spark" 
    creationComplete="initApp()"
    height="600">

    <fx:Declarations>
        <mx:HTTPService id="serviceInput" 
            resultFormat="text" 
            url="http://aspexamples.adobe.com/chart_examples/testDataPage.html"
        />
    </fx:Declarations>
    
    <fx:Script><![CDATA[
        import mx.events.FlexEvent;
        import mx.rpc.events.ResultEvent;
        import mx.rpc.events.FaultEvent;
        
        [Bindable]
        public var chartData:XMLList;   

        private function initApp():void {   
            serviceInput.addEventListener(ResultEvent.RESULT, resultHandler);
            serviceInput.addEventListener(FaultEvent.FAULT, faultHandler);
            serviceInput.send();    
        }

        public function resultHandler(evt:Event):void {
            // Extract the XML data from the HTML page.
            var htmlBlob:String = serviceInput.lastResult.toString();

            htmlBlob = htmlBlob.slice( htmlBlob.indexOf("<!-- data starts here -->", 0) + 
                25, htmlBlob.length );
            htmlBlob = htmlBlob.slice( 0, htmlBlob.indexOf("<!-- data ends here -->", 0) );             

            // Create an XMLList from the extracted XML data.
            chartData = new XMLList(htmlBlob);
        }

        public function faultHandler(evt:Event):void {
            trace(evt.toString());
        }
    ]]></fx:Script>
    
    <s:layout>
        <s:VerticalLayout/>
    </s:layout>

  <s:Panel title="Line chart with data extracted from HTML page">
        <s:layout>
            <s:VerticalLayout/>
        </s:layout>
         <mx:LineChart id="chart" 
            dataProvider="{chartData}" showDataTips="true">
             <mx:series>
                 <mx:LineSeries id="series1" yField="misc" xField="month"/>
             </mx:series>             
             <mx:horizontalAxis>
                 <mx:CategoryAxis categoryField="month"/>
             </mx:horizontalAxis>                  
         </mx:LineChart>
     </s:Panel>
</s:Application>

The executing SWF file for the previous example is shown below:

To load the data from a URL on another domain, that target domain must have a crossdomain.xml policy file in place. That policy file must allow the domain on which your Flex application is running to access its data.

In this example, if you requested the data page, the data does not render in the brower because it is wrapped in tags that are outside of the HTML specification. If the data were meant to be displayed, it might be surrounded in HTML entities for the left and right angle brackets, like the following example shows:

<html> 
<body> 
<h1>This is a data page</h1> 
<!-- data starts here --> 
&lt;entry&gt;  
    &lt;month&gt;Jan&lt;/month&gt;  
    &lt;misc&gt;15300&lt;/misc&gt;   
&lt;/entry&gt; 
&lt;entry&gt;  
    &lt;month&gt;Feb&lt;/month&gt;  
    &lt;misc&gt;17800&lt;/misc&gt;   
&lt;/entry&gt; 
&lt;entry&gt;  
    &lt;month&gt;Mar&lt;/month&gt;  
    &lt;misc&gt;20000&lt;/misc&gt;   
&lt;/entry> 
<!-- data ends here --> 
</body> 
</html>

In that case, you could replace the HTML entities with angle brackets after the source was loaded, as the following example shows:

var tagPattern:RegExp = /<[^<>]*>/g;   
htmlBlob = htmlBlob.replace(tagPattern, ""); 
 
var ltPattern:RegExp = /&lt;/g; 
htmlBlob = htmlBlob.replace(ltPattern, "<"); 
 
var gtPattern:RegExp = /&gt;/g; 
htmlBlob = htmlBlob.replace(gtPattern, ">");

Randomly generating chart data

A useful way to create data for use in sample charts is to generate random data. The following example generates test data for use with the chart controls:

<?xml version="1.0"?>
<!-- charts/RandomDataGeneration.mxml -->
<s:Application 
    xmlns:fx="http://ns.adobe.com/mxml/2009" 
    xmlns:mx="library://ns.adobe.com/flex/mx" 
    xmlns:s="library://ns.adobe.com/flex/spark"
    creationComplete="initApp()"
    height="600">
  
  <fx:Script><![CDATA[
     import mx.collections.*;

     // Define data provider array for the chart data.
     [Bindable]
     public var dataSet:ArrayCollection;

     // Define the number of elements in the array.
     public var dsLength:Number = 10;

     public function initApp():void {
        // Initialize data provider array.
        dataSet = new ArrayCollection(genData());
     }

     public function genData():Array {
        var result:Array = [];

        for (var i:int=0;i<dsLength;i++) {
           var localVals:Object = {
                valueA:Math.random()*100,
                valueB:Math.random()*100,
                valueX:Math.random()*100,
                valueY:Math.random()*100
           };

           // Push new object onto the data array.
           result.push(localVals);
        }
        return result;
     }
  ]]></fx:Script>

    <s:layout>
        <s:VerticalLayout/>
    </s:layout>

  <s:Panel title="Plot Chart">
     <s:layout>
         <s:VerticalLayout/>
     </s:layout>
     <mx:PlotChart id="myChart" 
        dataProvider="{dataSet}" showDataTips="true">
        <mx:series>
           <mx:PlotSeries 
                xField="valueX" 
                yField="valueY" 
                displayName="Series 1"/>
           <mx:PlotSeries 
                xField="valueA" 
                yField="valueB" 
                displayName="Series 2"/>
        </mx:series>
     </mx:PlotChart>
     <mx:Legend id="l1" dataProvider="{myChart}"/>
  </s:Panel>
</s:Application>

The executing SWF file for the previous example is shown below:

Structure of chart data

In most cases, the data that is used as the chart’s data provider is made up of scalar values. For example, objects contain a single set of fields:

{month: "Aug", close: 45.87, open:25.19},

Or XML data contains a single set of child tags in a flat structure:

<stock> 
    <month>Aug</month> 
    <close>45.87</close> 
    <open>25.19</open> 
</stock>

In these cases, you assign the data provider’s fields to items in the chart by using the xField and yField for the series, or the categoryField for the axis; for example:

<mx:ColumnSeries yField="close"/> 
<mx:CategoryAxis categoryField="month"/>

However, the structure of the chart data can be made up of more complex objects, such as objects within objects or XML with nested child tags. For example, you can embed an object within an object:

{month: "Aug", close: {High:45.87,Low:12.2}, open:25.19}

Or use nested tags in an XML object:

<stock> 
    <date> 
        <month>Aug</month> 
    </date> 
    <price> 
        <close>45.87</close> 
        <open>25.19</open> 
    </price> 
</stock>

In these cases, you cannot refer to the target data by using the flat naming such as yField="close". You also cannot use dot notation. For example, yField="values.close" or categoryField="data.month" are not valid. Instead, you must use a dataFunction method to define which ChartItem fields are populated by the data provider.

For the CategoryAxis class, the dataFunction has the following signature:

function_name(axis:AxisBase, item:Object):Object

Where axis is the base class for the current axis, and item is the item in the data provider.

For the Series class, the dataFunction has the following signature:

function_name(series:Series, item:Object, fieldName:String):Object

Where series is a reference to the current series, item is the item in the data provider, and fieldName is the field in the current ChartItem that will be populated.

The following example creates two functions that access complex data for both the axis and the series:

<?xml version="1.0"?>
<!-- charts/DataFunctionExample.mxml -->
<s:Application 
    xmlns:fx="http://ns.adobe.com/mxml/2009" 
    xmlns:mx="library://ns.adobe.com/flex/mx" 
    xmlns:s="library://ns.adobe.com/flex/spark" 
    height="600">

  <fx:Script><![CDATA[
    import mx.charts.chartClasses.AxisBase;
    import mx.charts.chartClasses.Series;
    import mx.charts.CategoryAxis;
    import mx.charts.chartClasses.IAxis;
    import mx.charts.chartClasses.ChartBase;        
    import mx.charts.chartClasses.CartesianTransform;
    
    // This data provider contains complex, nested objects.
    [Bindable]
    public var SMITH:Array = [
        {month: "Aug", close: {High:45.87,Low:12.2}, open:25.19},
        {month: "Sep", close: {High:45.74,Low:10.23}, open:35.29},
        {month: "Oct", close: {High:45.77,Low:12.13}, open:45.19},
        {month: "Nov", close: {High:46.06,Low:10.45}, open:15.59},
    ];

    private function dataFunc(series:Series, item:Object, fieldName:String):Object {
        trace("fieldName: " + fieldName);
        if(fieldName == "yValue" && series.id=="highClose")
            return(item.close.High);
        else if(fieldName == "yValue" && series.id=="lowClose")
            return(item.close.Low);
        else if(fieldName == "xValue")
            return(item.month);
        else
            return null;
      }
    private function catFunc(axis:AxisBase, item:Object):Object {
        for (var s:String in item) {
            trace(s + ":" + item[s]);
        }
      
        return(item.month);
    }
   ]]></fx:Script>

    <s:layout>
        <s:VerticalLayout/>
    </s:layout>

  <s:Panel title="ColumnChart">
        <s:layout>
            <s:VerticalLayout/>
        </s:layout>
        <mx:ColumnChart id="chart" 
            dataProvider="{SMITH}" 
            showDataTips="true" 
            width="100%" 
            height="100%">
            <mx:horizontalAxis>
                <!-- The dataFunction replaces "categoryField='month'. -->
                <mx:CategoryAxis id="h1" dataFunction="catFunc"/>
            </mx:horizontalAxis>
            <mx:series>
                <!-- The dataFunction replaces yField value, which cannot drill 
                down into an object (close.High is not valid). -->
                <mx:ColumnSeries id="highClose" 
                    displayName="Close (High)" 
                    dataFunction="dataFunc"/>

                <!-- The dataFunction replaces yField value, which cannot drill 
                down into an object (close.Low is not valid). -->
                <mx:ColumnSeries id="lowClose" 
                    displayName="Close (Low)" 
                    dataFunction="dataFunc"/>
            </mx:series>
        </mx:ColumnChart>
    </s:Panel>
</s:Application>

The executing SWF file for the previous example is shown below:

Changing chart data at run time

Using ActionScript, you can change a charting control’s data at run time by using a variety of methods.

You can change a chart or a series data provider. To do this with an HTTPService as the source of your data provider, you change the URL and then call the HTTPService control’s send() method again.

The following example changes the data provider when the user selects a new ticker symbol from the ComboBox control:
<?xml version="1.0"?>
<!-- charts/ChangeSrvDataProvider.mxml -->
<s:Application 
    xmlns:fx="http://ns.adobe.com/mxml/2009" 
    xmlns:mx="library://ns.adobe.com/flex/mx" 
    xmlns:s="library://ns.adobe.com/flex/spark" 
    creationComplete="srv.send()"
    height="600">

    <fx:Declarations>
        <!-- View source of the following page to see the structure of the data that Flex uses in this example. -->
        <mx:HTTPService id="srv" url="http://aspexamples.adobe.com/chart_examples/stocks-xml.aspx"/>
        <!-- To see data in an HTML table, go to http://aspexamples.adobe.com/chart_examples/stocks.aspx -->  
    </fx:Declarations>

    <fx:Script><![CDATA[
        public function changeDataProvider(event:Event):void {
            srv.url = "http://aspexamples.adobe.com/chart_examples/stocks-xml.aspx" +
                "?" + "tickerSymbol=" + event.currentTarget.selectedItem;
                srv.send();
        }
    ]]></fx:Script>

    <s:layout>
        <s:VerticalLayout/>
    </s:layout>

    <s:Panel title="Column Chart">
        <s:layout>
            <s:VerticalLayout/>
        </s:layout>
        <mx:ColumnChart id="myChart" dataProvider="{srv.lastResult.data.result}" showDataTips="true">
            <mx:horizontalAxis>
                <mx:DateTimeAxis dataUnits="days"/>
            </mx:horizontalAxis>
            <mx:series>
                <mx:ColumnSeries 
                    yField="close" xField="date"
                    displayName="Closing Price of {cb1.selectedItem}"/>
            </mx:series>
        </mx:ColumnChart>
        <mx:Legend dataProvider="{myChart}"/>
    </s:Panel>

    <s:ComboBox id="cb1" change="changeDataProvider(event)">
        <s:ArrayCollection>
            <fx:String>FRED</fx:String>
            <fx:String>STRK</fx:String>
            <fx:String>FE</fx:String>
        </s:ArrayCollection>
    </s:ComboBox>
</s:Application>

The executing SWF file for the previous example is shown below:

The following example defines the data providers as ArrayCollections. It then binds the data provider to a local variable. The example then toggles the chart’s data provider using that local variable when the user clicks the button.

<?xml version="1.0"?>
<!-- charts/ChangeDataProvider.mxml -->
<s:Application 
    xmlns:fx="http://ns.adobe.com/mxml/2009" 
    xmlns:mx="library://ns.adobe.com/flex/mx" 
    xmlns:s="library://ns.adobe.com/flex/spark"
    height="600">

    <fx:Script>
        <![CDATA[
        import mx.collections.ArrayCollection;

        [Bindable]
        public var expenses:ArrayCollection = new ArrayCollection([
            {Month:"Jan", Profit:2000, Expenses:1500, Amount:450},
            {Month:"Feb", Profit:1000, Expenses:200, Amount:600},
            {Month:"Mar", Profit:1500, Expenses:500, Amount:300}
        ]);

        [Bindable]
        public var expenses2:ArrayCollection = new ArrayCollection([
            {Month:"Jan", Profit:2400, Expenses:1509, Amount:950},
            {Month:"Feb", Profit:3000, Expenses:2200, Amount:400},
            {Month:"Mar", Profit:3500, Expenses:1200, Amount:200}
        ]);

        [Bindable]
        public var dp:ArrayCollection = expenses;

        public function changeDataProvider():void {
            if (dp==expenses) {
                dp = expenses2;
            } else {
                dp = expenses;
            }
        }
        ]]>
    </fx:Script>

    <s:layout>
        <s:VerticalLayout/>
    </s:layout>

    <s:Panel title="Line Chart">
        <s:layout>
            <s:VerticalLayout/>
        </s:layout>
        <mx:LineChart id="myChart" dataProvider="{dp}" showDataTips="true">
            <mx:horizontalAxis>
                <mx:CategoryAxis 
                    dataProvider="{dp}" 
                    categoryField="Month"/>
            </mx:horizontalAxis>
            <mx:series>
                <mx:LineSeries 
                    yField="Profit" 
                    displayName="Profit"/>
                <mx:LineSeries 
                    yField="Expenses" 
                    displayName="Expenses"/>
                <mx:LineSeries 
                    yField="Amount" 
                    displayName="Amount"/>
            </mx:series>
        </mx:LineChart>
        <mx:Legend dataProvider="{myChart}"/>
    </s:Panel>

    <s:Button id="b1"
        label="Change Data Provider" 
        click="changeDataProvider()"/>
</s:Application>

The executing SWF file for the previous example is shown below:

You can add or remove a data point from a series in ActionScript. The following example adds an item to the existing data provider when the user clicks the button:

<?xml version="1.0"?>
<!-- charts/AddDataItem.mxml -->
<s:Application 
    xmlns:fx="http://ns.adobe.com/mxml/2009" 
    xmlns:mx="library://ns.adobe.com/flex/mx" 
    xmlns:s="library://ns.adobe.com/flex/spark" 
    xmlns="*" height="600" width="700">

    <s:layout>
        <s:VerticalLayout/>
    </s:layout>
    
    <fx:Script><![CDATA[
        import mx.collections.ArrayCollection;
        [Bindable]
        public var dpac:ArrayCollection =  new ArrayCollection([
           {A:2000},
           {A:3000},
           {A:4000},
           {A:4000},
           {A:3000},
           {A:2000},
           {A:6000}
        ]);
    
        public function addDataItem():void {
            var o:Object = {"A":2000};
            dpac.addItem(o);
        }
        
        private function removeItem():void {
            var i:int = dpac.length;
            if (i > 0) {
                dpac.removeItemAt(i - 1);
            }
        }
    ]]></fx:Script>
    
  <s:Panel title="Column Chart">
    <s:layout>
        <s:VerticalLayout/>
    </s:layout>
     <mx:ColumnChart id="myChart" 
        showDataTips="true"
        height="400" 
        width="600" 
        dataProvider="{dpac}">
        <mx:series> 
            <mx:ColumnSeries yField="A" displayName="Series 1"/>
        </mx:series>
     </mx:ColumnChart>  
     <mx:Legend dataProvider="{myChart}"/>
  </s:Panel>
  <s:HGroup>
      <s:Button label="Add Data Item" click="addDataItem();"/>
      <s:Button label="Remove Data Item" click="removeItem();"/>
  </s:HGroup>
</s:Application>

The executing SWF file for the previous example is shown below:

You can also change the fields of a series to change chart data at run time. You do this by changing the value of the data provider field (such as xField or yField) on the series object. To get a reference to the series, you use the series’ id property or the chart control’s series index. The following example toggles the data series when the user clicks on the Change Series button:

<?xml version="1.0"?>
<!-- charts/ToggleSeries.mxml -->
<s:Application 
    xmlns:fx="http://ns.adobe.com/mxml/2009" 
    xmlns:mx="library://ns.adobe.com/flex/mx" 
    xmlns:s="library://ns.adobe.com/flex/spark" 
    initialize="initApp();"
    height="600">

  <fx:Script><![CDATA[
     [Bindable]
     public var dataSet:Array;
     public var myStates:Array =
        ["Wisconsin","Ohio","Arizona","Penn"];
     public var curSeries:String;
     public function initApp():void {
        var newData:Array = [];
        for(var i:int=0;i<myStates.length;i++) {
           newData[i] = {
             Apples: Math.floor(Math.random()*150),
             Oranges: Math.floor(Math.random()*150),
             myState: myStates[i]
           }
        }
        dataSet = newData;
        curSeries = "apples";
     }
     public function changeData():void {
        var series:Object = myChart.series[0];
        if (curSeries == "apples") {
           curSeries="oranges";
           series.yField = "Oranges";
           series.displayName = "Oranges";
           series.setStyle("fill",0xFF9933);
        } else {
           curSeries="apples";
           series.yField = "Apples";
           series.displayName = "Apples";
           series.setStyle("fill",0xFF0000);
        }
     }
  ]]></fx:Script>

    <s:layout>
        <s:VerticalLayout/>
    </s:layout>

    <s:Panel title="Column Chart">
        <s:layout>
            <s:VerticalLayout/>
        </s:layout>
        <mx:ColumnChart id="myChart"
            dataProvider="{dataSet}" showDataTips="true">
            <mx:horizontalAxis>
                <mx:CategoryAxis dataProvider="{dataSet}"
                    categoryField="myState"/>
            </mx:horizontalAxis>
            <mx:series>
                <mx:ColumnSeries yField="Apples" displayName="Apples">
                    <mx:fill>
                        <mx:SolidColor color="0xFF0000"/>
                    </mx:fill>
                </mx:ColumnSeries>
            </mx:series>
        </mx:ColumnChart>
        <mx:Legend dataProvider="{myChart}"/>
    </s:Panel>

    <s:Button id="b1" label="Toggle Series" click="changeData()"/>

</s:Application>

The executing SWF file for the previous example is shown below:

You can take advantage of data binding to make your chart reflect data changes in real time. The following example uses a Timer to define the intervals at which it checks for new data. Because the chart’s data provider is bound to an ArrayCollection, whenever a new data point is added to the collection, the chart is automatically updated.

<?xml version="1.0"?>
<!-- charts/WatchingCollections.mxml -->
<s:Application 
    xmlns:fx="http://ns.adobe.com/mxml/2009" 
    xmlns:mx="library://ns.adobe.com/flex/mx" 
    xmlns:s="library://ns.adobe.com/flex/spark" 
    initialize="initData();"
    height="600">

    <fx:Declarations>
        <mx:SeriesInterpolate id="interp"
            elementOffset="0"
            duration="300"
            minimumElementDuration="0"
        />
    </fx:Declarations>
    
    <fx:Script><![CDATA[
        import mx.collections.ArrayCollection;

        [Bindable]
        public var dataSet:ArrayCollection;

        [Bindable]
        public var revenue:Number = 100;

        private var t:Timer;

        private function initData():void {
            dataSet = new ArrayCollection();
            t = new Timer(500);     
        }   

        private function startApp():void {
            t.addEventListener(TimerEvent.TIMER, addData);
            t.start();
        }

        private function addData(e:Event):void {
            /* Add a maximum of 100 data points before user has to click
               the Start button again. */
            if (dataSet.length > 100) {
                stopApp();
            }

            dataSet.addItem( { revenue: revenue } );
            revenue += Math.random() * 10 - 5;          
        }
        
        private function stopApp():void {
            t.stop();
            t.removeEventListener(TimerEvent.TIMER, addData);        
        }
    ]]></fx:Script>

    <s:layout>
        <s:VerticalLayout/>
    </s:layout>

    <s:Panel title="Line Chart">
         <s:layout>
             <s:HorizontalLayout/>
         </s:layout>
        <mx:LineChart id="myChart" dataProvider="{dataSet}">
            <mx:series>
                <mx:LineSeries 
                    yField="revenue" 
                    showDataEffect="{interp}"
                    displayName="Revenue"/>
            </mx:series>
            <mx:horizontalAxis>
                <mx:LinearAxis autoAdjust="false"/>
            </mx:horizontalAxis>
        </mx:LineChart>        
        <mx:Legend dataProvider="{myChart}"/>
    </s:Panel>

    <s:HGroup>
        <s:Button id="b1" label="Start" click="startApp()"/>
        <s:Button id="b2" label="Stop" click="stopApp()"/>
    </s:HGroup>

</s:Application>

The executing SWF file for the previous example is shown below:

You can also use system values to update charts at run time. The following example tracks the value of the totalMemory property in a LineChart control in real time:

<?xml version="1.0"?>
<!-- charts/MemoryGraph.mxml -->
<s:Application 
    xmlns:fx="http://ns.adobe.com/mxml/2009" 
    xmlns:mx="library://ns.adobe.com/flex/mx" 
    xmlns:s="library://ns.adobe.com/flex/spark" 
    initialize="initTimer()"
    height="600">

  <fx:Script><![CDATA[
      import flash.utils.Timer;
      import flash.events.TimerEvent;
      import mx.collections.ArrayCollection;

      [Bindable]
      public var memoryUsage:ArrayCollection = new ArrayCollection();

        public function initTimer():void {
           /* The first parameter in the Timer constructor
              is the interval, in milliseconds. The second
              parameter is how many times to run (0 is 
              infinity). */
           var myTimer:Timer = new Timer(1000, 0);

           /* Add the listener for the timer event. */
           myTimer.addEventListener("timer", timerHandler);
           myTimer.start();
        }

        public function timerHandler(event:TimerEvent):void {
           var o:Object = new Object();

           /* Get the number of milliseconds since Flash 
              Player started. */
           o.time = getTimer();

           /* Get the total memory Flash Player is using. */
           o.memory = flash.system.System.totalMemory;

           /* Add new object to the ArrayCollection, which 
              is bound to the chart's data provider. */
           memoryUsage.addItem(o);
        }
  ]]></fx:Script>

    <s:layout>
        <s:VerticalLayout/>
    </s:layout>

    <s:Panel id="p1" title="Memory Usage">
        <s:layout>
            <s:VerticalLayout/>
        </s:layout>
        
        <mx:LineChart id="chart" 
            dataProvider="{memoryUsage}" 
            showDataTips="true">
            <mx:horizontalAxis>
                <mx:LinearAxis/>
            </mx:horizontalAxis>

            <mx:verticalAxis>
                <mx:LinearAxis minimum="5000000"/>
            </mx:verticalAxis>
            <mx:series>
                <fx:Array>
                    <mx:LineSeries yField="memory"/>
                </fx:Array>
            </mx:series>
        </mx:LineChart>
    </s:Panel>        
</s:Application>

The executing SWF file for the previous example is shown below: