Managing Data Using The Flash MX Professional 2004 Architecture

 < Day Day Up > 

Flash MX Professional 2004 comes with multiple tools for managing the manipulation of client-side data in the Flash Player. As you have seen in Chapter 9, "Building and Using UI Components ," using data in the Flash Player can require the building of complicated data structures on the client. However, Flash MX Professional 2004 has a built-in framework that lets us manipulate and handle data efficiently in the Player. You can perform various advanced operations on data within the Flash Player, including the following:

  • Multiple sorts

  • Offline caching

  • Finding data

  • Filtering data

  • Linking data to UI controls

  • Keeping track of all changes in delta packets

You have been working with data, but have not used any data management tools; you have simply used data binding to bind the data directly to UI controls. You have had to handle everything manually; as your applications get more complex, you will crave tools that will make your life easier. When we linked two components together in Chapter 9, we had to build all the arrays and data structures by hand. In effect, we built our own data management tools. This is where the dataset and/or the DataHolder component enters in. Let's review the entire process in the following subsections. See Figure 14.10.

Figure 14.10. An overview of the data management process.

graphics/14fig10.gif

Moving Data from the Connector to the Dataset

The first part of working with data in Flash is using the connector components to connect to a datasource. You can use the Web Services connector, the XML connector, or the Remoting connector (not yet released), depending on the datasource to which you need to connect. It is possible to not use a connector component and just use the XML, Web Services, or Remoting classes directly to connect to a datasource. In either case, you need to be aware of the type of data being returned from the server; the XML and Web Services connectors will usually work best with an Array of Objects, but Flash Remoting works equally well with an Array of Objects, a RecordSet object, or many other datatypes.

The second part of working with data involves linking the connector to the dataset or the DataHolder component. One way of doing this is to use visual data binding, as shown in Figure 14.11:

Figure 14.11. Linking a connector to a dataset using data binding.

graphics/14fig11.gif

Another way of doing this is through ActionScript 2.0 code. All you need to do is set up a result event and then bind the object directly to the dataset. The object that is bound to the dataset can implement a dataProvider interface, such as a RecordSet . You can also use an Array of Objects returned from an XML connector or a Web Services connector. If you are linking an Array of Objects from the server to the dataset, you can use the items.array property; if you are using an implementation of the dataProvider class, such as a record set, you use the dataProvider property. The ActionScript 2.0 code to link a dataProvider is remarkably simple; all you have to do is link the object from the results to the dataProvider of the dataset, as shown in the following code:

 employeeObject :Object = new Object(); employeeObject.result = function() :Void{       employee_ds.dataProvider = employee_ws.results; } employee_ws.addEventListener("result", employeeObject); 

If you are using the XML connector or the Web Services connector, or are accessing an Array of Objects from the server using Remoting, you will be returning an Array of Objects. The best practice is to link that Array of Objects directly to the items array of the dataset, as shown in the following code:

 employeeObject :Object = new Object(); employeeObject.result = function() :Void {       employee_ds.items = employee_ws.results; } employee_ws.addEventListener("result", employeeObject); 

That's it! You have now added data to the DataSet component.

Using the DataSet Component

The DataSet component enables you to manage your client-side data by creating and loading the data into anonymous objects that are accessed and controlled by a cursor. The cursor in the dataset can be moved from record to record and the appropriate information can be obtained by accessing properties within the record.

In the following step sequence, you will add the data from the stock quote web service to a dataset, and you will do it in ActionScript 2.0 code so that you have complete control over the data that is coming in.

N OTE

You are hard-coding the web service parameters here and not using the text field to pass the stock quote parameters.


  1. Create a new FLA file and drag a web service connector from the Library to the Stage. Assign the connector an instance name of stockService .

  2. Drag a DataSet component from the Components panel to the Stage and assign it an instance name of stock_ds .

  3. Create an Actions layer and type the following code:

      stockService.WSDLURL = "http://www.swanandmokashi.com/HomePage/WebServices/StockQuotes.asmx?WSDL";   stockService.params = new Array (["macr aapl adbe msft orcl sunw"]);   stockService.trigger();   var stockListener :Object = new Object();   stockListener.result = function () {   stock_ds.items = stockService.results;   }   stockService.addEventListener ("result", stockListener);  

    The preceding code sets the URL for the web service connector and passes it parameters. When the results are received from the web service, it links the data from the web service to the dataset.

  4. Add the trace statement after the data from the connector is linked to the dataset data, as shown in the following code:

     stockListener.result = function () {        stock_ds.items = stockService.results;        trace (stock_ds.CompanyName); } 

    To access records from the dataset, reference the property name that is coming back from the server, in the result event. The code will return MACROMEDIA, INC because this is what the web service returns based on the first parameter that you sent.

  5. So how is the next record in the dataset, in this case Apple , accessed? Add the following ActionScript 2.0 code:

     stockListener.result = function () {        stock_ds.items = stockService.results;        trace (stock_ds.CompanyName);        stock_ds.next();        trace (stock_ds.CompanyName); } 
  6. Move the dataset cursor to the next record. The result of the second trace is Apple because that is the second parameter that you passed to the dataset.

Other methods can be used to facilitate navigation within the dataset. The first() method will move the data cursor to the first record in the dataset while the last() method will move the data cursor to the last record. A do-while loop is perfect for looping over a dataset; there is a method with the name of hasNext() that tests to see if the dataset does in fact have a record after the one the cursor is currently on. To loop through an entire dataset and retrieve the data, do the following:

  1. Move the data cursor to the first record in the dataset with the first method of the dataset, using the following code:

     stockListener.result = function () {        stock_ds.items = stockService.results;        stock_ds.first(); } 
  2. Set up a while condition using the hasNext() method of the dataset, as shown in the following code:

     stockListener.result = function () {        stock_ds.items = stockService.results;        stock_ds.first();        while (stock_ds.hasNext()) {} } 
  3. After executing the code on the appropriate record, move the data cursor to the next record while still in the loop, as shown in the following code:

     stockListener.result = function () {        stock_ds.items = stockService.results;        stock_ds.first();        while (stock_ds.hasNext()) {              trace (stock_ds.CompanyName)              stock_ds.next(); } } 

That's pretty straightforward. Looping can also be used for searching for a particular record, such as companies that have a stock price of greater than 20. This is part of the reason it is more efficient to use ActionScript 2.0 for binding; adding this type of logic is difficult using the Component Inspector. To do so, you could add the following logic to the stock quotes application:

 while (stock_ds.hasNext)) {       if (stock_ds.StockQuote >20) {             trace (stock_ds.CompanyName);       }       stock_ds.next(); } 

The real power of a dataset comes into play when other components are synchronized to the cursor of the dataset. This makes it very easy to create dependent components. Note that the same choices of using the Data Bindings panel or using ActionScript 2.0 code still apply. To do this, make the selectedIndex of the component the same as the selectedIndex of the dataset. The beauty of this approach is that the dataset will automatically move the cursor from record to record in the dataset when the user moves the record in the UI control.

  1. Add a list component to the Stage of the stock quote example with which we have been working. Assign the component an instance name of stock results .

  2. Select the DataSet component on the Stage and open the Component Inspector. Bind the selectedIndex property of the dataset to the selectedIndex of the list component on the Stage (instance name of stockResults), as shown in Figure 14.12:

    Figure 14.12. Linking the dataset to a list component using the Component Inspector.

    graphics/14fig12.gif

  3. Add a TextArea component to the Stage and assign it an instance name of stockQuote .

  4. Remove the visual binding between the dataset and the stockResults list. Add the following ActionScript 2.0 code:

     var changeList :Object = new Object(); changeList.change = function () {        stock_ds.selectedIndex = stockResults.selectedIndex;        stockQuote.text = stock_ds.StockQuote; } stockResults.addEventListener ("change", changeList); 

    Flash will manage everything automatically through the data cursor. When the user selects a company from the list, Flash will manage which company was selected and display the appropriate related information in the text fields. This makes it easy on the developer because the dataset handles all this interaction.

At first glance, it may seem like more work to use ActionScript 2.0 rather than the Component Inspector, but ActionScript does give us much more flexibility. It would be simple to apply conditional logic, for example, to affect other UI controls. Applying logic or modifying the data that already exists is cumbersome at best when using the Visual Data Binding Inspector. Certainly using a dataset here is saving lots of time; there is no need to loop through any data based on the user's selections because the two selectedIndex properties are bound together.

So far, the objects used within the dataset represent just a single record of data. The objects have properties that you have been calling that represent each field of data. The DataSet object also has the ability to create its own application program interface (API), which is a collection of methods on the client side. These methods can mirror the structure of a server-side object and even be sent back to the server for processing using the resolver components.

Note that the dataset is a collection of "transfer objects" modeled on the J2EE transfer object pattern. This server-side object exposes data with public attributes and has getter/setter methods to access and write that data. The transfer object is known as a pattern and more information about it is available from Sun at http://java.sun.com/blueprints/corej2eepatterns/Patterns/TransferObject.html.

It's important for Flash developers to understand the transfer object pattern because the dataset is a client-side implementation of this pattern. It enables developers to work with sophisticated client-side objects that are exactly the same as their server-side counterparts. It's also extremely easy and efficient to send data back and forth between the client-side object and the server-side object using delta packets.

Examine the following code:

 interface mx.data.to.TransferObject {   function clone():Object;   function getPropertyData():Object;   function setPropertyData(propData:Object):Void; } 

You use the itemClassName parameter of the dataset to specify the name of the class you create in ActionScript that implements the TransferObject interface, as shown in the following code:

 mydata set.itemClassName = myClass; 

The dataset will then automatically create instances of the object from the class upon the initial load of the data into the dataset as well as whenever the addItem method is used. You also must specify a fully qualified reference to the class somewhere within your SWF, as shown in the following code:

 var myItem:my.package.myItem; 

If you call server-side methods, they will be stored in the Flash Player until the object is sent to the server through Web Services or Flash Remoting using the resolver component. Another option is to use Flash Remoting or Web Services actually within the class; you then call the server-side method as soon as it is called on the client.

The Delta Packet Classes

Delta packets are one of the most powerful new features of Flash. Each dataset has an underlying delta packet that is changed whenever a user updates the dataset.

A lot of time was spent in the past section connecting a dataset to a UI control. Because of that hard work, the rest of the job becomes much easier. The ActionScript takes the results from a web service call, places the results into a dataset, and links that dataset to a data grid control. Whenever an end user moves to another record in the data grid, the data cursor in the dataset is moved automatically. The trace that is included in the change handler proves this.

The following code uses the stock quotes web service as an example, but the list has been replaced with a data grid that has an instance name of stockResults . Review the code and note the only difference is that the horizontal scrolling of the grid has been turned on:

 stockService.WSDLURL ="http://www.swanandmokashi.com/HomePage/WebServices/StockQuotes.asmx?WSDL"; stockResults.hScrollPolicy = "On" stockService.params = ["macr aapl adbe msft orcl sunw"];stockService.trigger(); var stockListener :Object = new Object(); stockListener.result = function () {        stock_ds.items = stockService.results;        stockResults.dataProvider = stock_ds.dataProvider;        stockResults.labelField = "CompanyName"; } var changeList :Object = new Object(); changeList.change = function () {        stock_ds.selectedIndex = stockResults.selectedIndex;        stockQuote.text = stock_ds.StockQuote; } stockResults.addEventListener ("change", changeList); stockService.addEventListener ("result", stockListener); 

Adding the following line of code makes the DataGrid UI control editable:

 stockResults.editable = true; 

You can change any one of the fields on the grid. The beautiful part of this is that by changing the field in the grid, the dataset is automatically updated as well. The dataset is managing all the data, and any changes that are made are captured inside the delta packet. The Delta Packet classes and interfaces enable viewing of the information being sent to the server, and they also enable the dataset to receive errors and make updates.

The delta packet consists of the following:

  • Delta Packet interface. Allows developers to access the modified data, known as delta, from the dataset.

  • Delta interface. The actual changed and unchanged values from the dataset.

  • DeltaItem. Informs the developer about the particular type of change that was made, and whether it was made to a property of the transfer object in the dataset or to a method.

  • Delta PacketConsts. Provides static variables indicating whether the information in the dataset was added, modified, or removed.

Resolvers

Now that the delta packet has been generated, it needs to be sent back to the server. The delta packet is accessible as a property of the DataSet component. However, it is not created until the applyUpdates method is called. The following code displays the delta packet of the employee_ds dataset, assuming a button, stock_ds , was on the Stage.

 pusher_pb.onRelease = function () {        stock_ds.applyUpdates();        trace (stock_ds.deltapacket); } 

This returns an object that has these properties:

  • _confInfo

  • _timestamp

  • _log

  • _transId

  • _keyInfo

  • _source

  • _optimized

  • _Delta Packet

Examining the object shows that the delta packet consists of many objects not suitable for a server to easily use. This is where the resolver comes in. The resolver takes a delta packet that has been bound to it and generates an updatePacket containing the changes in the delta packet. This is in an XML format and can easily be consumed by a server using a web service or Flash Remoting to pass the XML back.

The following code sets up a binding between the Delta Packet property of the resolver and the Delta Packet property of the dataset. This can also be done with visual data bindings to bind the Delta Packet property of the dataset to the Delta Packet property of the Resolver. Once bound, the resolver automatically creates the updatePacket property, which is an XML document. It also assumes a resolver component with the instance name of stock_resolve is on the Stage. When the push button is pressed, a delta packed is generated from the dataset that shows the data that was changed. A trace is then added to display the XML delta packet.

 pusher_pb.onRelease = function () {        stock_ds.applyUpdates();        stock_resolve.deltapacket = stock_ds.deltapacket;        trace (stock_resolve.updatePacket); } 

For example, if we change the prices of the stocks in the grid, the resolvers will grab the delta packet from the dataset and generate an XML packet to update the content. We would need a server-side piece to grab the XML packet and it is unlikely that this web service would appreciate us updating the price of Macromedia to 200 and downgrading Adobe to 1, as shown in the following code:

 <?xml version="1.0" ?>  <update_packet tableName="" nullValue="{_NULL_}" transID="IID17802395625:Thu Oct 16 20:15:55 GMT-0700 2003">  <update id="IID26029991731">   <field name="STOCKQUOTE" type="Number" oldValue=39.33  newValue=1 key="false" />   </update>   <update id="IID61346959788">   <field name="STOCKQUOTE" type="Number" oldValue=20.23 newValue=200 key="false" />   </update>   </update_packet> 

Notice that updatePacket is not sending all the data in the dataset; it sends only the data that has changed, which results in a very efficient and powerful solution.

This update packet is generated through the resolver components. The resolver will take a delta packet from a DataSet object and create an updatePacket that is suitable for consumption by a server-side solution.

DataHolder Component

The DataHolder component is a simple component especially useful with visual data binding. Unlike the DataSet component, it does not have any tools for managing, tracking, or updating data. It is useful when you cannot directly bind components together. For example, if you write ActionScript code and need to link this code to a component, you could use the DataHolder component to store the information and data binding to bind it to the appropriate UI control.

 < Day Day Up > 


Object-Oriented Programming with ActionScript 2.0
Object-Oriented Programming with ActionScript 2.0
ISBN: 0735713804
EAN: 2147483647
Year: 2004
Pages: 162

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