flex fusion charts with webservice - apache-flex

I have flex project where i want to call webservice and pass values from it to the xml file to update fusion chart xml
My code is
<fx:Script>
<![CDATA[
import mx.controls.Alert;
import mx.events.FlexEvent;
import mx.rpc.events.FaultEvent;
import mx.rpc.events.ResultEvent;
public var PUENumber:String;
protected var xmlLoader:URLLoader;
[Bindable]
public var avgPUEXml:XML = new XML;
protected function init():void
{
xmlLoader = new URLLoader();
xmlLoader.addEventListener(Event.COMPLETE,setDataXML)
xmlLoader.load(new URLRequest("data/AvgPUE.xml")); //Loading xml file for the chart from the folder
};
protected function setDataXML(event:Event):void
{
avgPUEXml = XML(event.target.data);
avgPUEXml.value = PUENumber; //updating chart xml value
fw.FCDataXML = avgPUEXml.toString();
fw.FCRender();
};
protected function getDC_POWERdataResult_resultHandler(event:ResultEvent):void
{
PUENumber = getDC_POWERdataResult.lastResult; //getting value to update in xml file
init();
}
protected function bordercontainer1_creationCompleteHandler(event:FlexEvent):void
{
getDC_POWERdataResult.token = mGEMWS.getDCPUE("4","715"); //user details to get data from the method
}
]]>
</fx:Script>
<fx:Declarations>
<s:CallResponder id="getDC_POWERdataResult" result="getDC_POWERdataResult_resultHandler(event)"/>
<mgemws:MGEMWS id="mGEMWS" showBusyCursor="true"
fault="Alert.show(event.fault.faultString + '\n' + event.fault.faultDetail)"/>
</fx:Declarations>
<ns1:FusionWidgets id="fw" FCChartType="Bulb" FCDataXML="avgPUEXml" />
in the declaration am calling web service. and on creationCompelete am sending userid details to get data from webservice. now where exactly i need to call init function so that it updates xml file with values coming from web service and display the fusion widget

You don't need the 'setDataXML' handler method. Also you don't need any 'URLLoader' or 'URLRequest' in the 'init' method. FusionCharts supports XML data as well as XML path. So remove the 'setDataXML' and remove all the codes from the 'init' method and add just fw.addEventListener(FCEvent.FCRenderEvent, wgdtRendHandler);
and add below handler method -
protected function wgdtRendHandler(e:FCEvent):void{
e.target.FCSetDataURL='data/AvgPUE.xml';
e.target.removeEventHandler(FCEvent.FCRenderEvent, wgdRendHandler);
}
I think this should work for you. In case you still don't get the updated data in the chart, check the XML file in the 'init' method whether it's updated properly at that point of time.

You can call the init function when the chart finishes loading and is ready for data.
You can do this listening to FCLoadEvent or FCRenderEvent of the gauge.
Please try using :
<ns1:FusionWidgets id="fw" FCChartType="Bulb" FCDataXML="avgPUEXml" FCRenderEvent="init()"/>
or
<ns1:FusionWidgets id="fw" FCChartType="Bulb" FCDataXML="avgPUEXml" FCLoadEvent="init()"/>

Related

Retrieve Last 2 Results from Service Call in Flex AS3 PHP

I'm a Flex newbie and I've searched both StackOverflow and Google'd but can't seem to figure out this (simple) problem with Flex/ActionScript 3 Asynchronous programming. I have a PHP service (Zend) that inserts a row into the table. What I would like to do is be able to call the service twice consecultively with different row values, and get back the new IDs (primary keys) returned by the service. Then I display the new IDs as 2 Alerts.
The problem is when I can the service twice in a row, I only get an Alert.show() for the last and most recent service call. I don't know how to access the result of the first.
I recognize I can reconfigure my Flex code and PHP service to accept an array of objects and just send a single PHP service call for both and receive back an array object with the results, but I'm also trying to get a better understanding in general how AsyncToken is working and how to access old results that I need. Is each use of {serviceResult}.token overwriting my previous result?
<s:NavigatorContent xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
// ...
Here is my related code where I want to set up 2 default folders for new users "Home" and "temp":
// imports
import mx.collections.ArrayCollection;
import mx.controls.Alert;
import mx.events.CloseEvent;
import mx.events.FlexEvent;
import mx.rpc.AsyncToken;
import mx.rpc.IResponder;
import mx.rpc.events.FaultEvent;
import mx.rpc.events.ResultEvent;
import mx.rpc.remoting.mxml.RemoteObject;
import mx.rpc.Responder;
import spark.events.IndexChangeEvent;
import valueObjects.Folders;
// When the user clicks "Save" button, 2 new folders are created for a new user:
protected function pendingUserSaveButton_clickHandler(event:MouseEvent):void
{
// Create 2 initial user folders: Home and temp-taiwan
var t1Folders:Folders = new Folders();
t1Folders.users_email = tempUser.email;
t1Folders.name = t1Folders.description = "Home";
createFoldersFunction( t1Folders ); // assume returns folder ID = 100
var t2Folders:Folders = new Folders();
t2Folders.users_email = tempUser.email;
t2Folders.name = t2Folders.description = "temp";
createFoldersFunction( t2Folders ); // assume returns folder ID = 101
}
and here are my event handlers, and I want an Alert box for each new ID to pop up:
protected function createFoldersFunction(item:Folders):void
{
createFoldersResult.token = foldersService.createFolders(item);
}
protected function createFoldersResult_resultHandler(event:ResultEvent):void
{
Alert.show("Folder #" + ((event.result as int) as String) + " created");
// Currently, I only get Alert saying "Folder #101 created".
// I want to see 2 Alerts - one for #100 and another for #101
}
and here are my mx codes for callresponder and service:
<s:CallResponder id="createFoldersResult"
result="createFoldersResult_resultHandler(event)"/>
<foldersservice:FoldersService id="foldersService"
fault="Alert.show(event.fault.faultString + '\n' + event.fault.faultDetail)"
showBusyCursor="true"/>
Only '101' (the result of second service call) is triggering an Alert. Why is this?
Thank you!
Your code is overriding the token that createFoldersResult should respond to. A proper code would be:
protected function createFoldersFunction(item:Folders):void
{
var token:AsyncToken = foldersService.createFolders(item);
var responder:Responder = new Responder(createFoldersResult_resultHandler, someFaultHandler)
token.addResponder(responder);
}
another option would be set up the result handler for createFolders directly in the mxml, so your foldersservice:FoldersService would be:
<foldersservice:FoldersService id="foldersService"
fault="Alert.show(event.fault.faultString + '\n' + event.fault.faultDetail)"
showBusyCursor="true">
<mx:method name="createFolders" result="createFoldersResult_resultHandler(event)"/>
</foldersservice:FoldersService>
then you don't need createFoldersFunction, you can call foldersService.createFolders directly.

Custom component containing filterFunction problem when using multiple instances

I have a main app that is using two instances of a custom MXML DropDownList component.
I included all the logic and queries within the custom component to query MySQL and fill an ArrayCollection with the result.
In my first DropDownList, I want to show all the available currencies avilable in my database.
In the second DropDownList, I only want to show the CAD and USD currencies using a filterFunction.
I don't know why, but once the filterFunction is applied to the first element, the second act like they are sharing the same currenciesList variable (THIS IS MY PROBLEM).
[Bindable] for currenciesList is required to bind to my aSyncListView.
public for currenciesList is required in order to be used in the main app.
And no matter if my variable is public or private, I have the same bug... Please view the output at the end of this message.
The call in my main app look like :
<mx:Form>
<formElems:DropDownListCurrencies id="product_cost_price_curr"
currencyCadUsdOnly="true"/>
<formElems:DropDownListCurrencies id="product_price_curr"/>
</mx:Form>
Now my custom component :
<fx:Script>
<![CDATA[
import classes.SharedFunctions;
import mx.collections.ArrayCollection;
import mx.controls.Alert;
import mx.events.FlexEvent;
import mx.rpc.events.ResultEvent;
[Bindable]
public var currenciesList:ArrayCollection;
public var currencyCadUsdOnly:Boolean = false;
protected function dropdownlist1_creationCompleteHandler(event:FlexEvent):void
{
getAllCurrenciesResult.token = currenciesService.getAllCurrencies();
// DEBUG just to show the id of the component
trace('id:' + this.id + ' (getAllCurrencies)');
}
protected function getAllCurrenciesResult_resultHandler(event:ResultEvent):void
{
currenciesList = getAllCurrenciesResult.lastResult;
// DEBUG before filterFunction
trace('id:' + this.id + ', currencyCadUsdOnly:' + currencyCadUsdOnly + ', currenciesList.length:' + currenciesList.length + ' (BEFORE filterFunction)');
if (currencyCadUsdOnly == true) {
currenciesList.filterFunction = filterCadUsdOnly;
currenciesList.refresh();
}
// DEBUG after filterFunction
trace('id:' + this.id + ', currencyCadUsdOnly:' + currencyCadUsdOnly + ', currenciesList.length:' + currenciesList.length + ' (AFTER filterFunction)');
}
protected function filterCadUsdOnly(obj:Object):Boolean
{
return (obj.code == 'CAD' || obj.code == 'USD');
}
]]>
</fx:Script>
<fx:Declarations>
<s:CallResponder id="getAllCurrenciesResult" result="getAllCurrenciesResult_resultHandler(event)"/>
<currenciesservice:CurrenciesService id="currenciesService" fault="SharedFunctions.showError(event.fault.faultString, event.fault.faultDetail)" showBusyCursor="true"/>
</fx:Declarations>
<s:AsyncListView list="{currenciesList}"/>
Finally let's have a look at the console output. I'm expecting the ArrayList to have a length of 7 on creation of the second component... :
id:product_prices_curr (getAllCurrencies)
id:product_cost_price_curr (getAllCurrencies)
id:product_prices_curr, currencyCadUsdOnly:true, currenciesList.length:7 (BEFORE filterFunction)
id:product_prices_curr, currencyCadUsdOnly:true, currenciesList.length:2 (AFTER filterFunction)
id:product_cost_price_curr, currencyCadUsdOnly:false, currenciesList.length:2 (BEFORE filterFunction)
id:product_cost_price_curr, currencyCadUsdOnly:false, currenciesList.length:2 (AFTER filterFunction)
THANKS FOR THE HELP!
Whenever you need to have the same list in multiple places with differing filters, what you need is a ListCollectionView. That way you can apply a filter to it and you won't affect the original list. It's as easy as:
var secondList:ListCollectionView = new ListCollectionView(originalList);
And your secondList can have any filter you like without affecting the original list, with the added benefit of updating when items are added or removed from the originalList.
See here: mx.collections.ListCollectionView
Try to change your code to be the following:
if (currencyCadUsdOnly == true) {
currenciesList = new ArrayCollection(currenciesList.source);
currenciesList.filterFunction = filterCadUsdOnly;
currenciesList.refresh();
}
Hope this helps!

Is there an easy way to automatically format dates according to locale in Flex 4?

I understand that one can use local-specific ResourceBundles in combination with DateFormatters to format dates according to locale. However this is a manual process - is there an automatic way to do this or to set a default for the application?
In Java for example, all your dates will automatically appear in dd/mm/yy or mm/dd/yy format simply by setting the locale. In Flex, a default date output will always be in US format unless manually formatted otherwise. I'm looking for a way to get closer to the Java functionality.
I did this recently using flah.globalization classes:
see its very informative about getting locale etc..
http://www.adobe.com/devnet/flashplayer/articles/flash_globalization_package.html
here's my code:
remember to call init(); on creation complete !
<fx:Script>
<![CDATA[
import flash.globalization.DateTimeFormatter;
import flash.globalization.DateTimeStyle;
import flash.globalization.StringTools;
import mx.collections.ArrayCollection;
import spark.events.IndexChangeEvent;
[Bindable]
private var listColl:ArrayCollection;
private var localeList:Array = new Array("en-US", "fr-FR", "es-ES","ja-JP", "hi-IN","ru-RU");
private var country:String;
private function init():void{
// set the dp for drop down;
listColl = new ArrayCollection(localeList);
country = localeList[0];
}
private function doDateLabel(item:Date):String {
trace("input = " + item);
if(item != null) {
var locale:String = country;
if(locale != null){
var dtf:DateTimeFormatter = new DateTimeFormatter(locale);
dtf.setDateTimeStyles(DateTimeStyle.SHORT, DateTimeStyle.NONE);
/*
DateTimeSyle.MEDIUM
DateTimeSyle.LONG
*/
var shortDate:String = dtf.format(item);
trace(shortDate + " (" + dtf.getDateTimePattern() + ")");
}
}
return shortDate;
}
protected function dropDownList_changeHandler(evt:IndexChangeEvent):void {
country = countryList.selectedItem;
}
]]>
</fx:Script>
<s:HGroup width="100%" height="100%" gap="20" top="50" left="50">
Hope that's what you were after
<mx:DateField id="begin" width="200"
showToday="true"
labelFunction="doDateLabel"
parseFunction="null"/>
<s:DropDownList id="countryList"
requireSelection="true" prompt="Please select an Country"
horizontalCenter="0" top="20" dataProvider="{listColl}"
change="dropDownList_changeHandler(event);">
</s:DropDownList>
</s:HGroup>
Look at toLocaleString and toLocaleTimeString
http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/Date.html#toLocaleString()
http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/Date.html#toLocaleTimeString()
It is a feature of Flash Player 10.1 placed in flash.globalization package
The flash.globalization package in Flash Player: Cultural diversity without complexity

HTTPService Result - checking number of items with a specified name

I have a question about HTTPService and the data it returns.
Well lets consider this XML:
<PhotoGalleryData>
<Photo>
<id>1</id>
<name>Summer Vacation</name>
<description>In vacation</description>
<fullImage>originalImg/1.JPG</fullImage>
</Photo>
<Photo>
<id>2</id>
<name>Winter Vacation</name>
<description>coold</description>
<fullImage>originalImg/2.JPG</fullImage>
</Photo>
</PhotoGalleryData>
As you see i have two instances of Photo, that would be retrieved using a HTTPService, well then on the Result Event of that same HTTPService i would want him the count the amount of instances named Photo he as returned on is .lastResult.
This is a dumb question, but i can't find it anywhere in Adobe Docs.
Of course any help, hint, suggestion is greatly appreciated.
Medoix
I gotta be blind or something, because it still returns 0.
Something missing here?
MXML
<mx:HTTPService id="getData"
url="{XMLDataFileLocation}"
showBusyCursor="true"
fault="getDataFaultHandler()"
result="getDataResultHandler(event)"/>
ActionScript
import mx.controls.Alert;
import mx.rpc.events.ResultEvent;
private var xmlData:XMLList;
private var numItems:int;
private function getDataResultHandler(evt:ResultEvent):void
{
if (evt.result.PhotoGalleryData)
{
xmlData = XML(evt.result).descendants("Photo");
numItems = xmlData.length();
Alert.show('Nº '+numItems,'num de Photo');
}
}
in the http_result function you have you will be putting this data in an XMLList for an example and then you can call the xmllist.length();
private var xmlData:XMLList;
private var numItems:Integer;
private function HttpResult(evt:ResultEvent):void {
if (evt.result.PhotoGalleryData) {
xmlData = XML(evt.result).descendants("Photo");
numItems = xmlData.length();
}
}
EDIT: Do the below...
Change
<mx:HTTPService id="getData"
url="{XMLDataFileLocation}"
showBusyCursor="true"
fault="getDataFaultHandler()"
result="getDataResultHandler(event)"/>
To...
<mx:HTTPService id="getData"
url="{XMLDataFileLocation}"
resultFormat="e4x";
showBusyCursor="true"
fault="getDataFaultHandler()"
result="getDataResultHandler(event)"/>
This is working for me.
Just do the following. it will solve your probs ;)
private var xmlData:XMLList;
private var numItems:Integer;
private function HttpResult(evt:ResultEvent):void {
if (evt.result.PhotoGalleryData) {
numItems = ArrayCollection(evt.result.PhotoGalleryData.Photo).length;
}
}
RSTanvir

Adobe Air/Flex + SQLite database problem

I'm still a newbie to Adobe Air/Flex, and still fairly new with SQL.
I've downloaded this (http://coenraets.org/blog/2008/11/using-the-sqlite-database-access-api-in-air…-part-1/) code and have been looking over it and I'm trying to implement the same idea.
I think it's just something stupid. I'm using Flex Builder. I made a new desktop application project, didn't import anything.
I added a DataGrid object and bound it to an ArrayCollection:
I'm trying to make it so when the program initializes it will load data from a database if it exists, otherwise it'll create a new one.
The problem is, when the application runs, the datagrid is empty. No column headers, no data, nothing. I've tried changing a whole bunch of stuff, I've used the debugger to make sure all the functions are being called like they're supposed to. I don't know what I'm doing wrong. I've compared my code to the before mentioned code, I've looked for tutorials on Google. Anyone know what I'm doing wrong?
<?xml version="1.0" encoding="utf-8"?>
<mx:WindowedApplication xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" width="672" height="446"
applicationComplete="onFormLoaded()"
title="iRecipes">
<mx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
private var sqlConnection:SQLConnection;
[Bindable] private var recipeList:ArrayCollection;
private function onFormLoaded():void
{
sqlConnection = new SQLConnection();
openDataBase();
}
private function openDataBase():void
{
var file:File = File.userDirectory.resolvePath("recipes.db");
sqlConnection.open(file, SQLMode.CREATE);
if(!file.exists)
{
createDatabase();
}
populateRecipeList()
}
private function createDatabase():void
{
var statement:SQLStatement = new SQLStatement();
statement.sqlConnection = sqlConnection;
statement.text = "CREATE TABLE Recipes (recipeId INTEGER PRIMARY KEY AUTOINCREMENT, recipeName TEXT, authorName TEXT)";
statement.execute();
statement.text = "INSERT INTO Recipes (recipeName, authorName) VALUES (:recipeName, :authorName)";
statement.parameters[":recipeName"] = "Soup";
statement.parameters[":authorName"] = "Joel Johnson";
statement.execute();
statement.parameters[":recipeName"] = "Garbage";
statement.parameters[":authorName"] = "Bob Vila";
statement.execute();
}
private function populateRecipeList():void
{
var statement:SQLStatement = new SQLStatement();
statement.sqlConnection = sqlConnection;
statement.text = "SELECT * FROM Recipes";
statement.execute();
recipeList = new ArrayCollection(statement.getResult().data);
}
]]>
</mx:Script>
<mx:DataGrid dataProvider="{recipeList}">
</mx:DataGrid>
</mx:WindowedApplication>
I just tried this out using your code. I made a change and removed the condition as I was getting errors about the table not existing.
//if(!file.exists)
//{
createDatabase();
//}
This got the datagrid showing the correct info. I think that there is something wrong with the way you are initialising the database file. I'm having a look into it at the moment.
Try using
sqlConnection.open(file, SQLMode.CREATE);
instead, for opening the database.
Thanks Feet. With your suggestion, I believe I have figured it out. I changed the if statement to this:
if(!file.exists)
{
sqlConnection.open(file, SQLMode.CREATE);
createDatabase();
}
else
{
sqlConnection.open(file, SQLMode.UPDATE);
}
And it works great. Thanks for your help.

Resources