Creating and Using the ProductEvent Class


In this next exercise, you will create an event subclass called ProductEvent. ProductEvent will add a single property to the Event class named product, which will hold an instance of the Product value object (defined in Lesson 5, "Handling Events and Data Structures"). This procedure will follow the same structure as the CategoryEvent class you created in the last exercise.

1.

Right-click the events folder, and create a new ActionScript class. Name the new class ProductEvent, ensure that the Package is set to events, and set Event as the superclass.

The skeleton for your new class should look like this:

package events {    import flash.events.Event;    public class ProductEvent extends Event {    } } 


2.

Create a property of your new class, named product, with a data type Product.

If you use code completion and choose the Product class from the list, the import statement for valueObjects.Product will automatically be added. If not, you will need to manually import the class.

package events {    import flash.events.Event;    import valueObjects.Product;    public class ProductEvent extends Event {       public var product:Product;    } } 


3.

Create a constructor for your class, which takes two arguments. The first argument is an instance of the Product class; the second is a String that indicates the type for the event.

public function ProductEvent(prod:Product, type:String){    super(type);    product = prod; } 


4.

Override the base classes clone() method. This method will return a new instance of the ProductEvent class with the same type and product.

public override function clone():Event{    return new ProductEvent(product, type); } 


5.

Save the ProductEvent class and verify there are no errors in the Problems panel.

The class should currently look like this:

package events {    import flash.events.Event;    import valueObjects.Product;    public class ProductEvent extends Event {       public var product:Product;       public function ProductEvent(prod:Product, type:String){          super(type);          product = prod;       }       public override function clone():Event{          return new ProductEvent(product, type);       }    } } 


6.

Open UpdateDeleteProd.mxml from your flexGrocer/views/dataEntry directory.

Alternately, you can open this file from the Lesson09/start/views/dataEntry directory, and save it in your flexGrocer/views/dataEntry directory.

7.

Add a new private method named broadcastEvent(), which takes two arguments: the first an instance of the Product class; the second a String that describe the event type. Inside this method, create a new instance of the ProductEvent class with the two passed-in arguments and dispatch it.

private function broadcastEvent(prod:Product, type:String):void{    var e:ProductEvent = new ProductEvent(prod,type);    this.dispatchEvent(e); } 


Rather than having redundant logic in both AddProduct and UpdateDeleteProduct, both of which show a pop-up to confirm adding, editing, and deleting a product, both components will dispatch a ProductEvent and use an event type to indicate whether the product is being added, updated, or deleted.

If not automatically added by the code-completion feature, manually add the import statement for the ProductEvent class to the top of the <mx:Script> block:

import events.ProductEvent; 


8.

Find the doProdUpdate() method. Remove the call to showPopUp(). In its place, call the broadcastEvent() method and pass it the product and the string productUpdate.

broadcastEvent(prod,"productUpdate"); 


9.

Find the doProdDelete() method. Remove the call to showPopUp(). In its place, call broadcastEvent() method, and pass it the product and the string productDelete.

broadcastEvent(prod,"productDelete"); 


10.

Add metadata to declare that UpdateDeleteProd.mxml will dispatch events named productUpdate and productDelete. Declare both events to be of type events. ProductEvent.

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


11.

Open AddProduct.mxml from your flexGrocer/views/dataEntry directory.

Alternately, you can open this file from the Lesson09/start/views/dataEntry directory, and save it in your flexGrocer/views/dataEntry directory.

12.

Find the doProdAdd() method. Remove the line calling the showPopUp() method, and instead, create a new instance of the ProductEvent class using the product created on the previous line and the string productAdded.

private function doProdAdd():void{    var prod:Product = Product.buildProduct(prodModel);    var o:ProductEvent = new ProductEvent(prod,'productAdded');    this.dispatchEvent(o); } 


Just as you did with UpdateDeleteProd, you are now preparing AddProduct to dispatch an event using the ProductEvent class.

If not automatically added, you will need to manually add the import statement for the ProductEvent class to the top of the <mx:Script> block:

import events.ProductEvent; 


13.

Add metadata to declare that AddProduct.mxml will dispatch an event named productAdded. Declare the event to be of type events.ProductEvent.

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


14.

Delete the the showPopUp() method from UpdateDeleteProd. Copy and delete the showPopUp() method from AddProduct.

This method will be implemented in DataEntry instead.

15.

Open DataEntry.mxml from your flexGrocer directory. After the imports, create a private property named win of type ConfirmScreen.

private var win:ConfirmScreen; 


This will hold the instance of the window that is launched. If you use the code-completion features, the import will automatically be added for you.

16.

Inside the <mx:Script> block, paste the showPopUp() method you copied in step 14.

private function showPopUp(prod:Product, title:String):void{    win = ConfirmScreen(PopUpManager.createPopUp(this, ConfirmScreen, true));    win.prod = prod;    win.title = title; } 


17.

At the top of the <mx:Script> block, add imports for valueObjects.Product and mx.managers.PopUpManager.

import valueObjects.Product; import mx.managers.PopUpManager; 


You just added calls to these classes in the previous step. Because you were pasting code, there was no chance to use code completion and have the imports automatically added, so you need to manually import the classes.

18.

Call your newly created showPopUp() method as the event handler for productAdded, productDelete, and productUpdate.

<v:UpdateDeleteProd    units="{units}"    foodColl="{foodColl}"    productUpdate="showPopUp(event.product,'Product Updated')"    productDelete="showPopUp(event.product,'Product Deleted')"/> <v:AddProduct    cats="{categories}"    units="{units}"    productAdded="showPopUp(event.product,'Product Added')"/> 


Now, the DataEntry application is solely responsible for showing confirmation pop-ups. You no longer have to handle it in each child component. If you save and test the application, it will continue to behave as it did in the previous lesson, but it is built in a far more maintainable and reusable manner.

Using ProductEvent to Remove a Product from the Cart

At the end of Lesson 8, you had the ability to add items to your shopping cart, but no means to remove them from the cart. The same ProductEvent class that you wrote for the DataEntry application can be used any time an event needs to carry a Product with it. One such case is when the user decides to remove a product from the shopping cart. In this next exercise, you will use the same ProductEvent class to facilitate removing items from the cart.

1.

Open Cart.mxml from flexGrocer/views/ecomm.

Alternatively, you can open the file from Lesson09/start/views/ecomm and save it in your flexGrocer/views/ecomm directory.

2.

Add a Button after the List, with a label Remove, and add a click event handler that will call a soon-to-be-written method called removeItem().

<mx:Button label="Remove"    click="removeItem();"/> 


This will allow the user to choose an item in the List and click this button to remove it.

3.

Create a new method called removeItem(). This method should use the selectedItem property of the List control to find the ShoppingCartItem, which is selected. Using the ShoppingCartItem, you can find the product for the selected item.

private function removeItem():void{    var item:ShoppingCartItem = cartView.selectedItem as ShoppingCartItem;    var prod:Product = item.product; } 


Currently, this method extracts the product from the selectedItem of the cart List. Knowing the product, you can now create a ProductEvent for it. Remember that if you want to treat the selectedItem as a member of the ShoppingCartItem class, you need to use casting to remind the compiler that the selectedItem of this List is a ShoppingCartItem.

Tip

These two lines:

var item:ShoppingCartItem = cartView.selectedItem as ShoppingCartItem;; var prod:Product = item.product; 


could be combined into a single line if you prefer:

var prod:Product = (cartView.selectedItem as ShoppingCartItem).product; 


4.

At the end of the removeItem() method, create an instance of the ProductEvent class with the selected product and a type of productRemoved. Dispatch the event instance.

var e:ProductEvent = new ProductEvent(prod,"productRemoved"); this.dispatchEvent(e); 


If not automatically added, you will need to specifically add the import statements for the ProductEvent class.

import events.ProductEvent; 


Tip

These two lines:

var e:ProductEvent = new ProductEvent(prod, "productRemoved"); this.dispatchEvent(e); 


could be done as a single line:

this.dispatchEvent(new ProductEvent(prod, "productRemoved"); 


Or you can combine it with the previous tip:

this.dispatchEvent(new ProductEvent(ShoppingCartItem(     cartView.selectedItem).product, "productRemoved"); 


However, it is easier to understand (and therefore maintain), if you leave it as the four lines:

var item:ShoppingCartItem = cartView.selectedItem as ShoppingCartItem; var prod:Product = item.product; var e:ProductEvent = new ProductEvent(prod,"productRemoved"); this.dispatchEvent(e); 


5.

Add metadata to declare the productRemoved event as an instance of the events.ProductEvent class.

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


All that remains is to have the EComm.mxml application listen for this event and remove the product when the event is heard.

6.

Open EComm.mxml from your directory. Find the instantiation of Cart. Listen for the productRemoved event and handle it by passing the event.product object to the deleteProd() method.

<v:Cart     width="100%"    cart="{cart}"    productRemoved="deleteProd(event.product)"/> 


The event that you are receiving here is a ProductEvent, which, as you defined earlier, has a property called product. Because the deleteProd() method was already written to accept a product as an argument, you can reuse the same method without changing it by just passing it the product from the event. If you save and run the application, you will find it is still functioning properly, and is built with a much more sound architecture.

Tip

If you click the Remove button without selecting an item in the List first, a run-time error will occur. In Lesson 25, "Debugging and Optimizing Flex Applications," you will learn about different strategies for catching and handling this error.


Using ProductEvent to Add a Product to the Cart

The ProductEvent class can also put to use to add products to the shopping cart. At the end of Lesson 8, items were added to the shopping cart from the GroceryDetail component with this line of code:

mx.core.Application.application.addToCart(prod); 


This is tightly coupling the GroceryDetail so that it can be used only in an application that has a method named addToCart() in the root application file. A far better practice is for the component to dispatch an event and pass along the product to be added.

1.

Open GroceryDetail.mxml from flexGrocer/views/ecomm.

Alternatively, you can open the file from Lesson09/start/views/ecomm and save it in your flexGrocer/views/ecomm directory.

2.

Find the itemAdded() method and remove the mx.core.Application.application.addToCart line. Instead create an instance of the ProductEvent class which uses the same product, and has its type set to itemAdded. Then dispatch that event.

private function itemAdded(prod:Product):void{    var e:ProductEvent = new ProductEvent(prod,"itemAdded");    dispatchEvent(e); } 


Again, the tightly coupled references are removed and replaced with event-based architecture. Determine if you need to specifically add the import for the ProductEvent class.

import events.ProductEvent; 


3.

Add metadata to indicate that GroceryDetail will dispatch an event called itemAdded() of type events.ProductEvent.

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


Now that GroceryDetail is dispatching the event, you want its parent, FoodList, to listen for and handle the event.

Tip

In the next section, you will see how event bubbling can simplify this process, enabling the event to pass through FoodList without FoodList explicitly redispatching it.

4.

Open FoodList.mxml from flexGrocer/views/ecomm.

5.

Find where GroceryDetail is instantiated. Add an event handler for the itemAdded event and pass the event object to a method you will add shortly named addItem().

<v:GroceryDetail     width="80%"    groceryItem="{foodRepeater.currentItem}"    itemAdded="addItem(event)"/> 


Here, you are listening for the itemAdded event and handling it with the addItem() method.

6.

Create a new private method called addItem(), which accepts an argument named event as an instance of the ProductEvent class. The method should return void. Inside the function, use the dispatchEvent() method to rebroadcast the event.

private function addItem(event:ProductEvent):void{    this.dispatchEvent(event); } 


Determine if you need to add the import statement for the ProductEvent class.

import events.ProductEvent 


7.

Add metadata to indicate that this method will dispatch an event called itemAdded that will be an instance of the events.ProductEvent class.

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


You can actually cut and paste this from GroceryDetail if you prefer because it is identical to the definition there.

8.

Open EComm.mxml from your directory

Alternatively, you can open EComm_remove.mxml from Lesson09/intermediate and save it as EComm.mxml in your directory.

9.

Find the instantiation of FoodList. Listen for the itemAdded event and handle it by passing the event.product object to the addToCart() method.

<v:FoodList     width="100%" height="100%"    prodByCategory="{prodByCategory}"    itemAdded="addToCart(event.product)"/> 


The event that you are receiving here is the ProductEvent you dispatched from the GroceryDetail. Because the addToCart() method was already written to accept a product as an argument, you can reuse the same method without changing it by just passing it the product from the event.

If you save the files and run the EComm application now, it should continue to run as it did.




Adobe Flex 2.Training from the Source
Adobe Flex 2: Training from the Source
ISBN: 032142316X
EAN: 2147483647
Year: 2006
Pages: 225

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net