Communicating with the TileWindow

Posted: December 19, 2006 in Flex

Communicating with the TileWindow

Fortunately, Flex gives us the ability to open and manipulate windows containing additional controls and data. So someone asked me this question:

Question: “How do I create a window in a Flex application and pass data into it?”

Solution: Well the answer is quite simple. Three things are needed to create and open a window within a Flex application; import the TitleWindow class, import the PopupManager class, and create a custom MXML component based on the TitleWindow class. Once you have created an instance of your custom TileWindow, you can then pass a reference to the main application into your TileWindow instance. You can even pass a reference to a data structure into your TileWindow.

In the next few code segments I will explain the application I created to demonstrate this solution.

 

code segment 1 of 6 (TitleWindowPassData.mxml)


<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" horizontalAlign="left" layout="vertical" initialize="initApp()">
</mx:Application>

The code segment above (line 1 and 2) shows the template for our application. The remainder of the code will be inserted starting on line 3. As usual, I instruct my application to execute a function called initApp once the application construction is complete.

 

code segment 2 of 6 (the interface)


	<mx:Panel title="Combobox to DataGrid" width="50%">
		<mx:VBox width="100%" paddingTop="5" paddingLeft="5" paddingBottom="5" paddingRight="5">
			<mx:Label text="Step1. Select a Media Type from the ComboBox" fontSize="16" fontWeight="bold" />
			
			<mx:ComboBox id="mediaCB" change="changeEvt(event)" >
				<mx:ArrayCollection>
					<mx:Object label="- Select Media -" data="" />
					<mx:Object label="Painting" data="1" />
					<mx:Object label="Scultpure" data="2" />
					<mx:Object label="Photography" data="6" />
				</mx:ArrayCollection>
			</mx:ComboBox>
    
    		<mx:Label text="Step2. Select a piece of Art from the DataGrid" fontSize="16" fontWeight="bold" />
    		
    		<!-- instruct the DataGrid to bind a variable named, acCourses to the DataGid's dataProvider -->
			<mx:DataGrid id="dgArt" dataProvider="{acArt}" width="100%" change="updateArt()">
				<mx:columns>
					<mx:DataGridColumn headerText="Name" dataField="ARTNAME"/>
					<mx:DataGridColumn headerText="Price" dataField="PRICE"/>
					<mx:DataGridColumn headerText="Sold?" dataField="ISSOLD"/>
				</mx:columns>
			</mx:DataGrid>
			
			<mx:Label id="numRec" />
		</mx:VBox>
		
		<mx:ControlBar>
			<mx:Button id="showArtWork" label="Show Art Work" click="showArt()"/>
		</mx:ControlBar>
    </mx:Panel>

We start the interface by defining a VBox inside a Panel and the Label gives our user a bit of instruction.

The ComboBox listed on lines 4 through 11 defines the ComboBox containing our initial values.

The next Label defines a little more instruction.

The DataGrid listed on lines 13 through 19 defines three columns using the acArt dataProvider. The acArt dataProvider is an ArrayCollection which, I will describe in the next code segment.

The final Label is used to display the number of rows of data in the DataGrid – Informational purposes only.

 

code segment 3 of 6 (data connection)



  1. wsdl="http://10.180.180.18/FlexDemos/TitleWindowData/cf/art.cfc?wsdl" showBusyCursor="true" result="handleGetArt(event)">

Code segment 3 of 6 defines our WebService class used to get data from the database via a ColdFusion CFC component.

 

code segment 4 of 5 (the script)

  1. import mx.rpc.events.ResultEvent;
  2. import mx.controls.Alert;
  3. import mx.collections.ArrayCollection;
  4. import mx.containers.TitleWindow;
  5. import mx.managers.PopUpManager;
  6. public var selMediaID:Number = 0;
  7. public var ArtImageInstance:ArtImage;
  8. [Bindable]-->
  9. [Bindable]private var acArt:ArrayCollection;
  10. private function initApp():void {
  11. myService.getArt.send()
  12. }
  13. public function handleGetArt(event:ResultEvent):void{
  14. var acTemp:Array = event.result as Array;
  15. acArt = new ArrayCollection(acTemp);
  16. filterAC();
  17. }
  18. private function changeEvt(event:Event):void {
  19. selMediaID = event.currentTarget.selectedItem.data;
  20. filterAC();
  21. }
  22. private function filterAC():void {
  23. acArt.filterFunction = mediaFilterFunc;
  24. acArt.refresh();
  25. numRec.text = "Number of records: " + acArt.length.toString();
  26. }
  27. private function mediaFilterFunc(item:Object):Boolean {
  28. return item.MEDIAID == selMediaID;
  29. }
  30. private function showArt():void {
  31. objItemSelected = dgArt.selectedItem;
  32. if(ArtImageInstance == null) {
  33. ArtImageInstance =
  34. ArtImage(PopUpManager.createPopUp(this, ArtImage, false));
  35. ArtImageInstance.width = 370;
  36. ArtImageInstance.height = 440;
  37. ArtImageInstance.mainApp = this;
  38. ArtImageInstance.itemSelected = objItemSelected;
  39. PopUpManager.centerPopUp(ArtImageInstance);
  40. }
  41. ArtImageInstance.title = objItemSelected.ARTNAME;
  42. }
  43. private function updateArt():void {
  44. if(ArtImageInstance != null) {
  45. objItemSelected = dgArt.selectedItem;
  46. ArtImageInstance.title = objItemSelected.ARTNAME;
  47. }
  48. }
  49. ]]>

Now we add our Script block. We start by importing server classes

The ResultEvent class allows us to pass and introspect properties and data in response to an event.

The Alert class allows us to display Alert boxes.

The ArrayCollection classs allows us to create and work with a very powerful type of array structure.

The next two lines (6 and 7) import the classes we need to work with and communicate with our TitleWindow.

The selMediaID variable is used to keep track of the ID selected from the ComboBox.

Line number 9 defines the instance variable that will hold a reference to our TitleWindow instance. It is typed as the custom MXML component shown in code segment 5

Next we defined a Bindable variable that is used to hold the object refering to the selected row in the DataGrid

On line 11 we define the Bindable ArrayCollection variable that is used to hold the data for the DataGrid.

OK. Now on lines 12 to 14 we define the function that includes the line of code (line 13) that will execute our method within the ColdFusion CFC component.

Lines 15 through 19 define the result handler function that is called as a result of a successfull retrieval by the WebService.

Once the result has been returned, we must cast it as an array before we convert it into an ArrayCollection. Why you may ask? Well, the result data is returned as an Object that FLex is unable to convert into an ArrayCollection. So we first cast our result Object as an Array (line 16) and then convert to an ArrayCollection (line 17).

Now we call a function that will apply a filter to our ArrayCollection. Again you may ask why. The acArt variable is bound to the DataGrid and we want our DataGrid to be empty until the user selects a value from the ComboBox. So the filterAC function will filter out all rows. More on this later.

The changeEvt function (lines 20 to 23) is called when a selection is made from the ComboBox. It will save the selected ID in the selMediaID variable and then filter the ArrayCollection based on that value.

Note: You could just as well pass the selMediaID value to the filterAC function.

Now to the filterAC function (lines 24 to 28). The mediaFilterFunc is used as the function that is passed to the filterFunction property of our ArrayCollection. This will allow us to filter the ArrayCollection based on the reuslt from the mediaFilterFunc function.

Line 27 simply updates our Label to display the number of rows in our ArrayCollection.

The mediaFilterFunnc function (lines 29 to 31) returns an item containing data for each row passing the condition shown on line 30.

OK. Now we get to the function that allows us to open our TitleWindow (lines 32 to 44). First we get the selected item from the DataGrid control (line 33). Remember the variable called objItemSelected? We defined it as a Bindable variable a few lines above (line 10).

The if conditions checks to see if our TitleWindow instance, ArtImageInstance, has been initialized. If it is still null we continue through the remaining lines (35 to 41).

First we use the PopupManager class to create a popup. The three parameters refer to the; parent of the window (this), the custom TitleWindow component (ArtImage), and specifies that the window is non-modal (false). A non-modal window means that user is able to interact with the rest of the application while the window stays open. A model window does not allow the user to interact with the rest of the application until the window has been closed. Got that? Imagine a File Open dialog box in MS Word or even your browser. Once the dialog box is open you are unable to interact with the browser until the dialog box is closed.

Ok. Still on line 35, we then convert the popup into a TitleWindow by passing it to our custom component’s constructor. We’ll be looking at that custom component a bit later. The resulting reference in stored in our ArtimageInstance instance variable. Now we have an instance of our custom TitleWindow component.

On lines 37 to 40 we begin to assign values to several properties of our instance. Two of which are inherent. The other two were defined within our custom component. The property mainApp holds a reference to the main application and itemSelected holds a reference to the selected item from the DataGrid. More on that later.

now we actually create our popup, TitleWindow, by calling the method centerPopUp and passing it our ArtImageInstance. This method does more than just show our popup it also centers it within the application.

Finally we set one more property within our instance, the title.

Our final function, updateArt, is used to update the Bindable object variable, objItemsSelected, and update the window instance title. As you can see, we only perform this if the window instance is not null.

So what does our custom TitleWindow component look like …?

 

code segment 5 of 6 (ArtImage.mxml)

  1. showCloseButton="true"
  2. close="closeWindow()">
  3. import mx.managers.PopUpManager;
  4. import mx.collections.ArrayCollection;
  5. [Bindable]-->
  6. [Bindable]public var itemSelected:Object;
  7. private function initComponent():void {
  8. }
  9. private function closeWindow():void {
  10. mainApp.ArtImageInstance = null;
  11. PopUpManager.removePopUp(this);
  12. }
  13. ]]>

So now we get to the custom TitleWindow component I’ve mentioned so many times during this tutorial.

Line 3 to 6 shows that this component is based on the TitleWindow. Upon creationComplete I instruct it to execute the initComponent function.
I set the showCloseButton property of the component to allow the user to close the window by clicking on a small ‘x’ that will appear in the upper right-hand corner of the window.
I alse specify the function that wil be called in response to the close event.

Let’s skip down to the user interface defined on lines 21 to 26. We define a VBox that is scaled to the full width and height of its parent, the window itself.
Then we define another Vbox that will contain the image itself. I do this so that I can provide a border around the image.

Next on line 23 we define a SWFLoader. Its source references the LARGEIMAGE value within the objItemSelected object contained within the main application (mainApp).
You may be asking why I used the SWFLoader tag and not the Image tag. Well, I’m using this component in a larger application that will display not only images but also Flash swf files.

An lastly on line 25 we define a Label control to display the DESCRIPTION of the artwork. The last two lines described here show one of the ways you can reference and use data that has been defined outside the window.
In a later post I will show a better (loosely coupled) way of communicating between multiple windows and the main application.

 

code segment 6 of 6 (Art.cfc)

  1. SELECT art.ARTNAME, art.PRICE, art.MEDIAID, art.LARGEIMAGE, art.ISSOLD, art.DESCRIPTION, media.MEDIATYPE
  2. FROM art INNER JOIN media ON art.MEDIAID = media.MEDIAID
  3. ORDER BY art.MEDIAID, art.ARTNAME

I kept the ColdFusion CFC component rather simple. It contains one function called getArt (line 2) that defines a CFQUERY (line 5 to 9) to retrieve all the artwork information. We then simply return that query object back to our Flex application.

Note: The ColdFusion CFC component returns a query object that is interpreted within Flex as an object containing an array of objects. Debugging is Fun!


And there you have it. This simple example can (and will!) be expanded to contain more functionality such as:

  • Opening multiple windows and keeping the content within those windows in sync with the selected row of data.
  • Having controls within the window communicate back to its parent.
  • and more …

The power of Flex leaves it to your imagination!

Advertisements
Comments
  1. Ken Caldwell says:

    I would really like to review your code so I can learn how to do this. But most of the code is missing.
    Is it possible for you to email me the example ?

    I’m developing an application and as I’m learning Flex I have used the coldfusion/flex wizard.

    What I’m trying to achieve is:
    Using the login scripts from the wizard, when the user logs in I want to store the users information (access level, ect) for use throughout the application.

    it would appear that the best way to do this is with a singleton (class) which I have done and it all works well. Except I can’t figure out how to access the singleton from the other parts of the application.

    Regards
    Ken Caldwell

  2. Carl Steinhilber says:

    I’m not sure what’s happening with your blog, but it’s only displaying portions of the code snipets you’ve provided.

    “code segment 1 of 6 (TitleWindowPassData.mxml)”, for example, only displays:
    1.
    2.
    3. …
    4.

    Looked at it in Firefox and IE6, just to be sure it wasn’t a browser style issue… but the code doesn’t even appear in the page source.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s