Flex Question: How do I render a grid row differently based on data?
Wow. So this is one of those questions that I would have sworn would be easy in Flex. The Flex Datagrid has really nice support for handling custom display of cells. But while Flex makes it easy to say, "Do this to a cell when rendering", doing something for an entire row was definitely not as easy. I want to thank Andrew Powell for a lot of help with this blog entry. Any mistakes you see are entirely my fault though, not his.
Please Read: Help Tim Buntel and Flex 4
I wanted to make sure my readers took the time to read Tim Buntel's latest blog post: Desperately Seeking Debbie The title may seem a bit risque, but don't be worried. Tim is looking for help from a type of developer that I think matches a large portion of my audience. If you haven't had a chance yet to look much at Flex 4, and have time in the next few days, please be sure to follow the directions on his blog post.
I'm going to be a bit vague here but let me just say that I think this is pretty important. If you can make the time and meet the persona, please contact Tim. Thank you!
Follow up - Flash Builder 4, ColdFusion CFCs, and AIR
I've done a few blog entries recently showing simple examples of connecting to a ColdFusion CFC via Flex. My last blog entry demonstrated this using Flash Builder 4. A reader there asked me to create an example of this in AIR. It just took a few minutes, so let me walk you through the process (and please forgive me but let me give the normal disclaimer, I'm new to Flex, blah blah blah).
Simple example of accessing ColdFusion data with Flex (now with Flash Builder 4)
Last week I wrote up a quick blog entry demonstrating how to talk to ColdFusion via Flex. It wasn't meant to be the complete guide to Flex/ColdFusion development, but more a simple example to demonstrate how easy it is. Tonight I took a look at Flash Builder 4 and the support it has for working with data services. Here is what I found (and once again, I'll remind folks that I'm learning Flash Builder 4 and Flex 4 so please forgive any dumb mistakes).
I created a new Flex project called TestFB4, selected Web for the Application type, and ensured ColdFusion Flash Remoting was selected in the Server technology section.

The next page will ask you to confirm your ColdFusion settings. (I assume you know what to do there.)
Once done, you should end up with a simple, empty, Flex file. I took the simple button and text field from my first example in the last blog post and just pasted it into my document:
<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark" xmlns:mx="library://ns.adobe.com/flex/halo" minWidth="1024" minHeight="768">
<mx:Button label="Talk to ColdFusion" />
<mx:TextArea id="resultBox" />
</s:Application>
Unfortunately this won't quite work right. Switch to Design View and you see:

What the heck? I see the TextArea but not my button. I then noticed that there was no layout attribute in the core Application tag. One of the things that changed in Flex 4, specifically in the Spark components, is the layout stuff. You can't just use layout="vertical", but instead must declare it using a child tag:
<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark" xmlns:mx="library://ns.adobe.com/flex/halo" minWidth="1024" minHeight="768">
<s:layout>
<s:VerticalLayout/>
</s:layout>
<mx:Button label="Talk to ColdFusion />
<mx:TextArea id="resultBox" />
</s:Application>
My understanding, and let me stress here, it's just my understanding, is that this reflects the fact that layout is now handled by a component. Hence the lack of a simple layout="string" argument. If you have seen my Twits, you know I'm still a bit overwhelmed by the changes in Flex 4, so, let's just move on and ensure that works. A quick click back to Design mode shows that it does:

Ok, now for the fun part. I still had my CFC from the last entry. It was called testa and contained two methods, echotest and hellotest. How difficult is it to get FB4 hooked up to this?
First, ensure you see the Data/Services view. If you don't, go to Window, Show View, Data/Services. If you don't see it there, click Other and it will be under Flash Builder. (I'm confused - is it Flash Builder or FlashBuilder?) Mine looks like this:

Click on Connect to Data/Service and note that ColdFusion is selected first:

On the next screen, the Service Name is simply a reference to the remote CFC. In the last blog entry I had made a RemoteObject tag named cfservice. That's a bit vague, but I'll go ahead and use it again. Import CFC should be selected. I hit the Browse button to pick my testa file.

When you click next, you will be asked to enter your RDS info. After you do that, it should (hopefully!) parse your CFC data and display the methods:

Click Finish and you will notice the following warning:

This seems a bit odd, especially if you look over in the Data/Services panel and see...

My guess is that the String you see here is from the CFC file, and Flash Builder is simply saying, "Yes, I know you sya you return a string, but maybe you return some weird, freaky, non-standard string that will make me unhappy and slightly gassy." Fair enough. Right click on both operations (I'm only using one now) and click Configure Return Type. Select Use an Existing ActionScript or custom data type and pick String from the drop down. After you do that, notice the grey balls next to the method now become green balls. Not terribly obvious, but, I'll get used to it.

Ok, now for the cool part. Ensure you are still in design mode. Click on echotest and simply drag it to your button. You should see a green + when over the button. That's it. If you switch to Source view you can see what it did:
<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark" xmlns:mx="library://ns.adobe.com/flex/halo" minWidth="1024" minHeight="768" xmlns:cfservice="services.cfservice.*">
<fx:Script>
<![CDATA[
import mx.controls.Alert;
protected function button_clickHandler(event:MouseEvent):void
{
echotestResult.token = cfservice.echotest();
}
]]>
</fx:Script>
<s:layout>
<s:VerticalLayout/>
</s:layout>
<fx:Declarations>
<s:CallResponder id="echotestResult"/>
<cfservice:Cfservice id="cfservice" destination="ColdFusion" endpoint="http://localhost:80/flex2gateway/" fault="Alert.show(event.fault.faultString)" showBusyCursor="true" source="testa"/>
</fx:Declarations>
<mx:Button label="Talk to ColdFusion" id="button" click="button_clickHandler(event)"/>
<mx:TextArea id="resultBox" />
</s:Application>
That's a lot of code written for me! Of course, you may be thinking - we tied the method to the button, but we want the result to show in the box, right? Surely we have to type, right? Nope! This really surprised me. Switch back to the Design mode, and drag echotest again, but this time, drop it on the TextArea.
Note that you get a prompt now:

If you switch to Existing call result, you will have linked it up to the service call we created by dragging onto the button.
And that's it. Run it, click the button, and it just plain works.

Hopefully you guys are impressed by this, I am. The blog entry ended up being a lot longer than I expected, but mainly because of the screen shots. When I tried this the first time, it took about 60 seconds.
Simple example of accessing ColdFusion data with Flex
About a week ago I exchanged a few emails with Susan. She was learning Flex, and while she thought she understood the basic UI stuff (layout, widgets), she was having a real hard time grokking the basics of using ColdFusion Components with Flex. I whipped up a quick demo for her that was as simple as possible and I thought I'd share it on the blog. Please note that Flex, like ColdFusion, provides multiple ways of doing things, so this code could probably be done in many other ways.
Flex4/FlashBuilder4/Flash Catalyst Links
It's been a busy day. I've twittered/re-tweeted a bunch of these links, but thought I'd do a quick blog entry concerning some links that I think may be important for folks taking a look at the new goodness released today on Adobe Labs. Most likely some of these links repeat the same content, but I hope folks find it helpful.
- First off, check out this video by Tim Buntel: Flash Builder 4 (is it FlashBuilder or Flash Builder?) beta 4 for ColdFusion developers. It is a 12 minute video that you can easily watch during your lunch hour covering stuff specifically for ColdFusion developers.
- This next article, Network Monitor in Flash Builder 4 covers the... wait for it... I'm about to say it... the Network Monitor. Ok, sorry for the silliness. This is, without a doubt, one of the cooler parts of Flash Builder 4. It totally removes the need for tools like ServiceCapture or Charles.
- If you are like me, you may be a bit overwhelmed by the changes in Flex 4. This article: Differences between Flex 3 SDK and Flex 4 SDK beta can help you digest some of what has changed. Personally I'm finding the namespace changes to be quite significant. I'm going to have to digest this a bit before I really get it.
- This is probably a bit of a repeat, but there is a Dev Center at Adobe just on ColdFusion and Flex: Learn Flex and ColdFusion
- Check out these tutorials from Adobe Labs.
- Lynda.com, AKA the people who turned me down (not that I'm bitter, really!) announced free video tutorials on Flash Catalyst. More information may be found here: http://www.lynda.com/flashcatalyst
- Next - while this isn't a "Learning" type link, I wanted to share it. Ted Patrick is looking for community involvement in creating Catalyst skins. I sent him one, but I think it melted his computer. (Keep me away from design toools!) More information on his blog post: Where community and Catalyst meet
That's it for now. My plans are to review the changes in Flex 4 and hopefully write up a more detailed blog post. As I said, it is a bit overwhelming. But folks - now is the time. The Flex/Flash platform looks incredible now. If you are one of those ColdFusion folks who haven't taken the chance to learn Flex, now is the time. Do it. And if I can help in any way, let me know.
Flash Builder 4 and Flash Catalyst hit Labs
The title says it all. The public betas of FlexFlash Builder 4 and Flash Catalyst have just hit Adobe Labs. You can download them right now!

More playtime with Flex, AIR, ColdFusion, and Flex Messaging
Since I wrapped GameOne, and begun work on GameTwo, I've been thinking a lot about messaging about AIR/ColdFusion applications. I had an idea today for a simple application. Imagine your web site sells widgets. Every time you sell a widget, your boss wants an alert. You could easily use email, but emails tend to get ignored. How about writing a quick AIR application instead?
Liked GameOne? Want to learn more about BlazeDS/ColdFusion/Flex/AIR?
Just wanted to give a quick shout out to Aaron West and his blog entry on a class he will be giving at CFUNITED this year:
AIR Messaging: Integrating AIR, BlazeDS, and ColdFusion
I blogged about this myself recently with the release of my first proof of concept game built using AIR/Flex/CF/BlazeDS. I've got to say this is very exciting stuff. If you are attending CFUNITED, be sure to check out his talk. (I know I will be, if I'm not speaking at the same time.)
Code and Design of Gameone
So now that I'm done enjoying Festival International, I thought I'd do a quick write up about the code behind Gameone, the POC (proof of concept) AIR/Flex/Blaze/ColdFusion multiplayer game I released last week. I want to be sure folks remember that this is probably quite far away from 'Best Practice'. It was a learning experience for me, so please keep that in mind while reviewing the code and reading my comments. I've attached the full source code to both the front end and the server side. Note that the ColdFusion code was written very quickly and would benefit from ColdSpring. Anyway, enough with the foreplay, let's get down to it.
As I mentioned, the front end was built with Flex and AIR. I learned a heck of a lot while at Broadchoice. One of the tools we used there was the Swiz framework created by Chris Scott. Swiz helps solve one of the biggest issues I had with Flex - events. I don't mean stuff like click handlers for buttons, but more... communication between multiple files. Flex, then language, is pretty simple. But I found that once I got into multiple files, it became difficult for me to understand how best to have them work with even other.
Swiz let me set up the application almost like a Model-Glue/ColdSpring site. I created folders for the major sections of the application (which for me was just application and authentication) and within each I set up controller, model, and view folders. Swiz let me inject (copy in) code from one part of the application into another. For example, this line of code from the file that renders the Buy/Sell portion:
[Autowire(bean="stockController")]
public var stockController : StockController;
Swiz finds the controller via a Beans file that contains the stockController:
<!-- stock controller -->
<stockControl:StockController id="stockController"/>
I was also able to define my remoteObject here:
<mx:RemoteObject id="authenticationService" destination="ColdFusion" source="remoteservices.authenticationService"
showBusyCursor="true" channelSet="{myAmfChannel}" />
As for events, I can define both listeners and broadcasts as well - very much like ModelGlue. So for example, I want my register form to listen for a 'registration failed' event so it could tell people when their registration failed:
Swiz.addEventListener(AuthenticationController.REGISTRATION_FAILED, registrationFailed)
The flip side, broadcasting an event, is also trivial:
private function getStockPricesResult(result:ResultEvent):void {
var event:DynamicEvent = new DynamicEvent(StockController.STOCKS_LOADED)
trace('back from get stocks')
var stockData:ArrayCollection = result.result as ArrayCollection
event.stockData = stockData
Swiz.dispatchEvent(event);
}
Swiz does a heck of a lot more than what you will see in the code, but I can't describe how much of a relief it was to have this framework. It removed what was probably the biggest barrier to my Flex development.
The other interesting aspect was the integration with BlazeDS. Well, not terribly interesting. The code actually is pretty trivial. The server setup was the worst part. (I talked about it more here.) The Flex code for chatting came down to something like 10 lines of code. So for example, to tell the app to listen to and broadcast to the server begins with two declarations:
<mx:Producer id="producer" destination="ColdFusionGateway" channelSet="{myAmfPollingChannel}" fault="Alert.show(event.faultDetail)"/>
<mx:Consumer id="consumer" message="handleMessage(event)" channelSet="{myAmfPollingChannel}" destination="ColdFusionGateway" />
Sending a chat is just:
private function sendMessage():void {
if(chatMsg.text == '') return
var msg:AsyncMessage = new AsyncMessage();
msg.headers.gatewayid = 'GameOne';
msg.body = { msg : chatMsg.text, user : authController.currentUser.username };
producer.subtopic='chat'
producer.send(msg);
chatMsg.text=''
}
And code to handle listening (with the consumer) is first this in the init():
private function init():void {
consumer.subtopic='chat'
consumer.subscribe();
}
and this for handling the actual message:
private function handleMessage(e:MessageEvent):void{
var body :Object = e.message.body
if(body.user != null) {
chatWindow.htmlText = '<b>['+fmtDate.format(body.timestamp)+'] '+body.user + ' says: ' + body.msg + '</b>\n' + chatWindow.htmlText;
} else chatWindow.htmlText = '['+fmtDate.format(body.timestamp)+'] ' + body.msg + '\n' + chatWindow.htmlText;
}
Most of the code here is UI crap, and I think you can see that there really isn't a lot here. The one thing I'd point out is the subtopics. This is basically a 'filter' for the messages sent back and forth between the server. My game had 2 types of communications - stock updates and chat. So I simply used a different channel for each. The stock data view has a consumer as well:
stockConsumer.subtopic='stockupdate'
stockConsumer.subscribe();
Because it uses a different subtopic, it will ignore the chat messages going back and forth.
This is probably a good time to switch to the server side. The ColdFusion code is rather simple. I'll only point out the stuff specific to messaging. Stock updates are run every minute and cover both the actual price updates (which is game logic and I'll leave to those who download the code) and messaging. Here is the actual remote call invoked by the CF Scheduler.
<cfset application.stockService.updateStocks()>
<cfset application.messageService.notifyStockUpdate(application.stockService.getStockPrices())>
The updateStock methods changes the prices and the messaging service will handle the broadcast.
<cffunction name="notifyStockUpdate" access="public" returnType="void" output="false">
<cfargument name="stockdata" type="any" required="true">
<cfset var packet = StructNew()>
<cfset packet.body = {}>
<cfset packet.body["data"] = arguments.stockdata>
<cfset packet.destination = "ColdFusionGateway">
<cfset packet["headers"]["DSSubtopic"] = "stockupdate" />
<cfset SendGatewayMessage("GameOne", packet)>
</cffunction>
To be honest, I don't remember where I found the docs that said I should use "DSSubtopic" but it works. The last piece was the DataServicesMessaging event gateway. I set that up as a simple based on the documentation in the developer's guide.
Ok, so this is going on a bit long. It may make sense to stop now and work on a simpler example for later in the week. But here is the thing. It is freaking cool as surfboading ninja zombies to see my ColdFusion scheduler run some code that then updated stuff on my AIR application. Let's wrap this now. Take a look at the code (please don't laugh too hard at any simple Flex mistakes I made), and let's talk again later in the week about some simpler examples (I have a few good ideas coming to me now).
