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:
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.
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:
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:
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:
Now, let's look over the steps up to this point:
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:
|