Article
Build A Web 2.0 Voting Widget With Flex: Part II
Building the Voting Interface
The first step in building the voting application is to get the list of topics and to pick one to vote on. The code below implements just that portion of the functionality, but it defines the entire web server API in the RemoteObject object:
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical"
creationComplete="voteRO.getTopics.send()">
<mx:Script>
<![CDATA[
private var topicID:int = 0;
private function onGetTopics() : void {
var topicind:int = Math.round( Math.random() * voteRO.getTopics.lastResult.length );
if ( topicind >= voteRO.getTopics.lastResult.length )
topicind = voteRO.getTopics.lastResult.length - 1;
var topic:Object = voteRO.getTopics.lastResult[ topicind ];
topicID = topic.id;
topicText.text = topic.text;
}
]]>
</mx:Script>
<mx:RemoteObject id="voteRO"
endpoint="http://localhost/amfphp/gateway.php"
source="votes2.VoteService2" destination="votes2.VoteService2"
showBusyCursor="true">
<mx:method name="getTopics" result="onGetTopics()" />
<mx:method name="getOptions">
<mx:arguments><mx:Topic /></mx:arguments>
</mx:method>
<mx:method name="addVote">
<mx:arguments><mx:Topic /></mx:arguments>
</mx:method>
</mx:RemoteObject>
<mx:Label fontSize="20" id="topicText" />
</mx:Application>
There’s a lot here that we’ve seen from the original examples in the first article, but it does contain a lot more ActionScript code than any of the previous examples. Let’s start with what’s familiar.
The <mx:RemoteObject> is exactly the same as the one we had in the first article, with the exception that I’ve added a few more methods, and two of those methods have arguments. The <mx:Label> tag at the bottom will present the text of the question.
Now, the ActionScript code may look daunting, but it’s relatively straightforward. The onGetTopics method is called in response to a successful call to the getTopics function on the web server. The method takes the topics that were returned and picks one at random using the Math.random method. The code then sets the text of the table to the text of the topic.
The relationship between the getTopics method on the RemoteObject and the onGetTopics method in the application is worth our attention. Web services calls in Flex are asynchronous. In fact, just about everything in Flex is asynchronous and event-based. When you call the send method on getTopics, it returns immediately. Flex then asynchronously makes the call to the web server, gathers the response, and fires the result method which, in this case, calls the onGetTopics method. There’s also a callback for a web services fault, which I don’t specify in this example.
Back to the example, though. Running this should result in something that looks like this.
![]()
If you have added more topics to the database, you should see one of those topics chosen at random. The data set that I put in the MySQL code just had one topic, and we see that in the figure above.
Now, the next trick is for us to build an interface that allows the user to select one of the options. A conventional interface would consist of a set of radio buttons followed by a Submit button. But for a casual voting system like this, it may be just as easy to present a bunch of buttons, where clicking on one registers a vote. We’ll take that approach here.
The MXML code below, all of which is additional to the previous example, dynamically creates buttons for each of the options and adds them to the Application’s container:
<?xml version="1.0" encoding="utf-8"?>
<mx:Application ...>
<mx:Script>
<![CDATA[
import mx.controls.Alert;
import mx.controls.Button;
private var topicID:int = 0;
private function onGetTopics() : void {
// ...
voteRO.getOptions.send( topicID );
}
private function onGetOptions() : void {
for each( var opt:Object in voteRO.getOptions.lastResult ) {
var optBut:Button = new Button();
optBut.label = opt.text;
optBut.data = opt.id;
optBut.percentWidth = 100;
optBut.addEventListener( MouseEvent.CLICK, onOptionButtonClick );
addChild( optBut );
}
}
private function onOptionButtonClick( event:Event ) : void {
voteRO.addVote.send( event.currentTarget.data );
mx.controls.Alert.show( 'You successfully voted for ' + event.currentTarget.label );
}
]]>
</mx:Script>
<mx:RemoteObject id="voteRO" ...>
...
</mx:RemoteObject>
<mx:Label fontSize="20" id="topicText" />
</mx:Application>
Our original code remains unchanged, except for the addition of the call to getOptions in the onGetTopics method. When getOptions is finished successfully it calls onGetOptions, which creates a Button class for each of the options and adds it to the Application’s container. It also registers the onOptionButtonClick method to respond to mouse clicks on the newly created button.
These two methods, addEventListener and addChild, are fundamental to Flex. Almost every object in the Flex framework posts messages when it changes state. To listen for these messages, call addEventListener and specify the message for which you want to listen, and the method to call when that message is fired.
NOTE: Use the EventDispatcher to Publish Events
The messaging model discussed above is implemented by the EventDispatcher base class, and uses the dispatchEvent method. If you wish to create an object that publishes events, you’ll need to ensure that your object inherits from the EventDispatcher class to do so.
The addChild method is the cornerstone method of the Flex framework’s visual hierarchy. Just like an HTML document, the Flex application’s visual hierarchy can be represented by a tree. The root container is almost always the Application object. Within that, you can have containers and controls and so on, and in turn, almost every container or control supports child controls or containers. You can add child controls (as I’ve done in the code above) using addChild, and you can remove children with the removeChild and removeAllChildren methods.
Okay, with that mini-primer on Flex out of the way, let’s take a look at what happens when we launch this code from Flex Builder—check out this figure.
![]()
The figure shows that the application picked a question and put up buttons for each of the different options. The user can then respond to the poll by clicking one of the buttons, as demonstrated in this next figure.
![]()
Clicking one of these buttons calls the onOptionButtonClick, which in turn calls the addVote function on the server. The application also displays a nifty message box to inform the voter that the vote has been counted.