Does anyone know how to programmatically bind a property to a function that isn't a getter? IE: I have a function that returns a translated string based on the identifier you pass it. How do I do this in AS3 rather than MXML? (reason being - I have a dynamic layout that I render based on XML and so have create and add all children programmatically).
You can bind functions to any event that is dispatched when the property changes. use the addEventListener() member method to add a handler. Read the Flex 3.0 documentation here.
You can call a setter function using BindingUtils.bindSetter()
. You can use this to call a setter function that calls your translation function and sets the return value to a specified place. Unfortunately you can't dynamically specify the host of the setter like you can with BindingUtils.bindProperty()
.
I'm not sure this is what you're looking for, but I've done something similar this way:
Say you've declared a Label using your function:
<mx:Label text="{LocaleUtil.getMessage('label.description')}"/>
That getMessage
function reads a XML file depending on the selected Locale.
If the user changes the Locale, you should call executeChildBindings(true)
on any container or on the whole application:
this.parentApplication.executeChildBindings(true);
That will force every child UIComponent
to execute the bindings again.
Since functions are object in actionscript3.0, you may add properties to them, the same as you would any other object,
var f : Function = function() : void{
trace("Value of testProp: " + arguments.callee.testProp );
};
(f as Object).testProp = 'TESTING';
f();
arguments.callee is used like the this keyword. arguments.callee holds a reference to the function it is used inside of.
I'm not sure if this is what you wanted, but this is how you would add a property to a function.
I'm sorry I think i got it backwards, you want to add a function to a property, not add a property to a function. O well, hope you enjoy this post anyway.
Ok so to be honest I managed to resolve this one myself by doing:
public function loadStringBinding(aIdentifier:String, aField:UIComponent, aProperty:String, aAddtlChars:String = null):Function
{
return function():void {
var str:String;
if(aAddtlChars)
{
str = aAddtlChars;
}
else
{
str = '';
}
if(_localePacks.get(currentLocale))
{
if(XML(_localePacks.get(currentLocale)).translatedString.(@identifier==aIdentifier)[email protected]().length > 0)
{
aField[aProperty] = XML(_localePacks.get(currentLocale)).translatedString.(@identifier==aIdentifier).@translation + str;
return;
}
else
{
aField[aProperty] = aIdentifier + str;
return;
}
}
else
{
//TODO: Replace with webservice call to get individual string
}
aField[aProperty] = 'No locale pack' + str;
return;
}
}
What this does is return the function that it gets bound to, so I can pass it which ever component I want the property go get bound to. It is implemented like:
_currentWatchers.addItem(BindingUtils.bindSetter(LocaleManager.instance().loadStringBinding('firstName, myCFormItem, 'label', '*'), LocaleManager.instance(), 'newLocale'));
I'm sure that it doesn't really make sense to anyone seeing as the rest of the code isn't here and it's a bit involved of an application, but just know that the solution is that the bindSetter function takes a funciton as the first parameter, so I created a function that creates a function that executes the binding that I wanted. If that makes sense to anyone else.. awesome! Thanks for anyone who contributed though!
If you want to bind the result of a function, you will have to mention the type of event that will be triggered when the function's result changes (see point 2).
private var foo:int;
[Bindable(event="myCustomFunctionBinding")]
public function myFunction():String
{
return "This is foo :" + foo;
}
Then, when you want all elements to update the binded value, you must dispatch the event yourself :
private function bar():void
{
foo++;
dispatchEvent(new Event("myCustomFunctionBinding"));
}
In which case, you can bind like this :
<mx:TextArea text="{myClass.myFunction()}" />