Charlie Key

Modified
10 December 2007
Prerequisite knowledge
To understand and make use of this tutorial, you should have built simple Flex applications before, and have a basic understanding of HTML and JavaScript.
 
User level
Beginning
Required products
Flash Builder (Download trial)
Sample files

Note:
This article was created based on the Flex 3 beta releases. Minor changes in the description and code may be necessary before it can be applied to Flex 3.
 
When building web applications or websites, you will encounter many instances in which JavaScript is needed and used. These are usually in rich Internet applications (RIAs) that are built using many different techniques. One great example of an RIA that has many different components is Google Finance. In the Google Finance site, you will notice that HTML, CSS, JavaScript, and Flash all work together to make a seamless user interaction. But what you don't see is the glue that holds these together; and that is what this article is going to talk about and show. This article goes into detail about communicating between Flex and JavaScript using the ExternalInterface API. So sit back and enjoy this tutorial as it explains the basics of creating these multiple component web applications using JavaScript as the glue that holds them together.
 

 
Flex and JavaScript: an example application

The application shown here gives you a little taste of what can be done between JavaScript and Flex. You can add people to the Flex application using the small form on the bottom right through JavaScript, and if you select a person in the Flex app and click the "JavaScript Display" button, you will get the info back out to the small form on the top right.
 
<style type="text/css"> table.sample { width: 225px; border-width: 1px; border-spacing: 2px; border-style: dotted; border-color: gray; border-collapse: collapse; background-color: white; } table.sample td { font-size: 9px; border-width: 1px; padding: 5px; border-style: dotted; border-color: gray; -moz-border-radius: 0px 0px 0px 0px; text-align: left; } </style> <script language="javascript"> // Internet Explorer and Mozilla-based browsers refer to the Flash application // object differently. // This function returns the appropriate reference, depending on the browser. function getFlexApp(appName) { if (navigator.appName.indexOf ("Microsoft") !=-1) { return window[appName]; } else { return document[appName]; } } function displayPerson(person) { if(person == null){ alert("Please select a person, or maybe I screwed up."); } else{ document.getElementById('nameDisplay').innerHTML = person.Name; document.getElementById('ageDisplay').innerHTML = person.Age; document.getElementById('sexDisplay').innerHTML = person.Sex; } } function addPerson() { var name = document.getElementById('txtName').value; var age = document.getElementById('txtAge').value; var sex = document.getElementById('selSex').value; getFlexApp('FlexJSTutorial').addPerson(name, age, sex); } </script> <center> <object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" id="FlexJSTutorial" width="482" height="348" codebase="http://fpdownload.macromedia.com/get/flashplayer/current/swflash.cab"> <param name="movie" value="http://blog.paranoidferret.com/files/JSTutorial.swf" /> <param name="quality" value="high" /> <param name="bgcolor" value="#869ca7" /> <param name="allowScriptAccess" value="always" /> <embed src="http://blog.paranoidferret.com/files/JSTutorial.swf" quality="high" bgcolor="#869ca7" width="482" height="348" name="FlexJSTutorial" align="middle" play="true" loop="false" quality="high" allowScriptAccess="always" type="application/x-shockwave-flash" pluginspage="/go/getflashplayer"> </embed> </object> <br><br> <table class="sample"> <tr><td style="font-size: 11px;font-weight:bold;text-align: center;border-width: 1px;padding: 3px;border-style: dotted;border-color: gray;-moz-border-radius: 0px 0px 0px 0px;">Data coming into Javascript</td></tr> <tr><td> <table width="100%" style="border-spacing:5px;"> <tr><td>Name:</td><td id="nameDisplay" style="width:150px;">&nbsp;</td></tr> <tr><td>Age:</td><td id="ageDisplay" style="width:150px;">&nbsp;</td></tr> <tr><td>Sex:</td><td id="sexDisplay" style="width:150px;">&nbsp;</td></tr> </table> </td></tr> <tr><td style="font-size: 11px;font-weight:bold;text-align: center;border-width: 1px;padding: 3px;border-style: dotted;border-color: gray; -moz-border-radius: 0px 0px 0px 0px;"> Data sending from Javascript </td></tr> <tr><td> <table style="border-spacing:5px;" width="100%"> <tr><td style="border-style:none;padding:0px;">Name:</td> <td style="border-style:none;padding:0px;"><input id="txtName" type="text" /></td></tr> <tr><td style="border-style:none;padding:0px;">Age:</td><td style="border-style:none;padding:0px;"><input id="txtAge" type="text" /></td></tr> <tr><td style="border-style:none;padding:0px;">Sex:</td> <td style="border-style:none;padding:0px;"><select id="selSex" style="width:100px;"><option value="Male">Male</option><option value="Female">Female</option></select></td> </tr> <tr><td colspan="2" style="border-style:none;padding:0px;"><input type="button" id="butAddPerson" onclick="addPerson()" value="Add Person" /></td></tr> </table> </td></tr> </tbody> </table> </center>

 
Creating a Flex user interface

The very first thing to do is to set up a basic Flex application; the code below represents the closest to the simplest interface possible. This sets up an application with specified height and width and also adds the View Source option to the movie, with the source file specified by the viewSourceURL attribute.
 
<?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" width="482" height="348" viewSourceURL="../files/JSTutorial.mxml"> </mx:Application>
The next step in the process is to set up a simple Flex interface with no functionality built in. You now add a panel into the application and give it a title. Next you add a DataGrid object that will be bound to the datam which will be defined later. In the DataGrid you add a couple of columns (DataGridColumn); take notice to the dataField names, as they will define the keys for the incoming data. So in this case, the data coming in should have values from three keys: "Name", "Age" and "Sex". You will also add a button, which will later be used to call a JavaScript function on the page. Lastly you will add a label to give yourself a quick status update when sending the data to JavaScript. You also give each of the UI components an id attribute so that you can refer to them later. All this code goes inside the <mx:Application> tags.
 
<mx:Panel id="pnlMain" x="10" y="10" width="462" height="328" layout="absolute" title="Simple Javascript Interaction"> <mx:DataGrid id="dgPeople" x="10" y="10" width="422" height="229"> <mx:columns> <mx:DataGridColumn headerText="Name" dataField="Name"/> <mx:DataGridColumn headerText="Age" dataField="Age"/> <mx:DataGridColumn headerText="Sex" dataField="Sex"/> </mx:columns> </mx:DataGrid> <mx:Button x="10" y="256" label="JavaScript Display" id="butJSDisplay" /> <mx:Label x="149" y="260" id="lblMessage"/> </mx:Panel>
At this point you should be able to compile and run the app to see your small interface.
 

 
Setting up the data

Next, you need to get some data into your DataGrid, and you are going to do this with a small bit of ActionScript 3.0 . First, you attach a function call to the DataGrid's initialize event. So your new DataGrid opening tag looks like this:
 
<mx:DataGrid id="dgPeople" x="10" y="10" initialize="initDG()" width="422" height="229">
Now, to go along with the event, you need to write the actual function to which it refers. The first thing you need to do is add a <mx:Script> tag to the application; then, you can start writing the function. You can also add an import call so that you can use ArrayCollection.
 
Inside the function initDG you do a little bit of data creation. You create an array for the data, and then push a few items onto the array. You can use the {key1: "value1", key2: "value2"...} syntax to add an associative array for each item. Next you need to make sure the keys match the ones you used for the DataGridColumns so that the DataGrid knows what columns to associate with what values. Once that's done, you need to create an ArrayCollection to bind to and stick the array in it. And the last thing you do is bind the dgPeople (DataGrid) to the ArrayCollection and set the initial selected index. So, this gives you the following code for the script, and this code goes right below the <mx:Application> opening tag.
 
<mx:Script> <![CDATA[ import mx.collections.ArrayCollection; public function initDG():void { var people:Array = new Array(); people.push({Name: "Charlie", Age: "23", Sex: "Male"}); people.push({Name: "Brandon", Age: "23", Sex: "Male"}); people.push({Name: "Mike", Age: "23", Sex: "Male"}); people.push({Name: "Caroline", Age: "23", Sex: "Female"}); var peopleCollection:ArrayCollection = new ArrayCollection(people); dgPeople.dataProvider = peopleCollection dgPeople.selectedIndex = 0; } ]]> </mx:Script>
Okay, you again should be able to compile and run the application, and now there should be data in your DataGrid.
 

 
Setting up Flex to send data to JavaScript

Next up is sending this data to JavaScript. This is pretty easy to do. To start off, you need to add a click event to the button to call an ActionScript function. Below is the new modified button tag.
 
<mx:Button x="10" y="256" label="JavaScript Display" id="butJSDisplay" click="jsDisplayPerson()"/>
Now, to make this button work, you need to add that jsDisplayPerson() ActionScript function. This starts to get into the fun stuff now: to call JavaScript functions in Flex, you use the ExternalInterface API. You can learn more information about it on the Flex Documentation Site. Basically, it enables us to build wrappers to call JavaScript functions from Flex and vice versa.
 
You add the ActionScript function in the <mx:Script> tags, and you also need to add an import statement for "flash.external.*". There is not much to the function itself: first you check to see if there is an ExternalInterface available (basically, this makes sure the Flex application is in an HTML page). If the .swf file is embedded into an HTML page you can make the magic happen with a call to ExternalInterface.call. You then send the information to a JavaScript function called displayPerson whose argument is the selectedItem in your DataGrid. Now this should send an array of data of the selectedItem to JavaScript. To learn more about what can be sent to JavaScript, check out this Adobe Documentation page. Last, you update the status label saying that the data was sent. Otherwise, if the ExternalInterface is not available, you display an error message in the label. Now the <mx:Script> tag looks like this:
 
<mx:Script> <![CDATA[ import mx.collections.ArrayCollection; import flash.external.*; public function initDG():void { var people:Array = new Array(); people.push({Name: "Charlie", Age: "23", Sex: "Male"}); people.push({Name: "Brandon", Age: "23", Sex: "Male"}); people.push({Name: "Mike", Age: "23", Sex: "Male"}); people.push({Name: "Caroline", Age: "23", Sex: "Female"}); var peopleCollection:ArrayCollection = new ArrayCollection(people); dgPeople.dataProvider = peopleCollection; dgPeople.selectedIndex = 0; } public function jsDisplayPerson():void { if (ExternalInterface.available) { ExternalInterface.call("displayPerson", dgPeople.selectedItem); lblMessage.text = "Data Sent!"; } else lblMessage.text = "Error sending data!"; } ]]> </mx:Script>

 
Using JavaScript and HTML to display data

Now you get to write a bit of JavaScript code to display the person that is being sent from Flex. So, in a set of JavaScript tags you create the displayPerson function—remember, the name has to match perfectly to what you told the ExternalInterface.call function in Flex to call. The first thing you do in your JavaScript function is make sure you are not getting a null object; and if it is null, you will display an alert. Then you can just use the object passed as a JavaScript object and reference the appropriate DataGrid columns using JavaScript object property syntax. All you are going to do with them is display the values in a few table cells, but at this point you can do anything you want with the data. So, in the HTML <script> tags, the code looks like this:
 
function displayPerson(person) { if(person == null){ alert("Please select a person, or maybe I screwed up."); } else{ document.getElementById('nameDisplay').innerHTML = person.Name; document.getElementById('ageDisplay').innerHTML = person.Age; document.getElementById('sexDisplay').innerHTML = person.Sex; } }
So then, if you add a little bit of HTML like this next snippet, you will populate a few table cells. You should be able to embed the resulting compiled .swf file, but take notice that you need to have the allowScriptAccess property in the object and embed tags for the movie before the "JavaScript Display" button works. You can check the source of this page if you need more info.
 
<table> <tr> <td>Name:</td> <td id="nameDisplay" style="width:150px;">&nbsp;</td> </tr> <tr> <td>Age:</td> <td id="ageDisplay" style="width:150px;">&nbsp;</td> </tr> <tr> <td>Sex:</td> <td id="sexDisplay" style="width:150px;">&nbsp;</td> </tr> </table>
Now you should be able to call any JavaScript functions from your Flex applications using the above technique.
 

 
Calling Flex functions from JavaScript

The next thing you are going to do is set up your Flex application so that Flex functions can be called by JavaScript via ExternalInterface.
 
The first thing you need to do is add some code to the application startup to initialize what Flex functions will be accessible through external calls. You add code to the <mx:Application> tag to fire a function on the initialize event. The following code is the new application tag. It simply calls an ActionScript function when the initialize event is fired.
 
<mx:Application xmlns:mx="/2006/mxml" layout="absolute" width="482" height="348" initialize="initApp()" viewSourceURL="../files/JSTutorial.mxml">
Now you can write the initApp ActionScript function. This function will check if the ExternalInterface is available to keep from getting errors when running in the regular old Flash player. Then it adds a callback for an ActionScript function: this function will be referred to externally as addPerson (the first argument to addCallback) and will map to the internal function called addPerson (the second argument to addCallback). The initApp function should then look like the code below, which is added in the ActionScript <mx:Script> tags.
 
public function initApp():void { if (ExternalInterface.available) ExternalInterface.addCallback("addPerson", addPerson); }
Now the only thing left to do in the Flex application is create the function addPerson(), which will add people to your DataGrid. This function takes three arguments: a string each for the name, age, and sex of the new entry. Now, to add an item, you take the current Items in the DataGrid and cast them as an ArrayCollection, and then add a new item using the data you passed in. Again, this is an ActionScript function, so you need to put it in the ActionScript <mx:Script> tags.
 
public function addPerson(name:String, age:String, sex:String):void { (dgPeople.dataProvider as ArrayCollection).addItem( {Name: name, Age: age, Sex: sex}); }
Now that you have the MXML and ActionScript written, you can create some HTML and JavaScript to use the new external Flex function. The JavaScript function you are going to make will just grab a few values from a couple of input items on your HTML page, and then it will call the Flex function using those values as arguments. In order to call the Flex function, you'll use another function called getFlexApp('FlexJSTutorial'). I will go over this in just a second. So what is added to the JavaScript tag is the following code:
 
function addPerson() { var name = document.getElementById('txtName').value; var age = document.getElementById('txtAge').value; var sex = document.getElementById('selSex').value; getFlexApp('FlexJSTutorial').addPerson(name, age, sex); }
So now you are wondering about this getFlexApp function—well, this is the function that actually returns the Flex app that is on the page.
 

 
Wrapping up

I originally had an issue getting the embedded object, but found the suggested solution on Adobe's site. This function takes into account various types of browsers. The one thing you need to do is make sure your object and embed tags for your .swf file have id and name attributes. These are required for getting the Flex application. So the following function goes in the JavaScript tag:
 
// This function returns the appropriate reference, // depending on the browser. function getFlexApp(appName) { if (navigator.appName.indexOf ("Microsoft") !=-1) { return window[appName]; } else { return document[appName]; }
The last thing you are going to do is create the HTML inputs that are used in the JavaScript addPerson function. This includes two input text boxes and one input select with two options, one for "Male" and one for "Female". There's nothing special about these. Also, there is a button that is used to call the JavaScript function when the onclick event occurs. These are all put in a table for a little bit of organization:
 
<table style="border-spacing:5px;"> <tr> <td style="border-style:none;padding:0px;">Name:</td> <td style="border-style:none;padding:0px;"> <input id="txtName" type="text" /> </td> </tr> <tr><td style="border-style:none;padding:0px;">Age:</td> <td style="border-style:none;padding:0px;"> <input id="txtAge" type="text" /> </td> </tr> <tr><td style="border-style:none;padding:0px;">Sex:</td> <td style="border-style:none;padding:0px;"> <select id="selSex" style="width:100px;"> <option value="Male">Male</option> <option value="Female">Female</option> </select> </td> </tr> <tr> <td colspan="2" style="border-style:none;padding:0px;"> <input type="button" id="butAddPerson" onclick="addPerson()" value="Add Person" /> </td> </tr> </table>
And that about wraps it up.
 

 
Where to go from here

After learning how to use JavaScript and Flex together, you may still be looking for more information on how to use Flex and what can be done with it. Here on the Adobe site you can find tons of tutorials and articles on building applications using Flex. I also recommend checking out Flex.org and looking over what they have available for resources; they also have some great examples on their site. Another great site for Flex tutorials is http://blog.paranoidferret.com. If you are looking to build more advanced Flex and JavaScript applications I would advise taking a look at the Flex Ajax Bridge (FABridge); note that FABridge has to be used with Flex 3 or higher. Finally, don't forget about Adobe's new application environment, Adobe AIR, which is a great platform on which to build applications.