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
Related
I'm new to Actionscript programming. I'm trying to figure out what is the best way to return multiple variables, each having a different data type, from a function. For example, if a function needs to return variable aa ( a string) and variable bb (a number).
The function I'm using just crunches a lot of math, and doesn't relate to an object in a GUI. One method I got from a Google search used an Object, but as (I think) this requires me to create a class, I wondered if there was a simpler way. Since an array can hold elements of different data types, perhaps this is a simpler approach (?).
Here's an example mxml and AS3 file taken from "Flash Builder 4 and Flex 4 Bible" by David Gassner.
file: Calculator.mxml
<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
xmlns:components="components.*">
<fx:Script source="calculator.as"/>
<s:Panel title="Calculator" horizontalCenter="0" top="20">
<s:layout>
<s:VerticalLayout horizontalAlign="center"/>
</s:layout>
<mx:Form>
<components:ButtonTile id="input"
select="selectHandler(event)"
calculate="calculateHandler(event)"/>
<mx:FormItem label="Entry:">
<s:TextInput text="{currentInput}" editable="false" width="80"/>
</mx:FormItem>
<mx:FormItem label="Total:">
<s:TextInput text="{currentResult}" editable="false" width="80"/>
</mx:FormItem>
</mx:Form>
file: calculator.as
//ActionScript code for Calculator.mxml
[Bindable]
private var currentResult:Number=0;
[Bindable]
private var currentInput:String="";
private function calculateHandler(event:Event):void
{
currentResult += Number(currentInput);
currentInput="";
}
private function selectHandler(event:TextEvent):void
{
currentInput += event.text;
}
Could someone illustrate how to modify one of the functions in calculator.as, just as an example how to return two values, where one is a number and the other a string? Is there an obvious best-way to do this, or, what would be the pros/cons of different approaches? Thanks in advance!
You could just simply return an Object which is dynamic and thus lets you define values on the fly, like this:
return {something: "string", another: 18};
Or:
var obj:Object = {};
obj.something = "string";
obj.another = 18;
return obj;
But in my opinion this is really poor practice (especially if your function is to return the same sets of information with new values).
I'd take this route:
You can create your own class that holds various properties. From there you can return an instance of this object with the properties defined as you wish.
Example:
This would be in an external file called CollisionData.as
package
{
public class CollisionData
{
public var x:Number = 0; // X coordinate of the collision
public var y:Number = 0; // Y coordinate of the collision
public var angle:Number = 0; // Collision angle
}
}
And your function could be:
function calculate():CollisionData
{
var col:CollisionData = new CollisionData();
// determine collision details
col.x = 115;
col.y = 62;
col.angle = 0.345;
return col;
}
Then you can create your own collision data based off the result:
var myCollision:CollisionData = calculate();
And fetch the details:
trace(
myCollision.x,
myCollision.y,
myCollision.angle
);
No need to create class, this should work for you:
public function calculate():Object
{
return {valueA: "string", valueB: 1};
}
I am trying to have a random color to be picked as default for my ColorPicker. I am running my script on the creation complete of my Panel.
The script code is given below:
public var someColor:String = new String();
private function init():void{
var myColor:Number = Math.round( Math.random()*0xFFFFFF );
someColor = "0x"+myColor.toString(16);
}
and the code for the ColorPicker is:
<mx:ColorPicker id="calendar_color" width="20" height="20" selectedColor="{someColor}"/>
Even though, when I see the color in the var someColor, it shows a random color every time, but the colorPicker is not displaying the color.
Please let me know, what am I doing wrong here. And how it can be fixed.
1) Why do you have someColor as String? Therefore you've got two unnececcary type conversions: from Number to String (myColor.toString(16)) and from String to uint (selectedColor="{someColor}"). Why not just write this:
[Bindable] public var someColor:uint = 0;
private function init():void{
someColor = Math.random()*0xFFFFFF;
}
2) And one more thing I also don't like - in current answer you've got actually uneccecary binding, the one that will only shoot once, and you should not forget to call init() somewhere in youre code. I'd better change it on function call:
private function getRandomColor():uint{
return Math.random()*0xFFFFFF;
}
<mx:ColorPicker id="calendar_color" width="20" height="20"
selectedColor="{getRandomColor()}"/>
Here getRandomColor() will be automatically called on ColorPicker initialization. One unavoidable type conversion (from Number to uint), no bindings, no useless property, shorter code.
That's not premature optimization, that's removing premature pessimization.
You need to add the [Bindable] metadata:
[Bindable]
public var someColor:String = new String();
I can't tell from this post but what class is
public var someColor:String = new String();
in. you will just want to verify that it can be reached through the reference you made.
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()"/>
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
First time here asking a question and still learning on how to format things better... so sorry about the format as it does not look too well.
I have started learning flex and picked up a book and tried to follow the examples in it. However, I got stuck with a problem. I have a jsp page which returns xml which basically have a list of products. I am trying to parse this xml, in other words go through products, and create Objects for each product node and store them in an ArrayCollection. The problem I believe I am having is I am not using the right way of navigating through xml.
The xml that is being returned from the server looks like this:
<?xml version="1.0" encoding="ISO-8859-1"?><result type="success">
<products>
<product>
<id>6</id>
<cat>electronics</cat>
<name>Plasma Television</name>
<desc>65 inch screen with 1080p</desc>
<price>$3000.0</price>
</product>
<product>
<id>7</id>
<cat>electronics</cat>
<name>Surround Sound Stereo</name>
<desc>7.1 surround sound receiver with wireless speakers</desc>
<price>$1000.0</price>
</product>
<product>
<id>8</id>
<cat>appliances</cat>
<name>Refrigerator</name>
<desc>Bottom drawer freezer with water and ice on the door</desc>
<price>$1200.0</price>
</product>
<product>
<id>9</id>
<cat>appliances</cat>
<name>Dishwasher</name>
<desc>Large capacity with water saver setting</desc>
<price>$500.0</price>
</product>
<product>
<id>10</id>
<cat>furniture</cat>
<name>Leather Sectional</name>
<desc>Plush leather with room for 6 people</desc>
<price>$1500.0</price>
</product>
</products></result>
And I have flex code that tries to iterate over products like following:
private function productListHandler(e:JavaFlexStoreEvent):void
{
productData = new ArrayCollection();
trace(JavaServiceHandler(e.currentTarget).response);
for each (var item:XML in JavaServiceHandler(e.currentTarget).response..product )
{
productData.addItem( {
id:item.id,
item:item.name,
price:item.price,
description:item.desc
});
}
}
with trace, I can see the xml being returned from the server. However, I cannot get inside the loop as if the xml was empty. In other words, JavaServiceHandler(e.currentTarget).response..product must be returning nothing. Can someone please help/point out what I could be doing wrong.
My JavaServiceHandler class looks like this:
package com.wiley.jfib.store.data
{
import com.wiley.jfib.store.events.JavaFlexStoreEvent;
import flash.events.Event;
import flash.events.EventDispatcher;
import flash.net.URLLoader;
import flash.net.URLRequest;
public class JavaServiceHandler extends EventDispatcher
{
public var serviceURL:String = "";
public var response:XML;
public function JavaServiceHandler()
{
}
public function callServer():void
{
if(serviceURL == "")
{
throw new Error("serviceURL is a required parameter");
return;
}
var loader:URLLoader = new URLLoader();
loader.addEventListener(Event.COMPLETE, handleResponse);
loader.load(new URLRequest(serviceURL));
// var httpService:HTTPService = new HTTPService();
// httpService.url = serviceURL;
// httpService.resultFormat = "e4x";
// httpService.addEventListener(Event.COMPLETE, handleResponse);
// httpService.send();
}
private function handleResponse(e:Event):void
{
var loader:URLLoader = URLLoader(e.currentTarget);
response = XML(loader.data);
dispatchEvent(new JavaFlexStoreEvent(JavaFlexStoreEvent.DATA_LOADED) );
// var httpService:HTTPService = HTTPService(e.currentTarget);
// response = httpService.lastResult.product;
// dispatchEvent(new JavaFlexStoreEvent(JavaFlexStoreEvent.DATA_LOADED) );
}
}
}
Even though I refer to this as mine and it is not in reality. This is from a Flex book as a code sample which does not work, go figure.
Any help is appreciated.
Thanks
john
I just tried following code:
<?xml version="1.0" encoding="utf-8"?>
<mx:WindowedApplication xmlns:mx="http://www.adobe.com/2006/mxml"
creationComplete="onComplete();">
<mx:Script>
<![CDATA[
import radekg.JavaServiceHandler;
private function onComplete():void {
var jsh:JavaServiceHandler = new JavaServiceHandler();
for each ( var node:XML in jsh.response.products.product ) {
trace( node.id.text() );
trace( node.cat.text() );
trace( node.name.text() );
trace( node.desc.text() );
trace( node.price.text() );
trace("---------------------------------------");
}
}
]]>
</mx:Script>
</mx:WindowedApplication>
And radekg/JavaServiceHandler.as which emulates your handler class:
package radekg
{
public class JavaServiceHandler
{
public var response:XML = <result type="success">
<products>
<product>
<id>6</id>
<cat>electronics</cat>
<name>Plasma Television</name>
<desc>65 inch screen with 1080p</desc>
<price>$3000.0</price>
</product>
<product>
<id>7</id>
<cat>electronics</cat>
<name>Surround Sound Stereo</name>
<desc>7.1 surround sound receiver with wireless speakers</desc>
<price>$1000.0</price>
</product>
<product>
<id>8</id>
<cat>appliances</cat>
<name>Refrigerator</name>
<desc>Bottom drawer freezer with water and ice on the door</desc>
<price>$1200.0</price>
</product>
<product>
<id>9</id>
<cat>appliances</cat>
<name>Dishwasher</name>
<desc>Large capacity with water saver setting</desc>
<price>$500.0</price>
</product>
<product>
<id>10</id>
<cat>furniture</cat>
<name>Leather Sectional</name>
<desc>Plush leather with room for 6 people</desc>
<price>$1500.0</price>
</product>
</products></result>;
}
}
And as a result I'm getting:
6
electronics
Plasma Television
65 inch screen with 1080p
$3000.0
---------------------------------------
7
electronics
Surround Sound Stereo
7.1 surround sound receiver with wireless speakers
$1000.0
---------------------------------------
8
appliances
Refrigerator
Bottom drawer freezer with water and ice on the door
$1200.0
---------------------------------------
9
appliances
Dishwasher
Large capacity with water saver setting
$500.0
---------------------------------------
10
furniture
Leather Sectional
Plush leather with room for 6 people
$1500.0
---------------------------------------
Your JavaServiceHandler.result points to the XML root tag so in other words, replace your:
for each (var item:XML in JavaServiceHandler(e.currentTarget).response.products..product )
with:
for each (var item:XML in JavaServiceHandler(e.currentTarget).response.products.product )
Hope that helps.
I'm, not exactly an XML / Flex whiz, but is this a typo?
for each (var item:XML in JavaServiceHandler(e.currentTarget).response..product )
Did you try
for each (var item:XML in JavaServiceHandler(e.currentTarget).response.result.products.product )
That's how I do it. Explicit, explicit, explicit.
Try looking at JavaServiceHandler(e.currentTarget).response with a debugger. If it IS the XML you're referring to, then your method of accessing product should work. So, it's likely that your Java backend returns not the XML you're expecting.
Try loading the same XML from a simple text file, or simply embed it into a string to make it even more simple:
[Embed (source="xmltest.xml")]
private var xmlTest:String;
And then initialize XML with a var xml:XML = new XML(xmlTest); and try trace(xml..product)
The root element in your XML is result. So you should have either
for each (var item:XML in JavaServiceHandler(e.currentTarget).response.products..product )
Yes, two dots - no typo there, or (if you know for sure you'll have only product elements):
for each (var item:XML in JavaServiceHandler(e.currentTarget).response.products.children() )
Because you didn't tidy up your XML, you mistook products element for the root, as it took some time for me to notice too. The moral of the story is: always tidy up your XML.
Assign static value for DATA_LOADED in JavaFlexStoreEvent.as
public static const DATA_LOADED:String="onDataLoaded"
I Think you are not created JAvaFlexStoreEVent Here I am Posted full class
package com.wiley.jfib.store.events
{
import flash.events.Event;
public class javaFlexStoreEvent extends Event
{
public static const DATA_LOADED:String="onDataLoaded";
public function javaFlexStoreEvent(type:String, bubbles:Boolean=false, cancelable:Boolean=false)
{
super(type, bubbles, cancelable);
}
}
}
I see that you have commented out the use of http service. If you use this object and then specify the result data type of 'OBJECT', which you can access via the static variable 'HTTPService.RESULT_FORMAT_OBJECT'. This will then automatically parse your XML into objects for you. You can then use simple dot notation to access the data rather than looping over the XML.
Once you make this change, run the application using the debugger. Breakpoint your code at the result handler code and take a look at the result data. You should see that your XML has been parsed into an ArrayCollection of ObjectPoxy objects, which you can then loop over and map to your own objects for use in your application.
The benefit here is that the internal parser will handle namespaces, and most other variations of XML you throw at it, without you having to worry about it.
You can lose some performance with large data sets, but of course that only depends on how efficient you can write your own parsing code to be.