Building Your Application


Now that we have established a connection with our remote service, we can start to create other remote services to interact with our database. CFCs can be used many ways to return data to Flash. In our next example, we will use the <cfquery> tag to submit SQL (Structured Query Language) statements to communicate with the database and return the results of the query to Flash. In our getTestConn function, we only returned a string. Our returnType property in our <cffunction> tag was set to string. When returning values from a query, our returnType property needs to be set to query.

Return to your CFC unleashedCom.cfc, and type the following after the getTestConn function and above the closing </cfcomponent> tag:

 <! Get the ID and product name >     <cffunction name="getProducts" access="remote" returnType="query" output="true">     <cfquery name="productQuery" datasource="unleashedMenuData">     SELECT ID,prodName FROM products ORDER BY prodName ASC     </cfquery>  <cfreturn productQuery >     </cffunction>      <! get all records associated with the selected product ID >     <cffunction name="getProductsDetails" access="remote" returnType="query" output="true">     <cfargument name="prodID" type="numeric">     <cfquery name="productDetailQuery" datasource="unleashedMenuData">     SELECT * FROM products WHERE ID = #prodID#     </cfquery>  <cfreturn productDetailQuery >     </cffunction> 

We now have added two more functions, also known as remote services, to our CFC:

  • getProducts Retrieves the ID and product name from the products table in the database

  • getProductsDetails Retrieves all associated records based on the selected product ID

We now have completed our CFC. Next, we will add our elements to our Flash document. To do so, follow these steps:

NOTE

To save time from building the interface, you can open unleashedCafeMain_shell.fla and save it as unleashedCafeMain.fla.


1.

Return to Flash 8.

2.

Create two new layers and name them text and components.

3.

Select the Components layer.

4.

Open the Components panel.

5.

Drag a ListBox Component to the stage.

6.

Drag the Loader Component to the stage.

7.

Select the ListBox component, open the Properties panel, and enter the following values:

  • instanceName productsList

  • Width 200

  • Height 130

  • X 10

  • Y 45

8.

Select the Loader Component, open the Properties panel, and enter the following values:

  • instanceName imageHolder

  • Width 300

  • Height 300

  • X 10

  • Y 185

9.

Lock the Components layer.

10.

Select the Text layer.

11.

From the Tools menu, select the Text tool.

12.

Create three dynamic text fields and give each an instance name: prodTitle, prodDesc, and prodPrice. Make sure your prodDesc text field is mutiline.

13.

Create two static text fields and populate them with Description: and Price:

14.

Create two static text fields: Description and Price. Place them on the stage as pictured in Figure 23.7.

Figure 23.7. The Flash interface.


Now we have our interface set up and ready to go! Next, we can use ActionScript to apply the Flash Remoting results to some of our components and text fields. The great thing about Flash's capability to Test Movie is that you can view your progress as you build your movies and applications. During the following exercise, I encourage you to use Test Movie frequently to view your progress.

Comment the trace statement and add the following line:

 //trace(re.result); prodTitle.text = re.result; 

The preceding code populates the prodTitle dynamic text field with the string returned from our getTestConn() function. To view the outcome, Test Movie.

In our next task, we will use ActionScript to create a new method called getProducts(), which will call the getProducts function in our CFC. We will also create a ResultEvent and FaultEvent for the getProducts() call. This task is very similar to how we created the getTestConn() procedure.

Open your Actions panel and type the following after the closing brace (}) in the getTestConn_Fault() method:

 //Get the Products function getProducts(){ var products_pc:PendingCall = unleashedService.getProducts(); products_pc.responder = new RelayResponder(this,"getProducts_Result","getProducts_Fault"); } function getProducts_Result (re : ResultEvent){     DataGlue.bindFormatStrings (productsList, re.result, "#prodName#", "#ID#")      } function getProducts_Fault (fault:FaultEvent):Void{     trace ("error"); } 

The getProducts method creates a new PendingCall object for our getProducts service. It also creates a new RelayResponder object that redirects the results to either getProducts_Result or getProducts_Fault.

The getProducts_Result method handles the results from the SQL statement executed from the remote service. It receives the query results as a ResultEvent object. There are many ways to handle and manipulate data after it is returned to Flash. The DataGlue class is one methodit formats data to be used in many of the UI components, such as ListBox and ComboBox. The DataGlue parameters are as follows:

  • dataConsumer The UI component that will hold the data.

  • dataProvider The RecordSet(data) to populate the dataConsumer.

  • labelString The actual contents that the user will see in the UI component.

  • dataString The data that is associated with the labelString, hidden from the user.

The dataString parameter is vital in completing our application. It will be used to retrieve the rest of the data associated with that record. Refer to Figure 23.8.

Figure 23.8. ProductsLabel and Data values.


So, what does all of this mean? When the getProducts() method is called, it executes the following SQL statement from the CFC: SELECT ID,prodName FROM products ORDER BY prodName ASC. The data that is returned from this query is sent back to Flash and is caught by the getProducts_Result() method. The data is then treated as a ResultEvent object. The result property of the ResultEvent object, re.result, actually holds all the data in the form of a RecordSet. Using the DataGlue class, we can bind fields from the re.result to the productsList ListBox.

For our application to work, we need to add a line of code to our getTestConn_Result() method to see if the connection to Flash Remoting is successful. We want the application to execute the getProducts() method. Add the following line of code under prodTitle.text = re.result;:

 // Call the Products method getProducts(); 

At this point your code should look as follows:

[View full width]

import mx.remoting.Service; import mx.services.Log; import mx.rpc.RelayResponder; import mx.rpc.FaultEvent; import mx.rpc.ResultEvent; import mx.remoting.PendingCall; import mx.remoting.RecordSet; import mx.remoting.DataGlue; // Connect to the Gateway // Establish the Service var unleashedService : Service = new Service( "http://localhost/flashservices/gateway", new Log (Log.DEBUG), "unleashedCafeSite.unleashedCom", null, null); //Test the Connection function getTestConn () { //Create a PendingCall object var testConn_pc : PendingCall = unleashedService.getTestConn (); //Use the responder property to handle the success or failure testConn_pc.responder = new RelayResponder (this, "getTestConn_Result", "getTestConn_Fault"); } //Handle the Success function getTestConn_Result (re : ResultEvent) { //trace(re.result); prodTitle.text = re.result // Call the Products component getProducts(); } //Handle the Failure function getTestConn_Fault (fault:FaultEvent):Void { trace ("error"); } //Get the Products function getProducts () { var products_pc : PendingCall = unleashedService.getProducts (); products_pc.responder = new RelayResponder (this, "getProducts_Result", "getProducts_Fault"); } function getProducts_Result (re : ResultEvent) { DataGlue.bindFormatStrings (productsList, re.result, "#prodName#", "#ID#") } function getProducts_Fault (fault:FaultEvent):Void { trace ("error"); } //Start the Application getTestConn();

Test your movie; your application checks to see if the Flash Remoting connection is successful and then retrieves all the product names from the database and populates the ListBox (productsList). This is great, we are on our way! Next, we need to apply an event handler. When a user selects an item from the menu, we want to view the details about that particular item.

Type the following code above the //Start the Application comment:

 // Create an Event Handler for the ListBox var listBoxListener : Object = new Object (); this. listBoxListener.change = function () {     var prodID:Number = productsList.selectedItem.data;     getProductsDetails(prodID); } this.productsList.addEventListener ("change", listBoxListener); 

The preceding code listens for a change event for the ListBox and executes the statement within the function. The first line of code in the function retrieves the data that corresponds to the selected label and places it in a variable named prodID. (Remember, by using the DataGlue class, we are able to set the labelstring and datastring for the ListBox component.) Then it passes the value of prodID to a new method (that we have not created yet) called getProductsDetails(). For more information on the listenerObject, refer to the ActionScript Dictionary.

Next, we will create a new method called getProductsDetails(). This method will do the following:

1.

Create a new PendingCall object.

2.

Call our CFC unleashedCafeCom.getProductsDetails.

3.

The function within our CFC executes a query in the following SQL statement:

 SELECT * FROM products WHERE ID = #prodID#  

4.

The query returns the records to Flash. Flash will show the details within the interface.

5.

Now type the following code under the closing brace (}) of the getProducts_Fault() method:

[View full width]

//Get the Products Details function getProductsDetails (prodID) { var productsDetails_pc : PendingCall = unleashedService.getProductsDetails (prodID); productsDetails_pc.responder = new RelayResponder (this, "getProductsDetails_Result", "getProductsDetails_Fault"); } function getProductsDetails_Result (re : ResultEvent) { this.prodTitle.text = re.result.items[0].prodName; this.prodPrice.text = "$ " + re.result.items[0].prodPrice; this.prodDesc.text = re.result.items[0].prodDescription; var myImage:String = "images/" + re.result.items[0].prodImage + ".jpg"; this.imageHolder.contentPath = myImage; } function getProductsDetails_Fault (fault:FaultEvent):Void { trace ("error"); }

Now, let's look over the steps up to this point:

1.

Remote call to getTestConn.

2.

Success returned to getTestConn_Result().

3.

getTestConn_Result() makes a remote call to getProducts().

4.

Results returned to getProducts_Result().

5.

getProducts_Result() populates the ListBox.

6.

The ListBox event handler makes a remote call to getProductsDetails().

7.

getProductsDetails_Result() populates the Flash interface objects with data.

In the preceding code, the prodID parameter is made when a user selects a item in the ListBox. That prodID is then passed as a parameter to the function in our remote service, unleashedService.getProductsDetails(prodID). Now, the other functions in our CFC did not take any arguments, but this function must. Let's take a look at the function in the CFC:

 <! get all records associated with the selected product ID >     <cffunction name="getProductsDetails" access="remote" returnType="query" output="true">     <cfargument name="prodID" type="numeric">     <cfquery name="productDetailQuery" datasource="unleashedMenuData">     SELECT * FROM products WHERE ID = #prodID#     </cfquery>  <cfreturn productDetailQuery >     </cffunction> 

This CFC uses the <cfargument> tag. This tag passes the prodID to the SQL statement. If you look at the SQL statement SELECT * FROM products WHERE ID = #prodID#, you will notice that we are selecting everything from the products table that matches the ID that was selected from the ListBox. Refer to Figure 23.8.

If you take a look at our database design (refer to Figure 23.3), if a user selects Flash's Pancakes, which has an ID of four (4), the following items are returned, just for this one record: ID, prodName, prodDescription, prodPrice, and prodImage. This query is returned to Flash and is caught by the getProductsDetails_Result() method. This method takes the query, returns it as a RecordSet object, and places it in a ResultEvent object. Because re.result is a RecordSet object, to access these records individually, we need to utilize the items property of the RecordSet object. The items property is an array that contains all the data that was returned from the server. (For more information on arrays, refer to the ActionScript Dictionary.) So we could access all the items returned by using the following syntax:

 re.result.items[0].DATABASE FIELD NAME re.result.items[0].prodName; re.result.items[0].prodPrice; 

Figure 23.3. Database design and data.


So the following lines of code:

 this.prodTitle.text = re.result.items[0].prodName;     this.prodPrice.text = "$ " + re.result.items[0].prodPrice;     this.prodDesc.text = re.result.items[0].prodDescription;     var myImage:String = "images/" + re.result.items[0].prodImage + ".jpg";     this.imageHolder.contentPath = myImage; 

take the values received from the database and place them into the relating text fields and Loader component.

This may seem like a lot, but after you get the hang of it, it will be a breeze. Now if you select Test Movie, you will find that your ListBox is populated with data, but there is not a default description that is displayed with the first entry, ColdFusion's Country Eggs.

Add a line of code that will return the description for the first item in the ListBox. Put the following line of code inside the getProducts_Resut() method and under DataGlue.bindFormatStrings (productsList, re.result, "#prodName#", "#ID#").

 getProductsDetails(re.result.items[0].ID); 

This line will return the description and populate the Flash interface with data after the products are populated in the ListBox. That's it! Now, that wasn't so bad. All of your code in your Actions panel should look as follows:

[View full width]

import mx.remoting.Service; import mx.services.Log; import mx.rpc.RelayResponder; import mx.rpc.FaultEvent; import mx.rpc.ResultEvent; import mx.remoting.PendingCall; import mx.remoting.RecordSet; import mx.remoting.DataGlue; // Connect to the Gateway // Establish the Service var unleashedService : Service = new Service( "http://localhost/flashservices/gateway", new Log (Log.DEBUG), "unleashedCafeSite.unleashedCom", null, null); //Test the Connection function getTestConn () { //Create a PendingCall object var testConn_pc : PendingCall = unleashedService.getTestConn (); //Use the responder property to handle the success or failure testConn_pc.responder = new RelayResponder (this, "getTestConn_Result", "getTestConn_Fault"); } //Handle the Success function getTestConn_Result (re : ResultEvent) { //trace(re.result); prodTitle.text = re.result // Call the Products component getProducts(); } //Handle the Failure function getTestConn_Fault (fault:FaultEvent):Void { trace ("error"); } //Get the Products function getProducts () { var products_pc : PendingCall = unleashedService.getProducts (); products_pc.responder = new RelayResponder (this, "getProducts_Result", "getProducts_Fault"); } function getProducts_Result (re : ResultEvent) { DataGlue.bindFormatStrings (productsList, re.result, "#prodName#", "#ID#") getProductsDetails(re.result.items[0].ID); } function getProducts_Fault (fault:FaultEvent):Void { trace ("error"); } //Get the Products Details function getProductsDetails (prodID) { var productsDetails_pc : PendingCall = unleashedService.getProductsDetails (prodID); productsDetails_pc.responder = new RelayResponder (this, "getProductsDetails_Result", "getProductsDetails_Fault"); } function getProductsDetails_Result (re : ResultEvent) { this.prodTitle.text = re.result.items[0].prodName; this.prodPrice.text = "$ " + re.result.items[0].prodPrice; this.prodDesc.text = re.result.items[0].prodDescription; var myImage:String = "images/" + re.result.items[0].prodImage + ".jpg"; this.imageHolder.contentPath = myImage; } function getProductsDetails_Fault (fault:FaultEvent):Void { trace ("error"); } // Create an Event Handler for the ListBox var listBoxListener : Object = new Object (); this. listBoxListener.change = function () { var prodID:Number = productsList.selectedItem.data; getProductsDetails(prodID); } this.productsList.addEventListener ("change", listBoxListener); //Start the Application getTestConn();




Macromedia Flash Professional 8 Unleashed
Macromedia Flash Professional 8 Unleashed
ISBN: 0672327619
EAN: 2147483647
Year: 2005
Pages: 319

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