My Groundhound Day passing extra parameters to listeners

Back in AS2 when the mx.utils.Delegate class was introduced quickly many people were asking for extra parameters. It didn't take long until people came up with a new Delegate class that could indeed pass parameters.

Fast forward to AS3 and guess what? Again you cannot pass extra parameters to listeners. I'm talking about doing something like this:

[code lang="actionscript"]button.addEventListener(MouseEvent.CLICK,callback,myFancyParameter);[/code]

Half the answers I've found end up saying something like:

The event object that arrives to your callback has a target property that you can use.


Well, that doesn't help me much. Maybe I should change how I build things, but if I do it like this:

[code lang="actionscript"]
for(var x:uint=0;x<10;x++){
var button:Button = new Button();
button.addEventListener(MouseEvent.CLICK,callback);
}
[/code]

What's the difference between the buttons if all of them have been created on the same loop? There are a couple of dirty tricks that you can use to bypass this limitation, but so far the best solution I've found is using the data attribute of the Button object. Then the loop looks like this:

[code lang="actionscript"]
for(var x:uint=0;x<10;x++){
var button:Button = new Button();
button.data = wadus // where wadus might be any type of object
button.addEventListener(MouseEvent.CLICK,callback);
}

function callback(e:MouseEvent):void{
var yourWadus:Wadus = Wadus(e.target.data); // gotcha!
}
[/code]

This is obviously not the same as the ability to pass any number of parameters you might need, but at least it's something and it's official.

If you really, really need to pass any number of parameters, then get ready to step into the Dark Side: closures. Every time you use them a little puppy dies or so they say. Your objects won't be GC'ed and your performance will go even worst than the global economy but it feels sooooo good. Check it out:

[code lang="actionscript"]
for(var x:uint=0;x<10;x++){
var button:Button = new Button();
button.addEventListener(MouseEvent.CLICK,function(e:MouseEvent):void{ callback(x); });
}

function callback(x:uint):void{
trace("Oh yeah baby > " + x);
}
[/code]

Oh yes, I forgot, there's also the good way of doing it, which would look like this:

[code lang="actionscript"]
class MyButton extends Button{
public var myVar:uint;
}

for(var x:uint=0;x<10;x++){
var button:MyButton = new MyButton();
button.addEventListener(MouseEvent.CLICK,callback);
button.myVar = x; // now this is NOT a trick
}

function callback(e:MouseEvent):void{
trace("Oh yeah baby > " + MyButton(e.target).myVar);
}
[/code]

So maybe it's time to do things right and if your button needs an extra property, then it's not a Button, it's a MyButton. But, am I going to build a new type of Button for each element of my interface that has to pass a parameter to a listener??? Don't think so.

For the time being the data property works for me, but more than happy to hear other options.

Back to index