What does this this ActionScript syntax mean? ( Syntax for returning Objects Inline ) - apache-flex

I am a Java programmer and need to work on a Flex/ActionScript project right now. I got an example of using ITreeDataDesriptor from Flex 3 Cookbook, but there is one line of actionscript code that's hard for me to understand. I appreciate if someone could explain this a little further.
public function getData(node:Object, model:Object=null):Object
{
if (node is Office) {
return {children:{label:node.name, label:node.address}};
}
}
The part that I didn't understand was "{children:{label:node.name, label:node.address}}". Office is simply a value object that contains two String properties: name and address.

The following return expression (modified from the question) ...
return {children:{label:node.name, body:node.address}}
... is functionally equivalent to this code ...
var obj:Object = new Object();
obj.children = new Object();
obj.children.label = node.name;
obj.children.body = node.address;
return obj;
The anonymous object returned in the question code complicates matters because it defines a property twice. In that case, the first declaration is used, and the subsequent one(s) are ignored. No compile-time or runtime error is thrown.

I think in Java you would call that a map or an associative array. In Javascript and Actionscript you can say this to create an object with certain properties:
var myobject = {
'prop1': 100,
'prop2': {
'a': 1
}
}
trace( myobject.prop1 ); // 100
trace( myobject.prop2.a ); // 1
In your example it's just returned as a nameless object.

return {children:{label:node.name, label:node.address}};
Means you are returning a new Object. The {} are the Object's constructor, and in this case its an Anonymous object.

Thank you both for the quick response. So if I understand your explanations correctly, the return statement is returning an anonymous object, and this object has only one property named "children", which is again an associative array - ok, here is the part I don't quite understand still, it seems that both properties in this array are named "label", is this allowed?

Related

How to initialise an empty dictionary that contain objects in Swift

I'm trying to set up a class that has a dictionary with an int and my own object. On init I do not have anything to put in this dictionary.
class Menu
{
var emptyDic = Dictionary<String, String>()
var menuItem: Dictionary<Int,MenuItem>()
init()
{
//init object code
}
}
The emptyDic variable (which I got from StackOverflow) works fine, but I get an error consecutive declarations on a line must be separated by a ; if I mirror the same syntax for my menuItem dictionary. If I remove the () it complains that self.menuItem is not initialised.
I've not seen much written about dictionaries with other types other than strings. Is this a case for making it an optional or am I missing something more obvious?
Thanks
Andrew
You didn't copy the syntax. ':' and '=' are not equivalent. In this case, one specifies a type while the other specifies initialization.
Try:
var menuItem = Dictionary<Int,MenuItem>()

Image to Object with as3

I'm trying to convert an image in my assets folder
"./assets/image1.png"
to type Object. It needs to be Object because that's what the function I'm using it in is expecting.
Any ideas what would be the simplest way to do this?
Do you mean something like :
[Embed(source="assets/logo.jpg")]
private var logo:Class;
private function init(e:Event):void
{
this.displayImage(logo as Object);
}
private function displayImage(img:Object):void
{
//Assuming you have an image control on stage with an instance
//name of "myImage"
myImage.source = img;
}
If the function you are passing the image to is expecting an Object object, you can in pass anything, it won't reject it. That doesn't mean the function will work correctly, though. Any value will be an Object (except for undefined, which will be accepted but coerced to null and maybe some other strange cases).
So, assuming you didn't write the function yourself, do you have any doc that describes what it expects? Or maybe you have the source code for it?. Otherwise, if the only thing you know about what this function expects is that the parameter must be of type Object... you're in trouble, I think.
Why don't you create a new Object containing the information about the image... including the path.
var obj:Object = new Object();
obj.path = "/assets/image.jpg";
obj.height = 32;
obj.width = 32;
trace(obj.path);
// or, if Flex
Alert.show(obj.path);
And then just pass the new Object into the function and access it like I have above.

How to know if an object is dynamic in AS3

In Action Script 3, you can write a class that defines a dynamic object (MovieClip and Object are two examples), this objects can be modified in run-time. What I want to know if is there some way (in run-time, of course) to know if certain object is dynamic or not.
PS: Without making something like this:
function isDynamic(object) {
try {
object.newProperty = 'someValue'
} catch (e) {
return false
}
return true
}
CookieOfFortune has the right idea, but unfortunately the code itself has problems, isDynamic is an attribute, and the returned value will be a XMLList with a value of a String that reflects a true or false value, not a child node that directly returns a Boolean. It should look more like this:
function isDynamic(object) : Boolean
{
var type:XML = describeType(object);
return type.#isDynamic.toString() == "true";
}
Be careful!
Anytime you want to use the describeType() function, please please please use the variation:
import mx.utils.DescribeTypeCache;
var typeDesc:XML = DescribeTypeCache.describeType(object).typeDescription;
Performance of making repeated calls to the runtime reflective machinery will absolutely suck. That's why Adobe invented the DescribeTypeCache class.
You can use describeType from flash.utils to describe the object in XML form. Here's the reference to the API: flash.utils.describeType
function isDynamic(object) {
var type:XML = describeType(object);
if (type.#isDynamic == "true") return true;
return false;
}
This is a very old post, but I'll add an option for those future searchers.
AS3 has a built in way of doing this:
mx.utils.ObjectUtil.isDynamicObject(yourObject);
Read more about it here.

flex 3 webservice results issue

im having trouble with the result of a webservice call. When the result comes in and kicks off the resultHandler function i set a break point so i can examine the result. I can see that there are 0 records in the array collection however i can see content so im assuming that the zero is just referring to the first index of the array
the problem happens when i try assign the value to an array collection as follows;
public function resultHandler(event:ResultEvent):void{
var result:ArrayCollection = event.result as ArrayCollection;
the result of this operation is a result var with the value of null. Can anyone explain what could be happening here? thanks a lot
another thing i just noticed is that the result type is mx.utils.ObjectProxy, im expecting an array
If the webservice returns just one element, it will be deserialized as ObjectProxy. You will have to manually convert it into an array.
I'd normally do this after a WS call:
if (event.result is ArrayCollection) {
result = event.result;
}
else {
result = new ArrayCollection([event.result]);
}
Chetan is right -- the cast operation to ArrayCollection is failing, because the source object is not an ArrayCollection. Try this instead:
public function resultHandler(event:ResultEvent):void
{
var ac:ArrayCollection = new ArrayCollection([event.result])
// ...
}
The "as" operator will return null in situations where an exception would occur at runtime -- in your case, casting from ObjectProxy to ArrayCollection. If instead you pass event.result as the sole member of an array (by surrounding it with []), your ArrayCollection will be constructed properly, and you'll be able to retrieve the object normally:
var o:Object = ac.getItemAt(0) as Object;
trace(o.yourObjectProperty.toString());
Hope it helps!
0 records in the array is the length of the array, that actually means 0. If you have something in index 0 of an array, that array has a length of at least 1. It looks like you aren't getting any data back, not even and empty array collection.
The problem in my opinion is that you cannot cast event.result as an array collection, but you have to cast it as an array.
The best practice in this is having a getter and a setter:
private var _acLocation:ArrayCollection=new ArrayCollection;
public function set acLocation(acLocation:ArrayCollection):void{
_acLocation=acLocation;
//do this if you want for exaple to assign the arraycollection to a datagrid dataprovider
dgMyDataGrid.dataProvider=_acLocation;
}
public function get acLocation():ArrayCollection{
return _acLocation;
}
Then in the result handler function of a service call, code
acLocation=new ArrayCollection(event.result as Array);
Hope it helps

how to refactor code inside curly braces in flex

Data binding in ActionScript is really cool. But what if I want to refactor a big switch or if statement inside the curly braces into a function, for example:
{person.gender == 'male' ? 'Mr.' : 'Ms.'}
into:
{salutation(person)}
The compiler doesn't let me do that. I know about properties and I could write getters and setters on the person object. But since I am using inlined JSON objects now that's not convenient(I think). What are other good ways to refactor this code?
To answer Matt's comment. The data type of person is just plain Object. It was decoded from JSON format coming from a service call.
You'll need to make the Person class (assuming you have one) bindable in order for this to work.
However, since you are saying you're using JSON objects, I'm assuming you just have anonymous objects that were parsed from a JSON string. In that case, I'm pretty sure that won't work. You'll need to create a strongly typed object that has bindable properties.
Just FYI: to avoid having to write custom JSON parsers for every object you want to create, you can create strong typed objects from vanilla objects using a bytearray trick:
public static function toInstance( object:Object, clazz:Class ):* {
var bytes:ByteArray = new ByteArray();
bytes.objectEncoding = ObjectEncoding.AMF0;
// Find the objects and byetArray.writeObject them, adding in the
// class configuration variable name -- essentially, we're constructing
// and AMF packet here that contains the class information so that
// we can simplly byteArray.readObject the sucker for the translation
// Write out the bytes of the original object
var objBytes:ByteArray = new ByteArray();
objBytes.objectEncoding = ObjectEncoding.AMF0;
objBytes.writeObject( object );
// Register all of the classes so they can be decoded via AMF
var typeInfo:XML = describeType( clazz );
var fullyQualifiedName:String = typeInfo.#name.toString().replace( /::/, "." );
registerClassAlias( fullyQualifiedName, clazz );
// Write the new object information starting with the class information
var len:int = fullyQualifiedName.length;
bytes.writeByte( 0x10 ); // 0x10 is AMF0 for "typed object (class instance)"
bytes.writeUTF( fullyQualifiedName );
// After the class name is set up, write the rest of the object
bytes.writeBytes( objBytes, 1 );
// Read in the object with the class property added and return that
bytes.position = 0;
// This generates some ReferenceErrors of the object being passed in
// has properties that aren't in the class instance, and generates TypeErrors
// when property values cannot be converted to correct values (such as false
// being the value, when it needs to be a Date instead). However, these
// errors are not thrown at runtime (and only appear in trace ouput when
// debugging), so a try/catch block isn't necessary. I'm not sure if this
// classifies as a bug or not... but I wanted to explain why if you debug
// you might seem some TypeError or ReferenceError items appear.
var result:* = bytes.readObject();
return result;
}

Resources