2
votes

I have a Renderer:

<?xml version="1.0" encoding="utf-8"?>
<s:ItemRenderer xmlns:fx="http://ns.adobe.com/mxml/2009" 
                xmlns:s="library://ns.adobe.com/flex/spark" 
                xmlns:mx="library://ns.adobe.com/flex/mx">

  <fx:Metadata>
    [Event(name="addToCart",type="event.ProductEvent")]
  </fx:Metadata>
  <fx:Script>
    <![CDATA[
      import events.ProductEvent;

      import mx.collections.ArrayCollection;


      protected function button1_clickHandler(event:MouseEvent):void
      {
        var eventObj:ProductEvent=new ProductEvent("addToCart",data.price,data.descript);

        dispatchEvent(eventObj);

      }
    ]]>
  </fx:Script>

  <fx:Declarations>
    <!-- Place non-visual elements (e.g., services, value objects) here -->
  </fx:Declarations>

  <s:states>
    <s:State name="normal"/>
    <s:State name="hovered"/>
  </s:states>

  <s:BorderContainer >
    <s:layout>
      <s:VerticalLayout paddingBottom="10" paddingLeft="10" paddingRight="10" paddingTop="10"/>
    </s:layout>

    <s:Label text="{data.descript}"/>
    <mx:Image source="{data.url}" width="50" height="50" width.hovered="100" height.hovered="100"/>
    <s:Label text="{data.price}"/>
    <s:Button includeIn="hovered" click="button1_clickHandler(event)" label="buy"/>



  </s:BorderContainer>
</s:ItemRenderer>

and the custom event class:

package events
{
  import flash.events.Event;
  [Bindable]
  public class ProductEvent extends Event
  {

    public var price:String;
    public var descript:String;

    public function ProductEvent(type:String,price:String, descript:String)
    {
      super(type);
      this.price=price;
      this.descript=descript;
    }
    override public function clone():Event
    {
      return new ProductEvent(type,price,descript);

    }
  }
}

but i cannot call that event in a container from the main application

<s:SkinnableDataContainer id="Sk" x="200" y="300" left="100" right="900" dataProvider="{imagesCollection}" itemRenderer="components.ImageRenderer" includeIn="normal"   >
    <s:layout>
      <s:TileLayout/>
    </s:layout>

  </s:SkinnableDataContainer>

any ideas?

thanks


I want to make this:

<s:SkinnableDataContainer id="Sk" x="200" y="300" left="100" right="900" dataProvider="{imagesCollection}" itemRenderer="components.ImageRenderer" includeIn="normal" ***addToCart=something(event)*** >
6
I think you need to fix the formatting of the code in your question.JeffryHouser
see my comments below. when you dispatch the event you need the following: (owner as List).dispatchEvent(new CustomEvent); // set the owner to the container that you're using. Then you can add a listener to that component upon creation complete: myList.addEventListener(CustomEvent.TYPE, myCustomEventHandler);Yav

6 Answers

3
votes

Events are not called, so I'm not entirely sure what you want.

You can create an instance of an event class, like this:

var myProductEvent : ProductEvent  = new ProductEvent("productEventTypeA", true, ...); // true is for enabling Bubbles, so that the event bubbles up to the listener.

You can dispatch that event from an itemRenderer the same way you would do so if you were using an event elsewhere:

dispatchEvent(myEvent); 

Also on the item renderer, declare the event that is going to be dispatched:

[Event(name="productEventTypeA", type="local.events.ProductEvent")]

You can add an event listener on the List or DataGroup component implementing your item renderer so it runs your code after the event is dispatched:

myList.addEventListener("productEventTypeA", onProductEvent); // or a constant instead of "productEventTypeA"

or

myDataGroup.addEventListener("productEventTypeA", onProductEvent); // or a constant instead of "productEventTypeA"

And finally declare your listener function in the same file you added the event listener:

public function onProductEvent(e:ProductEvent):void
{
// do stuff
}

Note: In an itemRenderer, you often want to make your event bubble so that it can be listened to on the component which uses renderers--usually a list based class.

1
votes

I hope this helps someone, you don't need to do all that...

It's very simple:

ItemRenderer:

protected function dispatchMyCustomEvent():void {
(owner as List).dispatchEvent(new CustomEvent);
}

if the parent isn't a list then just typecast it to what the parent is.

then in your component that has the list you can do the following:

protected function creationComplete():void {
myList.addEventListener(CustomEvent.TYPE, onMyCustomeEvent);
}

protected function onMyCustomEvent(event:MyCustomEvent):void {
// handle the event
}
0
votes

It's hard to make out what you're trying to do from the question, because of the formatting, and it appears there's some text missing.

However. try making the event bubble, and add the event listener on the list which holds the itemRenderers.

Eg:

 <mx:Canvas creationComplete="list1.addEventListener('addToCart',onAddToCart)">
    <mx:List id="list1" itemRenderer="com.foo.YourItemRenderer" />
 </mx:Canvas>


 <!-- YourItemRenderer.mxml -->
 <mx:Canvas>
      <!-- Other item renderer stuff -->
       <mx:Button click="dispatchEvent(new ProductEvent('addToCart'))" />
 </mx:Canvas>


 // ProductEvent.as
 public class ProductEvent {
    public function ProductEvent(type:String,bubbles:Boolean=true) {
         super(type,bubbles);
         // ... etc
    }
 }
0
votes

Perhaps this is a little out of scope, but that sort of signaling with events is where MVC frameworks like Cairngorm shine. I usually think of them as AS event buses.

0
votes

This is possible using the Event metadata tag: http://livedocs.adobe.com/flex/3/html/help.html?content=createevents_3.html

You'll have to sub-class SkinnableDataContainer and add the metadata tag:

[Event(name="addToCart", type="events.ProductEvent")]
public class MySkinnableDataContainer extends spark.components.SkinnableDataContainer
{
}

You can also do it in MXML:

<?xml version="1.0"?>
<!-- ../MySkinnableDataContainer.mxml -->
<s:SkinnableDataContainer xmlns:fx="http://ns.adobe.com/mxml/2009" 
    xmlns:mx="library://ns.adobe.com/flex/mx" 
    xmlns:s="library://ns.adobe.com/flex/spark">

    <mx:Script>
    <![CDATA[
        import events.ProductEvent;
    ]]>
    </mx:Script>

    <mx:Metadata>
        [Event(name="addToCart", type="events.ProductEvent")]
    </mx:Metadata>

</s:SkinnableDataContainer>

Then use this new class instead of the SkinnableDataContainer:

<MySkinnableDataContainer id="Sk" x="200" y="300" left="100" right="900" dataProvider="{imagesCollection}" itemRenderer="components.ImageRenderer" includeIn="normal" addToCart="something(event)" />

Note: depending on your events bubble property you may have to catch it and then re-forward it along inside of MySkinnableDataContainer.

0
votes

Make the event bubble:

public function ProductEvent(type:String,price:String, descript:String)
{
  super(type, true); // Add bubbles = true instead of default false
  this.price=price;
  this.descript=descript;
}

Then in your app:

<s:SkinnableDataContainer id="Sk" x="200" y="300" left="100" right="900" dataProvider="{imagesCollection}" itemRenderer="components.ImageRenderer" includeIn="normal" creationComplete="Sk.addEventListener('addToCart', myFunctionToHandle)">

Add an event listener on creation complete.