Hello,
I am having trouble binding a LineChart to XML data via HTTPService object.
Here is my code:
<mx:Panel
xmlns:mx="http://www.adobe.com/2006/mxml"
xmlns:ui="flex.utils.ui.*"
xmlns:charts="flex.utils.ui.charts.*"
layout="vertical" horizontalAlign="center" verticalGap="2" paddingBottom="0" paddingTop="10" xmlns:local="*"
creationComplete="getChartDataSrv.send();"
>
<mx:HTTPService id="getChartDataSrv" result="onResult(event)" url="http://localhost:8060/BusinessServiceLayer/DataService.asmx/GetDeviceDatasetsByDateGranular?xxxxxxxx" />
<mx:Script>
<![CDATA[
import flex.utils.ui.events.CheckBoxLegendItemChangedEvent;
import mx.collections.ArrayCollection;
import mx.rpc.events.ResultEvent;
import mx.controls.Alert;
[Bindable]
private var deviceData:ArrayCollection;
private var deviceData2:ArrayCollection;
private function legendItemChanged(event:CheckBoxLegendItemChangedEvent):void {
var txt:String = "legendItemChanged: " + event.legendItem.label +
" [" + (event.legendItemSelected ? "selected]" : "not selected]");
trace(txt);
changeLabel.text = txt;
// update the vertical axis minimum/maximum values to ignore the hidden series
if (updateMinMaxCB.selected) {
updateVerticalAxisMinMax();
}
}
private function updateVerticalAxisMinMax():void {
var max:Number = 0;
var min:Number = 0;
var count:int = 0;
for each (var series:LineSeries in linechart.series) {
if (series.visible) {
// contains LineSeriesItem objects
var items:Array = series.items;
// Get the min and max y values for each item from the yNumber property
var minMax:Array = getMinMax(items, "yNumber");
min = Math.min(min, minMax[0]);
max = Math.max(max, minMax[1]);
count++;
}
}
if (count > 0) {
// change the min/max to the next interval
max = Math.ceil(max / vAxis.interval) * vAxis.interval;
min = Math.floor(min / vAxis.interval) * vAxis.interval;
//set the new minimum/maxmimum values
vAxis.maximum = max;
vAxis.minimum = min;
}
}
private function getMinMax(items:Array, field:String = null):Array {
var min:Number = 0;
var max:Number = 0;
for each (var item:* in items) {
if (item) {
var num:Number = NaN;
if (field && item.hasOwnProperty(field)) {
num = Number(item[field]);
} else {
num = Number(item);
}
if (!isNaN(num)) {
max = Math.max(max, num);
min = Math.min(min, num);
}
}
}
return [ min, max ];
}
private function updateMinMaxCBClicked(event:Event):void {
if (updateMinMaxCB.selected) {
updateVerticalAxisMinMax();
} else {
// reset the minimum & maximum values so that the axis will calculate them properly
vAxis.minimum = NaN;
vAxis.maximum = NaN;
}
}
private function swapDataProvider():void {
if (changeDataBtn.selected) {
linechart.dataProvider = deviceData2;
} else {
linechart.dataProvider = deviceData;
}
// validate first, then update the vertical axis min/max values
linechart.validateNow();
if (updateMinMaxCB.selected) {
updateVerticalAxisMinMax();
}
}
private function onResult(evt:ResultEvent):void {
linechart.dataProvider = evt.result.ArrayOfDAIX.DAIX;
linechart.invalidateDisplayList();
}
]]>
</mx:Script>
<mx:Stroke id = "s1" color="haloGreen" weight="2"/>
<mx:Stroke id = "s2" color="haloOrange" weight="2"/>
<mx:Stroke id = "s3" color="haloBlue" weight="2"/>
<mx:Stroke id = "s4" color="red" weight="2"/>
<mx:Stroke id = "s5" color="yellow" weight="2"/>
<mx:Label text="LineChart with CheckBox Legend" color="0xffffff"
fontSize="14" textDecoration="underline" fontWeight="bold"/>
<mx:VBox enabled="true" paddingTop="10" paddingRight="5" paddingBottom="10" paddingLeft="5"
backgroundColor="white" width="100%" height="100%" horizontalAlign="center">
<mx:LineChart id="linechart" color="#FDFDFD" width="100%" height="100%"
showDataTips="true" dataProvider="{getChartDataSrv.lastResult.ArrayOfDAIX.DAIX}">
<mx:horizontalAxis>
<mx:CategoryAxis categoryField="w"/>
</mx:horizontalAxis>
<mx:verticalAxis>
<mx:LinearAxis id="vAxis"/>
</mx:verticalAxis>
<mx:series>
<mx:LineSeries yField="v1" form="curve" displayName="Column 1" lineStroke="{s1}"/>
<mx:LineSeries yField="v2" form="curve" displayName="Column 2" lineStroke="{s2}"/>
<mx:LineSeries yField="v3" form="curve" displayName="Column 3" lineStroke="{s3}"/>
<mx:LineSeries yField="v4" form="curve" displayName="Column 4" lineStroke="{s4}"/>
<mx:LineSeries yField="v5" form="curve" displayName="Column 5" lineStroke="{s5}"/>
</mx:series>
</mx:LineChart>
<ui:TitledBorderBox title="Legend" borderColor="#666666" id="legendBox">
<charts:CheckBoxLegend dataProvider="{linechart}" color="white" direction="vertical"
toggleChartSeries="true" change="legendItemChanged(event)" id="legend"/>
</ui:TitledBorderBox>
</mx:VBox>
<mx:Label id="changeLabel" color="#ffffff"/>
<mx:HBox horizontalAlign="left">
<mx:CheckBox id="cb" selected="true" label="{cb.selected ? 'Select None' : 'Select All'}"
click="legend.selectAllOrNone(cb.selected)"/>
<mx:Spacer width="10" height="10"/>
<mx:CheckBox label="Update Vertical Axis Min/Max?" id="updateMinMaxCB"
toolTip="Check this box to update the vertical axis minimum and maximum values when the legend items change"
change="updateMinMaxCBClicked(event)"/>
</mx:HBox>
<mx:Button label="Change Data" toggle="true" id="changeDataBtn" click="swapDataProvider()"
toolTip="Change the data provider to a different set of values"/>
</mx:Panel>
Originally I had written a static array of data, to get this example working. It worked fine, until I made the HTTPService object and appropriate WebService calls.
When I debug this code, I can see that my HTTPService object is returning the array correctly, it has 96 items, which is desired.
The problem is, the LineChart graph is already rendered to the browser, and I cannot get my data into my LineChart. The static array worked fine but I am at a loss on why it will not work with my ResultEvent and HTTPService object.
Why can I not bind my Chart within my ResultEvent, or directly, with the result object? Even if I explicitly set the dataprovider of "linechart" (in the ResultEvent method) it does not update the LineChart data.
Also, if I use "linechart.invalidateDisplayList();", it too does not populate or redraw my LineChart. Is that because it's contained within a Panel?
Any ideas? Also, take note that this is all happening within a Panel and not within an Application. I cannot use Application tags on this component, so I am fairly confused about this. Why does the LineChart render first, and then my HTTPService produce the data the Chart will not use?