Data-driven Development with Flash Builder, Part II
Episode one of our introduction to data-driven development with Adobe Flash Builder saw us hook up a Catalyst-generated Flex application to our database, and use the code generation features of Flash Builder to create a PHP service for our app’s back end. By the time we finished, we had a working Flex application that made a full round-trip to our database via a PHP service, and populated a contact list with items.
In today’s final instalment, we’ll learn about some of the more advanced features of code generation that Flash Builder makes available to us, and add some data-editing capabilities to our application.
If you’ve followed this series since its first instalment, you should be up to speed and ready to roll; for anyone who’s joining us late, I’ll assume you have a little familiarity with Flex and MXML. You won’t actually need to know any PHP, as Flash Builder does all the heavy lifting for us, though you will need to have PHP and MySQL installed.
Make sure to test your knowledge with the Adobe-sponsored quiz at the end of the article.
In the first two articles in this series, we used Adobe Flash Catalyst to convert some basic artwork into a working prototype of a contact application, then imported the Flash Catalyst project into Flash Builder. Using Flash Builder’s data driven development tools, we automatically generated a PHP service that contained all the calls we need to manage our contact data, and automagically hooked it up to our application.
This time, you’ll see just how much work has been put into Flash Builder to allow us to build applications rapidly. But before we get to that, we’ll need to add a couple more features to make our application usable.
Our starting position is the end result of the previous article’s instructions. To make life easier, this installment’s downloadable archive has a Flash Builder project named part_2_start.fxp
.
When you import the .fxp
file, you will be presented with a dialog asking you to update path variables. This is because we are using a PHP installation in the project, and the variables should be set as follows:
- OUTPUT_FOLDER
-
This should be your webroot, or the web directory you’re serving your project from. For example
C:Inetpubwwwrootcontacts
. - PHP_FLEX_SERVER_ROOT
-
This should be the root of your web server. For example
C:Inetpubwwwroot
. - PHP_WEB_URI
-
This should be the url root used to access your project when it compiles. For example
http://localhost/contacts
.
This assumes you have a local web server and PHP installation, of course.
We already have a working contact list on the left-hand side of our application. What we need now is to add a single contact view, so that the user can see the details of any contact in the list when he or she clicks on a contact’s name.
When we were working in Flash Catalyst, we defined a contactView
state. The code in Main.mxml
works, but it’s a little simplistic for what we want to do, so let’s modify it slightly.
Start by cutting out all the <fx:DesignLayer>
and <s:RichText>
elements that are being used to show the contact’s name on the right-hand side of our display: we’re going to create a new component for this purpose.
Right-click on /src/components
in your Package Explorer pane in Flash Builder, and create a new MXML component. Call it ContactItem
and fill in the details in the dialog as per Figure 1, “The ContactItem Component”.
Flash Builder will generate the component structure for us. Next, we want to drop in the code to display the contact item’s details. First, insert the following code inside the Group
element, which adds a public variable so the component can be passed a Contact
value object:
<fx:Script> <![CDATA[ import valueObjects.Contact; [Bindable] public var contactData : Contact; ]]></fx:Script>
Don’t forget the [Bindable]
metadata—without it, the component won’t pick up changes to our selections at runtime. You’ll recall that, in article two of the series, Flash Builder generated the valueObjects/Contact.as
class for us, and we can use this as the expected type.
Now let’s add a slightly cleaned-up version of the generated Catalyst code, from which we’ve simply removed the Catalyst-specific items and stripped out the includeIn
attribute. The code should look like this:
<s:BitmapImage source="@Embed('assets/images/mockup/at.png')"/><s:RichText color="0xFFFFFF" fontSize="18" kerning="on" lineHeight="120%" whiteSpaceCollapse="preserve"> <s:content><s:p whiteSpaceCollapse="collapse"><s:span>Toby Tremayne</s:span></s:p></s:content></s:RichText><s:RichText color="0xFFFFFF" kerning="on" lineHeight="120%" whiteSpaceCollapse="preserve"> <s:content><s:p whiteSpaceCollapse="collapse"><s:span>9999 999 999</s:span></s:p></s:content></s:RichText><s:RichText color="0xFFFFFF" kerning="on" lineHeight="120%" whiteSpaceCollapse="preserve"> <s:content><s:p whiteSpaceCollapse="collapse"><s:span>toby@magicindustries.net</s:span></s:p></s:content></s:RichText><s:RichText color="0xFFFFFF" kerning="on" lineHeight="120%" whiteSpaceCollapse="preserve"> <s:content><s:p whiteSpaceCollapse="collapse"><s:span>21b Baker Street</s:span></s:p></s:content></s:RichText><s:RichText color="0xFFFFFF" kerning="on" lineHeight="120%" whiteSpaceCollapse="preserve"> <s:content><s:p whiteSpaceCollapse="collapse"><s:span>London</s:span></s:p></s:content></s:RichText>
Finally, we want to make sure the ContactItem
component is picking up the actual data that’s passed to it, so we replace the hard-coded values with references to our value
object:
<s:RichText color="0xFFFFFF" fontSize="18" kerning="on" lineHeight="120%" whiteSpaceCollapse="preserve"> <s:content><s:p whiteSpaceCollapse="collapse"><s:span>{contactData.first_name}</s:span></s:p></s:content></s:RichText><s:RichText color="0xFFFFFF" kerning="on" lineHeight="120%" whiteSpaceCollapse="preserve"> <s:content><s:p whiteSpaceCollapse="collapse"><s:span>{contactData.phone}</s:span></s:p></s:content></s:RichText><s:RichText color="0xFFFFFF" kerning="on" lineHeight="120%" whiteSpaceCollapse="preserve"> <s:content><s:p whiteSpaceCollapse="collapse"><s:span>{contactData.email}</s:span></s:p></s:content></s:RichText><s:RichText color="0xFFFFFF" kerning="on" lineHeight="120%" whiteSpaceCollapse="preserve"> <s:content><s:p whiteSpaceCollapse="collapse"><s:span>{contactData.address1}</s:span></s:p></s:content></s:RichText><s:RichText color="0xFFFFFF" kerning="on" lineHeight="120%" whiteSpaceCollapse="preserve"> <s:content><s:p whiteSpaceCollapse="collapse"><s:span>{contactData.city}</s:span></s:p></s:content></s:RichText>
Now, move back to Main.mxml
. First, check that the Application
tag’s currentState
attribute is set to listView
:
<s:Application xmlns:fc="http://ns.adobe.com/flashcatalyst/2009" xmlns:s="library://ns.adobe.com/flex/spark" xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:flm="http://ns.adobe.com/flame/2008" xmlns:lib="assets.graphics.mockup.*" xmlns:d="http://ns.adobe.com/fxg/2008/dt" xmlns:ai="http://ns.adobe.com/ai/2009" xmlns:ATE="http://ns.adobe.com/ate/2009" xmlns:contactservice1="services.contactservice1.*" height="600" width="800" backgroundColor="#FFFFFF" preloaderChromeColor="#FFFFFF" currentState="listView">
Next, go to the section of the code from which we stripped out the elements we put into ContactItem.mxml
, and drop in a call to our new component, like so:
<components:ContactItem id="contactPane" contactData="{contactList.selectedItem}" includeIn="contactView" x="450" y="125" />
If you type this using the code insight in Flash Builder (IE type the opening left angle bracket and wait for the little popup, you can navigate to your components:ContactItem
and when you select it, the IDE will automatically add an xmlns
attribute to your <Application>
tag. If not, you will need to make sure the following is added to the <Application>
tag:
xmlns:components="components.*"
The list component was automatically assigned an id
when we used the Flash Builder code generation tools to hook it up to our PHP service call, but it’s a very non-descriptive list1
. Change the id
to contactList
to make your code a little clearer.
You can, of course, set id
names and properties for your components in Flash Catalyst using the Properties pane in the Catalyst IDE prior to porting the project to Flash Builder.
Now we want to make the contact pane appear on the right hand side when the user selects an item from the contact list. Add this function to Main.mxml
’s script block:
protected function list_changeHandler():void { currentState='contactView';}
And then add a change handler on the contact list itself, like so:
<s:List id="contactList" skinClass="components.TobyTremayneDataList" x="157" y="163" change="list_changeHandler()" creationComplete="list_creationCompleteHandler(event)" labelField="address1" itemRenderer="components.RepeatedItem1"> <s:AsyncListView list="{getAllContactResult.lastResult}"/></s:List>
If you followed the last article and made your own adjustments, Flash Catalyst created transitions using parallels to simultaneously fade each element (first name, last name etc). We have replaced those individual elements with a single component, so we need to modify the transition code. Change it instead to have a simple Fade for each transition, targeting our new ContactItem component. The new set of transitions should look like this:
Flash Catalyst created transition
s that used parallel
s to simultaneously fade each element (first name, last name etc.). However, we’ve replaced those individual elements with a single component, so we need to modify the transition code. Change it instead to have a simple Fade
for each transition
, which will target our new ContactItem
component:
<s:transitions> <s:Transition fromState="contactView" toState="listView" autoReverse="true"> <s:Fade duration="200" target="{contactPane}" /> </s:Transition> <s:Transition fromState="listView" toState="contactView" autoReverse="true"> <s:Fade duration="200" target="{contactPane}" /> </s:Transition></s:transitions>
Now, if you save and compile your Flash Builder project, you’ll see that when you click in the contact list, the selected contact’s data appears on the right-hand side of the display.