Getting the target when using bindable getter in flex - apache-flex

I have the following files:
model.as
clint.mxml
in clint.mxml I have the following line:
<s:Group id='clint1' x="model.locationX">
...
in the model.as I have a getter:
[bindable(event="locationXChanged"))
function get locationX () : int {
return ...
}
My problem is that I need to know within the getter locationX that the id of the object that is getting the id is clint1 (The object id in the mxml).

The result of a getter should not depend on which object it is called from. I guess your getter should not be a getter and should maybe take a clintId as argument.

You can use this to refer to the current component. You can use 'this.id' to find out the component's name. More info on id property.
However, I'm getting mixed signals from your question and the question's title. Are you asking for the id of the binding target inside the binding source? Implementing that would add dependencies to your components thus harming their ability for reuse.

Related

Dart/Polymer binding object attributes of a list

I am trying to bind to the attributes of objects in a list. The list is made observable by using toObservable. Now I bind all the elements with polymer. Works fine. If a add an object to the list the update works also fine. But there is no update if the attributes of the objects in the list is changed. How can I achieve this?
I think you miss extends Object with Observable of the class declaration and/or the #observable annotation of the property declaration as shown below:
class YourListItem extends Object with Observable {
#observable aProperty;
}
If this doesn't help please provide the code of the objects you put into the list in your question.

Dynamically chose type depending on JSON content

In an ASP.NET MVC 4 application I get a JSON response from an external server that contains an array of "fields". Each field is of an individual type and contains an array of values of that type.
I'd like to deserialize that JSON either into a DynamicObject so that I can access the indivudual value propreties or I need some kind of a child class chooser which decides which class, derived from a "ValueBase" class, is needed to access the different properties of the individual value object.
I hope you know what I mean... it's a little bit complicating.
I've already tried to deserialize it into a DynamicObject (a class that derives from DynamicObject that is). But I get error messages when accessing that object's dynamic properties in the View that the properties I'd like to display don't exist.
So how does a class that derives from DynamicObject have to look like to accept and grant access to the individual differen "value"-properties provided by the JSON code?
And if that wasn't possible or the wrong way to go, how would I have to implement a suitable type chooser class?
Thanks a lot!
I've kinda solved it myself.
Instead of directly converting the returned JSON object (a JSON array to be more precise) into a specific class I fetch it as a dynamic and give it into the constructor of a class that contains a collection of instances of another class the object actually ought to be of (I get a JSON array returned from the webservice anyway). In the constructor of the collection class I decide depending on a value of the JSON object of which inherited class the new object is gonna be and put that into the collection. Yeah, I walked that way afoot somehow but it works.
Looks like this:
public CollectionClass(dynamic dyn)
{
foreach(var item in dyn.items) {
switch((string)item.external_id) { // might have used a Dictionary instead but...
case "member":
this._collection.Add(new Member(item));
break;
case "date":
this._collection.Add(new Date(item));
break;
default: break;
}
}
}
The Member-class itself contains a similar constructor which also requires a dynamic parameter. And it also "builds itself up" depending on values inside the item.
If there's any easier way or a "royal road" of achieving this I'd be grateful for any further advice.

How can you get a type of a control at runtime?

If any control (e.g. a DataGrid) is cast to UIComponent, how can you get its type at runtime?
Is this possible in Actionscript?
You can use getQualifiedClassName() to get class name by the value as a string. You can use describeType() to get the full information about class. And you can use constructor property to get class itself (to instantiate new instance by existing instance). Finally you can use is operator to compare to the limited set of classes. Less recommended usage of typeof operator which is rather obsolete.
To select the right way we need to know your particular problem.

Extending Flex FileReference class to contain another property

I want to extend the FileReference class of Flex to contain a custom property. I want to do this because AS3 doesn't let me pass arguments to functions through event listeners, which makes me feel sad, so I need this property to exist on the event target, so I can access it.
I also want to be able to cast extant FileReference objects to this class without any fuss. I have:
var fr:SmxFR = e.target as SmxFR
and I want that to work; right now it just returns null.
A blank, newly instantiated SmxFR object has the extended property in place, but all of its inherited properties and objects return Error: Error #2037: Functions called in incorrect sequence, or earlier call was unsuccessful.
This is the class I am using, SmxFR.as:
package
{
import flash.net.FileReference;
public class SmxFR extends FileReference
{
public var housenum:String = "";
public function SmxFR()
{
super();
}
}
}
Kept it as straightforward as I could, really. Can someone please help me figure this out? Thanks.
Edit:
Per request, this is the instantiation which results in the aforementioned error in all inherited objects:
var fr:SmxFR = new SmxFR();
I get living handle property from that, and all other (that is, inherited) properties throw Error #2037.
So, maybe what I want to do is going to require overriding FileReferenceList? If the original objects must be instantiated to SxmFR, that's what I'll have to do, since I'm using FRL to allow the user to select multiple files at once. Are you guys sure there is no way to fast from a FileReference to my class?
You can totally pass objects via event listeners, it's just done in a specific way. I'd learn to do it correctly, rather than trying to extend a core library which could cause you problems later if you make a small mistake.
My solution: instead of extending FileReference, extend Event and add your properties to that.
var myEvent:MyExtendedEvent = new MyExtendedEvent();
myEvent.myCustomProperty = myValue;
dispatchEvent(myEvent);
Then in your handler you just write:
function myEventHandler(e:MyExtendedEvent):void {
trace(e.myCustomProperty);
}
Much more painless to go down this road! The added benefit is that if any other Flash Developer anywhere ever looks at your code they're not going to get hit in the face with a non-standard customized FileReference. :)
When e.target is instantiate as FileReference you can't cast it to SmxFR because it's not in the line of inheritance. In the other way you can a SmxFR Object to FileRefernce.
Extending FileReferenceList is not going to be helpful. FileReferenceList.browse() method creates an array of FileReference object when user selects multiple files - that happens internally (may be in its private methods) and you cannot change that behavior and force it to create SxmFR objects instead. Use custom events as Myk suggested.
This article talks about Sound objects, but may be that's applicable to FileReference objects too. May be you cannot reuse them. Post the code where you use the SmxFr class and get the said error.

React to change on a static property

I'm re-writing an MXML item renderer in pure AS. A problem I can't seem to get past is how to have each item renderer react to a change on a static property on the item renderer class. In the MXML version, I have the following binding set up on the item renderer:
instanceProperty={callInstanceFunction(ItemRenderer.staticProperty)}
What would be the equivalent way of setting this up in AS (using BindingUtils, I assume)?
UPDATE:
So I thought the following wasn't working, but it appears as if Flex is suppressing errors thrown in the instanceFunction, making it appear as if the binding itself is bad.
BindingUtils.bindSetter(instanceFunction, ItemRenderer, "staticProperty");
However, when instanceFunction is called, already initialized variables on the given instance are all null, which was the cause of the errors referenced above. Any ideas why this is?
You have 2 options that I am aware of:
Option 1
You can dig into the code that the flex compiler builds based on your MXML to see how it handles binding to static properties. There is a compiler directive called -keep-generated-actionscript that will cause generated files to stick around. Sleuthing through these can give you an idea what happens. This option will involve instantiating Binding objects and StaticPropertyWatcher objects.
Option 2
There is staticEventDispatcher object that gets added at build time to classes containing static variables see this post http://thecomcor.blogspot.com/2008/07/adobe-flex-undocumented-buildin.html. According to the post, this object only gets added based on the presence of static variables and not getter functions.
Example of Option 2
Say we have a class named MyClassContainingStaticVariable with a static variable named MyStaticVariable and another variable someobject.somearrayproperty that we want to get updated whenever MyStaticVariable changes.
Class(MyClassContainingStaticVariable).staticEventDispatcher.addEventListener(
PropertyChangeEvent.PROPERTY_CHANGE,
function(event:PropertyChangeEvent):void
{
if(event.property == "MyStaticVariable")
{
someobject.somearrayproperty = event.newValue as Array;
}
});
I think you need to respond to the "PropertyChanged" event.
If you're going to do that, use a singleton instead of static. I don't think it will work on a static. (If you have to do it that way at all, there are probably a couple ways you could reapproach this that would be better).
var instance:ItemRenderer = ItemRenderer.getInstance();
BindingUtils.bindProperty(this, "myProperty", instance, "theirProperty");
After fiddling with this for a while, I have concluded that this currently isn't possible in ActionScript, not even with bindSetter. It seems there are some MXML-only features of data bindings judging by the following excerpt from the Adobe docs (though isn't it all compiled to AS code anyways)?
You cannot include functions or array
elements in property chains in a data
binding expression defined by the
bindProperty() or bindSetter() method.
For more information on property
chains, see Working with bindable
property chains.
Source: http://livedocs.adobe.com/flex/3/html/help.html?content=databinding_7.html
You can create a HostProxy class to stand in for the funciton call. Sort of like a HostFunctionProxy class which extends from proxy, and has a getProperty("functionInvokeStringWithParameters") which will invoke the function remotely from the host, and dispatch a "change" event to trigger the binding in typical [Bindable("change")] Proxy class.
You than let the HostProxy class act as the host, and use the property to remotely trigger the function call. Of course, it'd be cooler to have some TypeHelperUtil to allow converting raw string values to serialized type values at runtime for method parameters (splitted by commas usually).
Example:
eg.
var standInHost:Object = new HostFunctionProxy(someModelClassWithMethod, "theMethodToCall(20,11)");
// With BindingUtils.....
// bind host: standInHost
// bind property: "theMethodToCall(20,11)"
Of course, you nee to create such a utlity to help support such functionality beyond the basic Flex prescription. It seems many of such (more advanced) Flex bindings are usually done at compile time, but now you have to create code to do this at runtime in a completely cross-platform Actionscript manner without relying on the Flex framework.

Resources