tags:

views:

117

answers:

1

hi,

I've a parent (Canvas) with many children (LinkButtons)

The linkButtons trigger an event to communicate between them:

dispatchEvent(new SameBookmarkEvent("SameBookmarkEvent", bookmark.name));

and all linkButtons have a listener

this.addEventListener("SameBookmarkEvent", highlightMe);

...

private function highlightMe(e:SameBookmarkEvent):void {
    //do something
}

Now, the issue is that the event is only listened by the dispatcher child. In other words, only the child triggering the event, is receiving it. I was wondering what's wrong with it, and if I should add a listener to the parent (Canvas)...

I basically need the children (LinkButton) communicate between them

+1  A: 

Yes, when you add the button's listener to a function within that object, of course only that object will receive the event. When you call addEventListener with the highlightMe function, you pass a reference to the highlightMe function within the current scope. That means that the private function within that class is referenced. But that function is different for each new instance of the class.

In OOP each object works for itself and doesn't know anything about the parents, so one link button should not be able to know that there are other link buttons beside itself and what those buttons do. Instead the parent knows that there are X different link buttons, each working alone, but managed by the parent to work together. In that sense, when working with events, one should always leave the event handling in the parent object – except your custom class has default handlers that keep a standard procedure working (like changing appearance on mouse over etc), or when you have custom events that encapsulate other events.

As such the correct way to deal with it, is to have a single event handler in the parent class (where you instantiate the buttons) which then also is able to identify which button the event is related to.

Example

public class SomeParent extends Sprite
{
    public function SomeParent ()
    {
        var btn:Button;

        for ( var i:uint = 0; i < 100; i++ )
        {
            btn = new Button();
            btn.label = 'Button ' + i;
            btn.addEventListener( MouseEvent.CLICK, clickHandler );

            this.addChild( btn );
         }
     }

     private function clickHandler ( event:MouseEvent ):void
     {
          var btn:Button = event.eventTarget as Button;
          trace( 'Button with id ' + this.getChildIndex( btn ) + ' and label "' + btn.label + '" was pressed.' );
     }
}
poke
ok, anyway I'm still not very convinced. I usually trigger an event from a component and listen for it from another component that has not clue who the dispatcher is. In other terms, the 2 components not need to know about each other when I use events. So... let's say I have 2 different components (they both are children of the same parent), and one is the dispatcher and the other one the listener: in this case it works, right ?
Patrick
In that case the parent is still the one who will set the handler for the dispatcher, as each child won't know anything about the other. As the parent of course you can delegate the actual event handling to another component (which doesn't know about the actual dispatcher, except that there is an event with a target object), but you are still leaving the control of the events in the parent. I'll add a short example for multiple dispatchers and one central listener in a moment.
poke
so, a good solution would be: children dispatching Event1 and listening for Event2, parent listening for Event1 and dispatching Event2. (These are custom events so I can pass data with them.) Is this ok ? Or is there a simpler solution to pass information between children ?
Patrick
Well that way the child would know what the parent is and what event it will dispatch. Or it would require a public event handler function so the parent can assign it (`this.addEventListener( event, children.handleEvent )`). And then you could also just call such a function directly, so you better just add some interface to the child that does whatever you want the parent to trigger.
poke
ok. With "just add some interface to the child" you meant adding some public function to the children, for the parent to trigger right ? You didn't mean adding an "actionscript interface".
Patrick
Yes, you don't need to define an actual interface (in OOP sense) for it. Interfaces in general are just the set of open, or public available, methods an object has. So yes, a simple public function is enough :)
poke