views:

576

answers:

6

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).

A: 

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.

dirkgently
+1  A: 

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().

erikprice
+1  A: 

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.

leolobato
A: 

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.

ForYourOwnGood
A: 

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!

A: 

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()}" />