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.
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>
note: Don’t Forget the Metadata!
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.
note: Setting Names and Properties in Catalyst
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 transitions that used parallels 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.