views:

23

answers:

2

Hello Community!

I'm stuck with an issue and I cannot understand why it behaves like that...

In a for loop, I'm passing the for index as an event parameter. However, the eventHandler is getting the wrong index, but the right target...

Here's some code. .as class method:

public function set dataProvider(a:Array):void
{
    var x:int = 0;
    if(a != null && a.length > 0)
    {   
        labelsArray = (new ArrayCollection(a));
        trace("##############################################################");
        for(var i:int = 0; i<a.length; i++)
        {
            var btn:NavigationArrowButtonCtrl = new NavigationArrowButtonCtrl();
            var s:String = (new ArrayCollection(a)).getItemAt(i).toString();
            trace(i + '/' + s);

            btn.addEventListener(FlexEvent.CREATION_COMPLETE, function(e:FlexEvent):void{
                var lblIndex:int = i;
                btnAddLblHandler(e, lblIndex);
            });

            this.addChild(btn); 
            this.setChildIndex(btn, 0);
        }
        trace("##############################################################");
    }
}

private function btnAddLblHandler(e:FlexEvent, ind:int):void
{
    trace(labelsArray.length.toString() + '/' + ind.toString());
    if(ind < labelsArray.length)
    {
        trace('Handler ' + ind + '/' + String(labelsArray.getItemAt(ind)));
        (e.target as NavigationArrowButtonCtrl).lbl_body.text = String(labelsArray.getItemAt(ind));
    }
}

Here's the result trace I'm getting:

##############################################################
0/FINITION
1/> MOTORISATIONS
2/> EXTERIEUR
3/> INTERIEUR
4/> OPTIONS
5/> RESUME
##############################################################

6/6
6/6
6/6
6/6
6/6
6/6

Somehow, the handler is getting only the last value of the for index 'i' when it's supposed to get in each loop the current value of 'i' (0/1/2/3/4/5)... Any idea of what's wrong?

Thanks for your help! =) Regards,

BS_C3

+1  A: 

By the time the button is created and var lblIndex:int = i; gets called, the for loop would've completed its execution and the value of i would be a.length which is six here. You can either generate 5 different functions or use a little redesigning.

function getListener(i:Number):Function {
     return function(e:FlexEvent):void{
         var lblIndex:int = i;
         btnAddLblHandler(e, lblIndex);
     };
}
btn.addEventListener(FlexEvent.CREATION_COMPLETE, getListener(i));

It looks like you're trying to set the label of NavigationArrowButtonCtrl items once they're created; the easier way is to declare a [Bindable] variable inside that class and bind it to the lbl_body.text field. If you're not going to update it later, you need not really use binding either; you can just update the lbl_body.text from the public variable in the creationComplete handler.

Thus the code will look like:

//in NavigationArrowButtonCtrl.mxml
public var textvar:String;

//inside the for loop:
btn.textvar = labelsArray.getItemAt(i).toString();
btn.addEventListener(FlexEvent.CREATION_COMPLETE, btnAddLblHandler)

//inside btnAddLblHandler(e:FlexEvent):void
btn.lbl_body.text = btn.textvar;

//you can do it from the NavigationArrowButtonCtrl class itself
this.lbl_body.text = this.textvar;

Don't rely on e.target - use e.currentTarget instead. target can be some child of the button - currentTarget will always have the object with which event listener was registered.

By the way, don't create the same array collection in each iteration of the loop:

replace:

var s:String = (new ArrayCollection(a)).getItemAt(i).toString();

with

var s:String = labelsArray.getItemAt(i).toString();
Amarghosh
Hi!Thanks a lot for your comment =) It was really helpful and playing a bit with what u said, I did a slight modifications that solved the issue =)
BS_C3
A: 

This is what I did to solve the issue (scope thing): --> Same code as before, just encapsulating the 'for' part in a function.

public function set dataProvider(a:Array):void
{
    var x:int = 0;
    if(a != null && a.length > 0)
    {   
        labelsArray = (new ArrayCollection(a));
        trace("##############################################################");
        for(var i:int = 0; i<a.length; i++)
        {
            createBtn(i, a);
        }
        trace("##############################################################");
    }
}

private function createBtn(i:int, a:Array):void
{
    var btn:NavigationArrowButtonCtrl = new NavigationArrowButtonCtrl();
    var s:String = (new ArrayCollection(a)).getItemAt(i).toString();
    trace(i + '/' + s);

    btn.addEventListener(FlexEvent.CREATION_COMPLETE, function(e:FlexEvent):void{
            var lbl:String = s;
            btnAddLblHandler(e, lbl);
        }); 

    this.addChild(btn); 
}

private function btnAddLblHandler(e:FlexEvent, ind:int):void
{
    trace(labelsArray.length.toString() + '/' + ind.toString());
    if(ind < labelsArray.length)
    {
        trace('Handler ' + ind + '/' + String(labelsArray.getItemAt(ind)));
        (e.target as NavigationArrowButtonCtrl).lbl_body.text = String(labelsArray.getItemAt(ind));
    }
}
BS_C3