IntroductionWelcome| 00:00 | Hi, my name is David Gassner and
I'd like to welcome you to this video
| | 00:04 | series, Flex 3 Beyond the Basics. This is
a follow up to a previous lynda.com
| | 00:09 | series, Flex 3 Essential Training, in which
I described how to build and deploy
| | 00:13 | basic Flex 3 applications using Flex Builder
3 and the Flex 3 Framework.
| | 00:19 | In this video series, I describe advanced
Flex development skills, including
| | 00:23 | visual tricks like using custom pop-up
windows and programmatic animations,
| | 00:28 | parsing of XML with E4X and integration of
Flex applications with Cold Fusion,
| | 00:33 | ASP.NET and PHP.
| | 00:36 | I hope you enjoy this training and that it helps
you build better, more powerful Flex applications.
| | Collapse this transcript |
| Prerequisites| 00:00 | In this video, I am going to describe the
prerequisites for this title. This is
| | 00:04 | a follow up title to the existing video
series, Flex 3 Essential Training.
| | 00:09 | If you've already watched that video series
and feel comfortable with the skills
| | 00:13 | that are taught there or if you have equivalent
experience developing Flex
| | 00:16 | applications, you should be ready
to jump into this video series.
| | 00:20 | The Flex 3 Essential Training Video Series
contains information about building
| | 00:24 | basic applications and deploying them Flex
Builder 3. It describes how to layout
| | 00:29 | applications using containers and
absolute positioning. How to work with
| | 00:34 | events. And how to communicate with application
servers, using the HTTP Service component.
| | 00:40 | In both video series, there is an assumption
that you are comfortable with the
| | 00:43 | ActionScript language, but if you need a
refresher course, it might be worth
| | 00:48 | going back to the video series, ActionScript
3.0 in Flex Builder Essential Training.
| | 00:52 | That video series covers the fundamentals
of programing and advanced
| | 00:56 | object oriented concepts of programing
in the context of ActionScript 3.0.
| | 01:01 | Once you have watched this video series,
you might then want to move onto
| | 01:05 | another video series called AIR for Flex
Developers, where you learn how to
| | 01:09 | take all these skills put together and
use them in the context of building
| | 01:13 | native desktop applications that are deployed
using the Adobe Integrated Runtime or AIR.
| | Collapse this transcript |
| Using the example files| 00:00 | Just a quick word about the exercise
files we will be using. If you are a
| | 00:04 | premium member of the lynda.com Online
Training Library or if you are watching
| | 00:08 | this tutorial on a disc, you have access
to the exercise files used throughout this title.
| | 00:14 | In the exercise files folder, I have
collected some assets for you to use
| | 00:17 | during our tour of the advanced features
of Flex 3. They include applications,
| | 00:22 | source code, graphics and text files for using
the sample applications that we'll be creating.
| | 00:26 | I had copied the folder to my desktop,
but you can put it wherever you want.
| | 00:31 | If you are a monthly or annual subscriber to
lynda.com, you don't have access to
| | 00:36 | the exercise files but you can easily follow
along and use any files you want
| | 00:41 | as you create your own sample
applications. Let's get started.
| | Collapse this transcript |
|
|
1. Using Popup WindowsPresenting simple messages with the Alert class| 00:00 | In this chapter of the video series, I am
going to describe the use of pop-up
| | 00:04 | windows as part of Flex applications. A
pop-up window is a rectangular region
| | 00:09 | that floats and can move above the application
container. The user can click
| | 00:14 | and drag a pop-up window around the screen
as they want to. You can create
| | 00:18 | pop-up windows in a couple of ways in the
Flex framework. You can use the Alert
| | 00:22 | class to display a standard window that displays
text messages, optional icons
| | 00:27 | and a small set of buttons, or you can
create and display your own custom
| | 00:31 | pop-up windows using the PopUpManager
class and the title window or panel containers.
| | 00:37 | For all of the demonstrations in this chapter,
I will use exercises from the
| | 00:40 | Exercises folder. If you are following along
with the exercises you can import
| | 00:44 | the project I will be using. From the Flex
Builder menu select File, Import,
| | 00:50 | Flex Project. Click the Browse button next
to Archive File, navigate to the
| | 00:56 | Chapter 01 folder under the Exercises area,
and then import the file Chapter01Begin.zip.
| | 01:05 | Once the project has been imported, open
the project and then open its source folder.
| | 01:10 | Then open the application UsingAlert.mxml.
I demonstrated the use of a
| | 01:17 | simple alert pop-up window, in the Flex 3
Essential Training video series, so
| | 01:22 | this will be a review.
| | 01:24 | Go to the Script section and create a new
private function named showPopup. The
| | 01:31 | function will return void. In order to display
a pop-up window, with the Alert
| | 01:36 | class, call a static show method. Start by
typing the word Alert with an upper
| | 01:41 | case A. The Alert class must be imported
to use it correctly. So now, press
| | 01:47 | Ctrl+Space and you'll see a list of all
the classes starting with the word
| | 01:51 | alert and then select the Alert class.
| | 01:54 | You should see that Flex Builder automatically
adds an import statement above
| | 01:58 | the function. Now type the dot(.) character
and you'll see a list of all the
| | 02:01 | properties and methods of the Alert class
and start typing show. This is the
| | 02:07 | only static method that the Alert class
implements. The show method accepts a
| | 02:11 | number of arguments.
| | 02:13 | I'll be showing you how to use each of these
in the following videos, but for
| | 02:16 | this simple demonstration, I am only going
to use the first two arguments, both
| | 02:20 | strings. The first string value is displayed
in the body of the pop-up window,
| | 02:24 | that is in the center region and the second
string argument is displayed in the
| | 02:28 | title, that is in the upper left corner.
So in the show method I will pass in
| | 02:32 | these strings.
| | 02:34 | Flex 3 is awesome and About Flex 3. I'll
close the method call, then go down to
| | 02:44 | the button with the label of Open Alert
Popup, add a click event handler and
| | 02:50 | then call the method, showPopup. Save your
changes and run the application.
| | 02:57 | Once the application opens in the browser,
click the button, Open Alert Popup,
| | 03:02 | and you should see the pop-up window displayed
on the screen, centered in the
| | 03:05 | application. Notice that the pop-up window
created by the Alert class is modal.
| | 03:10 | That is to say, it locks interaction with
the rest of the application and
| | 03:15 | indicates that it can't interact with
the application by blurring the
| | 03:18 | background. For example, if the user tries
to click on the button in the main
| | 03:22 | application window, they won't be able
to until the user clears the Alert
| | 03:28 | pop-up window, then they can go back
and click that button again.
| | 03:32 | Close the Browser and return to the code.
One of the interesting aspects of the
| | 03:36 | Flash Player when you work with Flex application
development is that code
| | 03:41 | blocks once started always execute to their
end. Here's what I mean by this. In
| | 03:46 | many application environment which operate
synchronously such as browser based
| | 03:50 | Javascript, if you use a mechanism such
as the JavaScript Alert method to
| | 03:55 | display a pop-up window, the code execution
pauses until the user interacts
| | 03:59 | with the window. That isn't the case in the
Flash Player. The Flash Player has
| | 04:03 | a single application thread and so if you
pause the ActionScript code execution
| | 04:08 | everything else has to be suspended as
well, such as animations and other
| | 04:12 | interactions with the application.
| | 04:15 | So, let me demonstrate this by cloning the
code for Alert.Show. In Flex Builder
| | 04:20 | and in all of the clips, you can clone a
bit of code by selecting it and then
| | 04:25 | pressing Ctrl+Alt and the Down cursor key.
On the Mac the keyboard shortcut is
| | 04:30 | Command+Alt and the Down cursor key. So,
now I am calling the Alert.Show method
| | 04:35 | twice. Save and Run the application again
and then once the application opens,
| | 04:41 | click the Open Alert Popup button and at
first glance it may look like you've
| | 04:45 | only executed the code once, but then if
you drag the pop up window off in some
| | 04:50 | direction, you'll see that there are actually
two pop-up windows on the screen.
| | 04:54 | Clear the first one by clicking the OK
button, and clear the second one by
| | 04:59 | clicking its OK button and only then does
the application become completely
| | 05:03 | available and all of the blurriness go away.
| | 05:06 | So, that's the demonstration of how the
Flash Player and the Flex framework
| | 05:11 | operate in terms of ActionScript code execution.
Once you start an ActionScript
| | 05:15 | code block, you will always complete it
even if you pop-up windows that you
| | 05:19 | think of as modal. A modal window, such as
the Alert class's window, blocks the
| | 05:25 | user interaction, but does not stop ActionScript
code from executing in the
| | 05:29 | background.
| | 05:29 | Now, in the next set of videos, I'll show
you how to make more advanced use of
| | 05:34 | the Alert class's pop-up window.
| | Collapse this transcript |
| Managing Alert popup window buttons| 00:00 | In this video, I am going to describe how
to customize the Alert Popup window's
| | 00:04 | buttons? How to change the label on the
button? And how to select additional
| | 00:08 | buttons that you want to display, and then
at a later video I will show you how
| | 00:12 | to listen for the event that occurs when
the user clicks a button, so you can
| | 00:16 | determine which button was selected.
| | 00:18 | For all of the demonstrations in this
video, I'll use the application
| | 00:22 | AlertButtons.mxml from the Chapter01Begin
folder. If you are following along in
| | 00:27 | the exercises, open the application now.
In this version of the application, I
| | 00:32 | am once again showing a pop-up window, this
time with a question, are you sure
| | 00:36 | that Flex 3 is awesome? And I am going
to show you how to solicit an answer
| | 00:41 | from the user by displaying a set of buttons.
| | 00:44 | Each of the four buttons that the Alert Popup
window is capable of displaying,
| | 00:48 | is represented by a static constant value
that's a member of the Alert class.
| | 00:53 | You indicate which buttons you want to display
by selecting each constant for
| | 00:57 | the button you want to show, separating them
with the bitwise pipe(|) character
| | 01:01 | operator and then wrapping the
whole thing in parenthesis.
| | 01:04 | So for instance, if I wanted to show both
an OK and a Cancel button, I would
| | 01:09 | create a pair of parenthesis in the next
argument in the show method and then
| | 01:13 | within that I would add in the following
constants. Alert.OK and then a pipe
| | 01:19 | character and then the constant for the
Cancel button Alert.CANCEL. I'll save
| | 01:25 | the changes and run the application. I'll
click the button to open the Alert
| | 01:31 | Popup and this time I get two buttons,
OK and Cancel. I'll cancel the
| | 01:37 | operation and close the application and then
show you that there are two other
| | 01:41 | constants that you can select for Yes and No.
| | 01:45 | Once again, the labels for these values are
determined by the resource bundles
| | 01:49 | that control your particular Flex application.
So I'll use Alert.yes and then
| | 01:54 | the pipe character and then Alert.no. Once
again, I'll run the application,
| | 02:00 | click the button to display the pop-up window
and now I get buttons for yes and
| | 02:05 | no.
| | 02:06 | You can also change the labels that each
button displays. The Alert class has
| | 02:11 | four properties that are used for this
purpose named, yesLabel, noLabel,
| | 02:14 | okLabel and cancelLabel. So for example if
I wanted to change the words yes and
| | 02:21 | no to something else, before I call the
show method, I would call this code -
| | 02:26 | Alert.yesLabel equals For sure! and then
I'd set the noLabel property to No
| | 02:37 | way. I'll run the application now, and
then click the button to display the
| | 02:44 | pop-up and you'll see that the buttons
are displayed, but notice that the
| | 02:48 | labels are truncated. This is because the
labels that are a part of the Alert
| | 02:52 | class's pop-up window, don't automatically
resize themselves, based on their
| | 02:56 | labels the way standard button controls
do. So if you're going to change the
| | 03:00 | label, you also need to take control
over the button width.
| | 03:04 | I'll do that by setting a property of the
Alert class named buttonWidth and
| | 03:10 | I'll be conservative, I'll allow plenty of
space by setting this value to a 100
| | 03:15 | pixels. I'll Save the changes and run the
application again. Click the button
| | 03:21 | to display the pop-up and now I see the
buttons. Notice that the buttonWidth
| | 03:25 | property affects all buttons in the
Alert class's pop-up window.
| | 03:30 | So, that's how you display the buttons.
By the way it's worth mentioning that
| | 03:33 | there is one other flag or value that
you can pass into this argument. In
| | 03:38 | addition to the four button constants, Yes,
No, Ok and Cancel, notice that the
| | 03:45 | Alert. NONMODAL constant is another flag,
that is a value that you pass-in in
| | 03:49 | this third argument separated from the
others by the pipe character or the
| | 03:53 | bitwise operator.
| | 03:55 | Save the changes and run the application
again and click the Applications
| | 04:02 | button to display the pop-up window.
Once again, the pop-up window is
| | 04:05 | displayed, but notice that the application
background is not blurred this time.
| | 04:10 | This is a visual indicator for the user that
shows that they can still interact
| | 04:14 | with the rest of the application. I'll drag
the pop-up dialog box off to the
| | 04:18 | side and click the application button again
and notice now I can create as many
| | 04:24 | different pop-up windows all with the same
labels and so on as the others.
| | 04:29 | One thing however that you don't have
control over with the pop-up window
| | 04:32 | created by the Alert class is the positioning
of the pop-up, and this is where
| | 04:36 | the custom pop-up window architecture comes
into use. I'll be showing how to
| | 04:41 | use that in later videos. But in this next
video I'm going to show you, how to
| | 04:45 | listen for and handle the event that's dispatched
when the user clicks any of
| | 04:50 | the buttons in the pop-up window created
by the Alert class. You'll be able to
| | 04:53 | listen for the click, figure out which button
was selected and then react in
| | 04:58 | whatever way you need to for your application.
| | Collapse this transcript |
| Handling Alert Popup Window events| 00:00 | In this video I am going to describe how
to detect the event that's dispatched
| | 00:04 | when the user clicks the button in the
pop-up window generated by the Alert
| | 00:08 | class. You will be able to listen for the
event and then determine which button
| | 00:12 | was clicked so you can react accordingly.
| | 00:14 | For this demonstration I will use the application
AlertEvents.mxml that you
| | 00:19 | will find in the Chapter01Begin project.
In this version of the application the
| | 00:24 | Alert class pop-up window asking a simple
question, do you want to continue?
| | 00:29 | You can use this sort of pop-up window to
get any sort of confirmation from the
| | 00:33 | user and the goal is not only to display
a set of options Yes or No, OK or
| | 00:38 | Cancel or any other customized buttons you
like but also to react when the user
| | 00:43 | clicks one of the buttons.
| | 00:45 | Change the code as follows. First of all
place the cursor inside the Script
| | 00:50 | section after the existing showPopup function
and add a new private function.
| | 00:55 | When the user clicks any of the buttons
in the pop-up window generated by the
| | 00:59 | Alert class, the pop-up window dispatches
a Close event. So, we are going to
| | 01:04 | listen for the Close event and react
accordingly. Name the function
| | 01:09 | closeHandler. As with all event handler functions
accept an event object as an
| | 01:14 | argument and data type this one
as the class closeEvent.
| | 01:18 | Notice that as I have selected the closeEvent
class from the list of available
| | 01:22 | classes that the Import statement for the
class was added automatically. Unlike
| | 01:27 | the event classes that are members of the
standard package flash.Events, such
| | 01:32 | as flash.Events.Event or flash.Events.MouseEvent,
the closeEvent class is a
| | 01:38 | member of package named mx.Events and
it must be imported to be used
| | 01:42 | successfully. As with all good event handler
functions return void and then add
| | 01:48 | a call to the trace function within the closeHandler
method and simply output a
| | 01:52 | string of close event handled. Now, go
back to the function showPopup.
| | 01:59 | We are going to add two more arguments
to the show method call. The fourth
| | 02:04 | argument that you pass into the show method
is the parent, this is a reference
| | 02:09 | to the application window or to any other
window on which you want to center
| | 02:13 | the pop-up window generated by the Alert
class because we don't have any other
| | 02:17 | windows on which to center the pop-up,
we will use this, meaning the
| | 02:21 | application window itself. This is how
we are going to listen for the close
| | 02:25 | event. Pass in a reference to the function
you want to call when the Close
| | 02:29 | event is dispatched, which
we named closeHandler.
| | 02:33 | In a similar fashion when using the Add
Event Listener architecture, you pass
| | 02:38 | in a simple reference to the function you
want to call. The Alert class knows
| | 02:42 | how to call this function already, it will
call the function, pass the Close
| | 02:46 | event object and then you will be able
to determine by inspecting the event
| | 02:51 | object's properties which button was clicked.
Save your changes and run the
| | 02:55 | application in Debug mode, so you will
be able to see the trace method.
| | 03:02 | Click the button to open the pop-up and then
click either button in the pop-up
| | 03:06 | window. Go back to Flex Builder and you should
see that the trace method output
| | 03:12 | the message close event handled. So, if
you have been successful so far, now
| | 03:16 | you are ready to determine which button
was clicked. Terminate the debugging
| | 03:20 | session and then go back to full screen
coding. Within the eventHandler
| | 03:25 | function you determine which button was
clicked by inspecting an event object
| | 03:30 | property named detail. The event.detailProperty
will match whichever alert
| | 03:36 | button was clicked and you will be able
to determine this by inspecting the
| | 03:40 | constant associated with the button. Place
the cursor after the call to the
| | 03:44 | trace method and add an if conditional
block that looks like this, If
| | 03:50 | (event.detail == Alert.YES).
| | 04:01 | And again this is the constant representing
the YES button. Put in the pair of
| | 04:07 | braces to complete the conditional section
and use another call to the Alert
| | 04:11 | class and this time show a simple string
of Let's go!. To give the pop-up
| | 04:17 | window a complete look, I recommend that
you always pass in two strings, the
| | 04:22 | first string again is in the body of the
pop-up window and the second is in the
| | 04:26 | title. Now, add an else clause. Now if the
user clicks the No button or if they
| | 04:35 | simply press the Escape key the else clause
code will execute. I will display a
| | 04:41 | message of OK I'll stop, and once
again the title Event handler.
| | 04:48 | Save the application code and once again
run the application, this time in
| | 04:52 | standard mode. Click the button to display
the alert dialog, try clicking the
| | 04:58 | Yes button and you should see the reaction
Let's go! Clear that message, click
| | 05:04 | the button again to display the pop-up window
and this time click No and you
| | 05:09 | should see the message OK I'll stop. So,
this shows you how to react to the
| | 05:14 | close event when using the pop-up window
generated by the Alert class and you
| | 05:19 | are using customized buttons. You can detect
the clicks on the Yes, No, OK and
| | 05:24 | Cancel buttons and once again you can customize
the labels of these buttons as
| | 05:29 | you need to, to ask the questions
that you want to ask.
| | Collapse this transcript |
| Changing the Alert popup window's appearance| 00:00 | In this video I am going to describe a couple
of approaches to customizing the
| | 00:04 | appearance of the pop-up window generated
by the Alert class. For these
| | 00:09 | demonstrations I will use the application
AlertAppearance.mxml. If you are
| | 00:14 | following along with the exercises you can
open that file now. In this version
| | 00:19 | of the application, I am once again using
the Alert class to display a pop-up
| | 00:23 | window. The code starts at the point
where the last exercise left off,
| | 00:28 | displaying a message, do you want to continue?
And then reacting to the Close
| | 00:32 | event of the Alert class by using an event
handler function to determine which
| | 00:36 | button was clicked.
| | 00:38 | There are two major aspects to controlling
the appearance of a pop-up window
| | 00:41 | generated by the Alert class. The first
is the use of a custom icon, a custom
| | 00:46 | icon is a graphic that you can display in
the Alert class pop-up window. For
| | 00:51 | this purpose I recommend that you use
a graphic format that supports
| | 00:55 | transparency, PNG, GIF files or SWF files
will do the trick and for this
| | 01:01 | application, I am going to use a graphic
that's already been created and placed
| | 01:05 | in the Assets folder of the project, named
questionIcon.png, this is a PNG file
| | 01:11 | that was originally created in Fireworks
and it still has its underlying Sprite
| | 01:18 | architecture.
| | 01:19 | So, if you have a copy of Fireworks you
will be able to open up this graphic
| | 01:23 | and make any changes to it such as its color,
its font face and so on. I will
| | 01:28 | close Fireworks and return to Flex Builder.
The first step in using a custom
| | 01:33 | icon graphic is to embed the graphic in
the application. There are couple of
| | 01:38 | ways of doing this but the simplest is to
do it in the Script section. Place
| | 01:42 | your cursor inside the Script section and
add and Embed metadata tag. Now, if
| | 01:48 | you haven't used the Embed tag before,
it's a metadata tag similar to the
| | 01:52 | Bindable metadata tag.
| | 01:54 | So, it uses brackets on the outside and then
the word Embed with an uppercase E
| | 02:00 | and then a source attribute that points
to the location of the graphic file
| | 02:04 | that you want to embed. I will embed the
graphic icon using the source property
| | 02:11 | assets/questionIcon.png. Make sure you spell
the name of the file exactly as
| | 02:17 | it's saved on disk and it is case-sensitive.
Now, after the Embed metadata tag,
| | 02:23 | declare a variable, datatyped as a class.
This will be associated with the
| | 02:28 | graphic and will be used to pass the graphic
to the Alert class pop-up window.
| | 02:33 | You can name the variable anything you want.
| | 02:35 | For simplicity I will use the same name as
the graphic file itself but without
| | 02:39 | the .png file extension questionIcon, and
then data type it as a class. The
| | 02:46 | next step is to go to the show method
call for the Alert class. Go to the
| | 02:51 | showPopup method, place the cursor after
the closeHandler function call, put in
| | 02:57 | a comma and then pass in the name of your
class questionIcon. Notice that
| | 03:03 | because the class isn't a variable name,
you can auto complete it by pressing
| | 03:07 | Ctrl+Space and then selecting the appropriate
class name. Save your changes and
| | 03:12 | run the application, then click the button
to display the pop-up window and you
| | 03:19 | should see that the graphic icon is correctly
displayed and that because it has
| | 03:23 | transparency, it displays the background
color of the pop-up window through the
| | 03:28 | graphic icon.
| | 03:29 | Close the application and return to the code.
The other method that you use to
| | 03:34 | determine the appearance of a pop-up window
generated by the Alert class is to
| | 03:38 | change Cascading Style Sheet properties.
Add a pair of style tags to the
| | 03:43 | application after the Script section and
before the button. When you create an
| | 03:47 | Alert pop-up window, it creates a variable
that's actually datatyped as the
| | 03:52 | Alert class and so one aspect of using
Cascading Style Sheets to modify the
| | 03:57 | appearance is to create a type selector using
the Alert class name. Within the
| | 04:03 | Alert class you can then change any of
the styles associated with the Alert
| | 04:07 | class. If you are not sure which styles are
available, check the documentation
| | 04:11 | for the Alert class but for example you
could change the background color and
| | 04:17 | that would change the color of the center
area of the pop-up window that is the
| | 04:21 | area where the main string, the buttons
and graphic icon are displayed.
| | 04:26 | I will change my background color to a value
of #EEEEEE which is an off-white
| | 04:33 | and then I will also change the font color
like this. I will put in a color
| | 04:37 | style declaration and change that value to
#000000 which is black. I will save
| | 04:46 | the changes and run the application. Click
the button to show the pop-up and
| | 04:53 | you will see that the center area of the
pop-up window is the off-white color
| | 04:56 | and the graphic icon's transparency allows
it to show through. I will close the
| | 05:00 | application and add one more wrinkle. The
Alert class supports a predefined
| | 05:05 | style name called windowStyles, which determines
what the fonts in the header
| | 05:09 | look like.
| | 05:10 | I will add a windowStyles style name selector.
Notice that as with all style
| | 05:15 | names or classes you prefix the name of the
style with a period and then I will
| | 05:20 | add font properties to change the look of
the font in the header. I will add a
| | 05:26 | font style of Italic and a font size of
18 pixels. Remember when setting font
| | 05:33 | sizes that everything is in terms of
pixels, so you don't add a unit of
| | 05:37 | measurement after the number as you would
in HTML. I will run the application
| | 05:42 | again, click the button and you will see
that the font in the header of the
| | 05:49 | pop-up window uses 18 pixels in Italics.
One caution about the windowStyles
| | 05:55 | style name, this is used not only by the
Alert class but also by the Panel
| | 05:59 | Container and the Title Window Container.
You will learn how to use the Title
| | 06:04 | Window Container in later videos in this
chapter when we talk about custom
| | 06:07 | pop-up windows. This is because the Alert
class, the Panel and the Title
| | 06:13 | Container are all part of one family of
container components in the Flex
| | 06:17 | Framework. So, if you change the windowStyles
here, you will be changing them
| | 06:21 | for the Panel and for the Title window as
well. So, those are two major aspects
| | 06:25 | of modifying the appearance of your pop-up
windows generated by the Alert
| | 06:29 | class, the use of the custom icon graphics
and the use of Cascading Style
| | 06:34 | Sheets.
| | Collapse this transcript |
| Creating custom popup windows| 00:00 | In this video I am going to describe how
to define a custom pop-up window using
| | 00:05 | the Panel Container. The Panel Container
has a default dialog box style look
| | 00:10 | and feel and its well suited for use as
the base for any pop-up dialogs that
| | 00:15 | you want to create. A custom pop-up window
is a standard MXML component
| | 00:20 | typically that has as its root element
one of the Flex containers. For this
| | 00:25 | demonstration I am going to be creating a
brand new MXML component from scratch
| | 00:30 | and I will base it on the panel container
and then in the next video I will
| | 00:34 | show you have to instantiate this component
using ActionScript code and then
| | 00:38 | use a class called the PopUpManager
to show it on the screen.
| | 00:42 | Go to the Chapter01Begin project and locate
the windows folder under the source
| | 00:46 | root. Right click on the windows folder
or Ctrl+Click on the Mac and select
| | 00:51 | New, MXML component. In the New MXML Component
wizard, set the file name as
| | 00:58 | LoginWindow, base your new custom component
on the Panel container. Remove any
| | 01:07 | Width or Height settings so that you
will allow the window to resize
| | 01:11 | automatically depending on its child elements
and set the Layout property to
| | 01:16 | Vertical, then click Finish. The Panel container
has a couple of good standard
| | 01:21 | properties that you can use to control
the appearance of the custom pop-up.
| | 01:25 | For example, the title property determines
the text that appears in the
| | 01:31 | top-left corner of the Panel's header. Set
the title property of the panel to
| | 01:35 | Please Login In. Create a Form container
within the panel consisting of a set
| | 01:42 | of form tags and then go to Design View,
so that you can use the Components
| | 01:47 | View to start creating the form. When you
go back to Design View, if you don't
| | 01:52 | see the Components View appear, go to the
Window menu and select Components
| | 01:57 | which you will find at the top of the menu.
| | 01:59 | Now, drag in a couple of visual controls.
Go to the Components View and scroll
| | 02:04 | down until you see the text input control,
then drag it and place it inside the
| | 02:09 | form. Make sure that the blue selector is
inside the form rectangle, it's very
| | 02:14 | small and sometimes a little hard to see
on these videos, but on your own
| | 02:18 | computer screen you should see that it is
accurately showing you that you are
| | 02:22 | dropping the text input control into the
form. Notice that when you drop the
| | 02:26 | text input control into the form, it wraps
the text input inside a form item.
| | 02:33 | Double click on the form item's label to
change its setting and set it to User
| | 02:37 | Name. Now click on the text input control,
make sure that you can see the Flex
| | 02:42 | Properties View and again if you can't go
to the Window menu and select Flex
| | 02:47 | Properties, which you will find as
the second item on the menu.
| | 02:51 | With the text input control selected set
the ID to userinput. Now, drag in
| | 02:58 | another text input control. Place this new
text input control inside the form
| | 03:04 | but right underneath the existing form item
container. You will know when you
| | 03:08 | are placing in the right place when the blue
selector line expands to the width
| | 03:13 | of the form item container that is inside
the form. Once again if you drop it
| | 03:18 | in the right place you will see a label
and the form item container wrapped
| | 03:21 | around it. Double click on the label and
type password and a colon and press
| | 03:27 | Enter or Return.
| | 03:29 | Then once again click on the text input control
inside the form item, go to the
| | 03:34 | Flex Properties View and set the ID to passwordinput.
Also set the Display as
| | 03:41 | password value to true, that will mean
that when the user types a value and
| | 03:45 | they will see asterisk instead of the actual
string that they type in. Next we
| | 03:49 | are going to create buttons wrapped in
a control bar, just as with Panel
| | 03:53 | containers that are displayed inline in
the application, a Panel container
| | 03:57 | being used as a pop-up window can wrap
all of its button controls inside a
| | 04:02 | control bar which will appear as the footer
of the panel or the pop-up window.
| | 04:07 | Go back to the Components view and scroll
down to the Layout section. Drag in
| | 04:12 | the control bar and place it under the form
container. It will drop into place
| | 04:17 | at the bottom of the panel. Now add a
couple of buttons, go back to the
| | 04:22 | Components View to the control section and
drag in two buttons. Place it inside
| | 04:28 | the control bar. You will know you are in
the right place when the little blue
| | 04:32 | indicator is in the footer area of the
panel. Drop in the first button then
| | 04:38 | drag in another button then place it next
to the first. Set the labels of the
| | 04:42 | two buttons as follows.
| | 04:44 | You can double click on each button control
to set its label, set the label of
| | 04:48 | the first button to Log In and then double
click on the second button and set
| | 04:54 | its label to Cancel. You have now created
a custom component that's suitable
| | 04:59 | for use as a custom pop-up window. In the
next video I will show you how to
| | 05:04 | instantiate this component using ActionScript
code and then how to use the
| | 05:08 | PopUpManager class to display the component
as a floating pop-up window.
| | Collapse this transcript |
| Displaying and centering custom popup windows| 00:00 | In this video I am going to describe how
to instantiate a custom pop-up window
| | 00:05 | and then show it using the PopUpManager
class. I will be using the custom
| | 00:09 | component that I created in the previous
exercise. There is also a completed
| | 00:14 | version of that exercise file in the windows
folder of the project named
| | 00:18 | LoginWindowComplete.mxml. If you are starting
on this video, you can use that
| | 00:23 | file instead and just rename it as LoginWindow.mxml.
If you are following along
| | 00:28 | with the exercises, go to the project
and then open the application file
| | 00:32 | UseCustomPopup.mxml and take a look at the
existing code. This application is
| | 00:39 | going to display a login window
upon application started.
| | 00:43 | So I have created a function named Init with
returns void and then called that
| | 00:47 | function upon the applicationComplete event
of the application component. There
| | 00:52 | is a label component at the bottom of the
application that I will use later on
| | 00:56 | to display the results of the login. The
first step to displaying a custom
| | 01:00 | pop-up window is to instantiate the component
you are using. Typically you do
| | 01:05 | this outside of any functions, so that
you can address the window from any
| | 01:09 | function in the application. Place the cursor
in the Script section before the
| | 01:13 | Init function but inside the CDATA block.
Then declare a new private variable
| | 01:18 | named loginWin and data type it as your
custom component LoginWindow.
| | 01:24 | Notice that when I select the LoginWindow
component from the list of available
| | 01:27 | classes, that an Import statement is created
automatically for me. Now go to
| | 01:32 | the Init method. The next step is to instantiate
the window. Upon application
| | 01:38 | startup, I will create an instance of the
LoginWindow component and I will use
| | 01:42 | the predeclared LoginWin variable. I
will use this code loginWin=new
| | 01:50 | LoginWindow. The next step is to use the
PopUpManager and one of its static
| | 01:56 | methods to display the window. Start by typing
PopupMan, then press Ctrl+Space
| | 02:03 | to see the list of available classes and
select PopUpManager from the list.
| | 02:08 | Notice that Flex Builder automatically adds
an Import statement for this class.
| | 02:12 | Now, type in dot(.) character and you will
see a list of all of the static
| | 02:15 | methods of the class and select the first
one addPopUp. The addPopUp method is
| | 02:21 | used to display an existing window on the
screen. We have already instantiated
| | 02:26 | the window in memory. Now, we are going
to say show it to the user. Add the
| | 02:30 | loginWin variable as the first argument.
The next argument is the parent
| | 02:34 | window, that is the window that will be
use to calculate the position of the
| | 02:38 | pop-up. As I did in the Alert class demonstrations
earlier I will type in this.
| | 02:44 | The next value is a Boolean property named
modal, which determines whether this
| | 02:49 | pop-up window will block access to the
rest of the application. As with the
| | 02:53 | Alert pop-up, you can display custom pop-ups
either modally or non-modally. A
| | 02:58 | modal window blocks access to the rest of
the application, while a non-modal
| | 03:02 | window allows the user to continue interacting
with other elements. Because we
| | 03:07 | want the user to have to login before
they continue with the rest of the
| | 03:10 | application, I will pass in a value of true.
That's all I need. I will run the
| | 03:16 | application and let's take a look at the
result. As the application starts up,
| | 03:20 | the LoginWindow appears in the top left corner.
| | 03:23 | This is the default position of the LoginWindow,
the user can click and drag
| | 03:28 | the LoginWindow around the screen and when
they release the mouse button, its
| | 03:32 | position will be retained on the screen.
Close the application and I will show
| | 03:36 | you a couple of ideas about how to position
the window on screen. One approach
| | 03:41 | is to use X and Y properties just like
you would with components that are
| | 03:45 | placed in an absolute positioned container.
I will set LoginWin.x to a vale of
| | 03:50 | 100 and LoginWin.y to a value of 100.
I will save the changes and run the
| | 03:57 | application again and notice that as the
application starts up, the dialog
| | 04:02 | appears in a specific position relative
to the top-left corner of the
| | 04:06 | application.
| | 04:07 | Here is another approach though. Rather
than using X and Y properties, you
| | 04:12 | might want to center a custom pop-up
window in the direct center of its
| | 04:15 | containing window, the application. The PopUpManager
class has a static method
| | 04:20 | for this purpose to call this code. PopUpManager.centrePopUp
and then pass in
| | 04:27 | the reference to the pop-up window which
I have called loginWin. Run the
| | 04:31 | application again and this time as the application
starts up, you will see the
| | 04:36 | pop-up window appear in the direct center
of the application and after user
| | 04:40 | resizes the browser, you will notice
that the pop-up window doesn't
| | 04:44 | automatically reset its position. That's
because this is not like constrained
| | 04:48 | properties where the position is being
continually recalculated.
| | 04:52 | The centering of the pop-up window only
happens upon the explicit call to the
| | 04:56 | PopUpManagers centerPopUp method. So, that's
a look at how to display a pop-up
| | 05:02 | window. Now, in the next video I will
show you have to remove the pop-up
| | 05:05 | programmatically using another method
of the PopUpManager class.
| | Collapse this transcript |
| Removing popup windows| 00:00 | In this video I am going to describe how
to create a custom component that
| | 00:04 | displays a Close icon in the upper right
hand corner and how to handle the
| | 00:08 | event that's dispatch when the user clicks
that icon. I will then show you how
| | 00:12 | to remove the pop-up from the screen in reaction
to the event both from within
| | 00:16 | the component and from the application
code. To get started with this
| | 00:20 | demonstration, if you are following along
with the exercises, go to the windows
| | 00:24 | folder and open the file LoginWindow.mxml
that was created previously or if you
| | 00:30 | don't have that file because you didn't
walk through those exercises, you can
| | 00:33 | actually use the file LoginWindowComplete.mxml
and get exactly the same result.
| | 00:39 | In the LoginWindow.mxml component, I am
going to save it as a new component
| | 00:43 | name, named LoginWindowWithClose.mxml and
then I am going to change its root
| | 00:48 | element from panel to title window. The
nature of that title window container
| | 00:54 | is that it's a subclass of the panel container
that adds the ability to display
| | 00:58 | and then dispatch events for a Close icon.
In the LoginWindow.mxml file, change
| | 01:04 | the root element from Panel to TitleWindow.
Be sure to do this in the both the
| | 01:09 | start and the end tags. Because the custom
component is now a TitleWindow
| | 01:14 | instead of a Panel, you will now have
access to a new property called
| | 01:18 | ShowCloseButton. This property is Boolean,
it takes a true or false value and
| | 01:24 | when set to a value of true, it results
in displaying a Close button in the
| | 01:28 | upper right hand corner of the component.
| | 01:31 | Now, save these changes under a new name
LoginWindowWithClose.mxml. Now, let's
| | 01:38 | go to an application that was using the
original LoginWindow. Open the
| | 01:42 | application file RemovePopup.mxml from the
source root of your project. Notice
| | 01:48 | that this application is using the component
LoginWindowComplete. It isn't
| | 01:53 | using the LoginWindow component because that
wasn't created at the beginning of
| | 01:56 | these exercises for this chapter. But we
are going to change the data type of
| | 02:00 | the window we are creating from LoginWindowComplete
to LoginWindowWithClose,
| | 02:06 | the component we just created. Make the
change in three places, in the Import
| | 02:11 | statement at line 8, in the variable declaration
at line 10 and then in the
| | 02:18 | Constructor method call at about line 14.
| | 02:20 | So, we are being consistent in the data
typing of the object and in the
| | 02:25 | constructor method call. Save your change
and now run this version of the
| | 02:30 | application. As the application starts up,
it once again displays and centers
| | 02:35 | the pop-up window. But now you will see
the Close icon appear in the upper
| | 02:39 | right hand corner as a result of setting
the showCloseButton property to true.
| | 02:43 | If you click this button nothing happens,
the only result of clicking the Close
| | 02:48 | icon is to dispatch a Close event and if
you wanted to do something, you have
| | 02:53 | to listen for the event and handle it in
some fashion. Here are two possible
| | 02:58 | approaches. Close the browser that's displaying
the application and return to
| | 03:02 | the component LoginWindowWithClose.mxml.
When the component dispatches the
| | 03:07 | close event you can listen for it and then
react by closing or removing the
| | 03:13 | pop-up window from the screen.
| | 03:15 | In this version I will add a close event
listener as an attribute to the
| | 03:19 | TitleWindow tag in the component itself.
I will put in the close event listener
| | 03:25 | and then I will call the PopUpManager. Just
as in the application, if you want
| | 03:29 | to call the PopUpManager's methods you have
to import it. In this context you
| | 03:34 | can type in the word Popup, press Ctrl+Space
and then select PopUpManager from
| | 03:39 | the list of available classes. Flex Builder
should react by adding the
| | 03:44 | appropriate Import statement. Now put
in the dot and use this method
| | 03:48 | removePopUp and pass in a reference to the
current component instance, this.
| | 03:54 | Save your changes and then go back to the
application and run it. When the
| | 04:01 | application starts up it once again displays
the component and you should now
| | 04:05 | be able to click that Close icon in the
upper right corner and the window
| | 04:09 | should close leaving a blank application.
| | 04:12 | Typically however, it's usually not a great
idea to have a component close
| | 04:16 | itself in this fashion. Remember that
you added the pop-up window to the
| | 04:20 | interface from coding the application's
scope and that's typically you could
| | 04:24 | practice to remove the pop-up window from
the same scope. So, now let's go back
| | 04:29 | to the component definition and we are just
going to comment out the code in
| | 04:33 | the Close event. We might need the close
event handler later. So I will leave
| | 04:37 | the attribute in but I will just comment
out the code between the quotes using
| | 04:41 | the double slash. Save the changes there,
then go back to RemovePopup.mxml, the
| | 04:48 | application.
| | 04:49 | Place the cursor after line 14 where we
are instantiating the pop-up window
| | 04:53 | component and add a new line of code.
Now, add an event listener,
| | 04:58 | LoginWin.addEventListener and you will listen
for the event that's represented
| | 05:04 | by the CloseEvent class's CLOSE method
and then call a method called
| | 05:08 | closeHandler that will need to create. Now,
place the cursor after the existing
| | 05:14 | function and add a new private function
named closeHandler. The event object
| | 05:20 | that's dispatched with the CloseEvent
is named closeEvent.
| | 05:24 | So, setup your CloseEvent handler to listen
for that event object. Name the
| | 05:29 | argument event and data type it as CloseEvent.
As with all good event handler
| | 05:36 | functions, return void and then within the
body of the closeHandler method, use
| | 05:41 | the same code as you did within the component.
PopUpManager.removePopUp and
| | 05:49 | then pass in the reference to the custom
component that you already added to
| | 05:53 | the interface LoginWin. Save your changes
and test the application.
| | 06:00 | When you click the close icon on the dialog
box, once again it closes the
| | 06:04 | dialog. But now, you are controlling
its closing or more accurately the
| | 06:09 | removing of the pop-up window from the user
interface from the same scope and
| | 06:14 | same code location as where you added it.
This will make it easier to maintain
| | 06:18 | this application and make the application
a little less brittle. So in this
| | 06:22 | video, you learned how to use the TitleWindow
container, a subclass of the
| | 06:26 | Panel, you learned how to use its Close button,
how to display the Close button
| | 06:31 | and how to listen for its close event and
then how to remove a custom pop-up
| | 06:35 | window from the user interface by using
the PopUpManager's static removePopUp method.
| | Collapse this transcript |
| Handling Popup Window events| 00:00 | In this video I am going to describe how
the listen for and react to events
| | 00:04 | that are dispatched from the custom pop-up
window. I already showed how to
| | 00:07 | listen for one event, the Close event that's
dispatched from the TitleWindow
| | 00:11 | container when it's used as a custom pop-up.
In this video, we will listen for
| | 00:16 | custom events that are dispatched from
our own ActionScript code. For this
| | 00:21 | demonstration, I will use a customized
version of the LoginWindow component
| | 00:25 | named LoginWindowWithEvents.mxml. If you
are following along with the exercises
| | 00:30 | you will find this component in the windows
folder under the source root of the project.
| | 00:35 | Open the source and take a look at it. In
this version of the component, I am
| | 00:39 | using the TitleWindow container as the base
or the root element and I am once
| | 00:43 | again using the showCloseButton property
to display the Close icon in the upper
| | 00:47 | right hand corner of the pop-up window.
This version of the component though
| | 00:51 | also declares two events named login and
cancel. In this component when the
| | 00:58 | user clicks the login button, they call a
method called loginClickHandler. This
| | 01:02 | method constructs an instance of a login
value object, passes in values from
| | 01:07 | the form's input controls, wraps the Value
Object in a custom event and then dispatches it.
| | 01:13 | Similarly, when the user clicks
the Cancel button this method
| | 01:17 | cancelClickHandler is executed. And here
I am instantiating the standard event
| | 01:21 | class with an event name of cancel and dispatching
that event to indicate that
| | 01:26 | the user has tried to cancel the login process.
Now, let's take a look at the
| | 01:30 | application. Go back to the Flex Navigator
View and go to the source code root
| | 01:36 | and open this application HandlePopupEvents.mxml.
Go down to the Script section
| | 01:41 | first. Notice that this version of the application
uses the new custom version
| | 01:46 | of the component LoginWindowWithEvents.
It's still listening for the close
| | 01:50 | event that's dispatched when the user clicks
the Close icon in the upper right
| | 01:53 | hand corner of the component and it's calling
the closeHandler method, when that happens.
| | 01:59 | There is also a private function that's been
declared in this application named
| | 02:02 | loginHandler. This custom event handler function
accepts an event object typed
| | 02:07 | as that same login event class that was
instantiated and dispatched from the
| | 02:11 | component. And there was a trace that outputs
the user name and password. I am
| | 02:16 | going to add a little bit of extra code
here to separate the values when we
| | 02:20 | debug. Now, here is how we are going to
listen for the cancel and the login
| | 02:24 | events. Go to the Init method and place
the cursor after the existing call to
| | 02:30 | addEventListener. Add a line of code and
now listen for another event of the
| | 02:35 | LoginWindow component. loginWindow.addEventListener
and this time listen for
| | 02:42 | the cancel event. When the cancel event
occurs, call the same eventHandler
| | 02:47 | function as for the close event, which
we named closehandler. Now, because
| | 02:52 | these are two different kinds of events,
the close event dispatches the
| | 02:55 | closeEvent class and the cancel event
dispatches the standard Flash Event
| | 03:00 | class. Go down to the closeHandler and notice
that this version is using the
| | 03:05 | standard event class as the event object,
not the closeEvent and that will make
| | 03:10 | the closeHandler function compatible with
both uses. Also add one more call to
| | 03:15 | the addEventListener function, this time
listen for the login event and in
| | 03:19 | response call the loginHandler function.
And that will result in passing that
| | 03:24 | event object to this handler, so
we can react accordingly.
| | 03:27 | Save your changes and run the application
in Debug mode. As the application
| | 03:34 | starts up, it shows the login dialog, you
might want to position and size your
| | 03:40 | application browser so that you can see
the Flex Builder console in the
| | 03:43 | background. So we can see the trace output
when we try to login. I will click
| | 03:48 | into the user name and password and type
in a user name and the password and
| | 03:53 | then click the Login button and you should
see a trace output in the console in
| | 03:58 | the background. Showing the user and password
information that was typed in.
| | 04:02 | Now, I will click the Cancel button and you
will see that the window disappears
| | 04:07 | and the application is completely blank.
So, that's the behavior so far. I will
| | 04:11 | modify the code so that the application reacts
a little bit more intelligently
| | 04:16 | to each event. Close the application and
check your Console view to make sure
| | 04:20 | that you have terminated the debugging session.
If it is terminated correctly,
| | 04:25 | you will see that the Terminate button
is deemed out. Now, let's go to the
| | 04:28 | closeHandler. In this application we don't
want the user to be able to escape
| | 04:34 | from the login dialog unless they have
filled in correct information. So if
| | 04:38 | they try to cancel or they click the close
button, instead of calling the
| | 04:42 | removePopUp we are going to
display an error message.
| | 04:46 | Comment out the existing line of code.
In Flex Builder 3 you can do this by
| | 04:51 | placing the cursor anywhere in the line
of code and then you can go to the
| | 04:54 | source menu and select Toggle Comment. You
will notice if you look at the menu
| | 05:00 | that there is also a keyboard shortcut for
this. Now replace that comment to
| | 05:04 | that line of code with this bit of code,
loginWin.errorString = You must login
| | 05:11 | to see the photos. The errorString property
is a property of all visual
| | 05:19 | components in Flex. It results in displaying
the red border around the selected
| | 05:24 | objects that you set the property on and
then when the user moves the cursor
| | 05:27 | over the object such as in this case, the
pop-up window, you will see the error
| | 05:32 | string displayed in a little tooltip on the
side. Run the application this time
| | 05:37 | in Normal mode, try to close the dialog
box and you will see the dialog box
| | 05:45 | turns red because that's the border of the
dialog box and because the cursor is
| | 05:49 | already over the dialog box, you will
see the error message appear.
| | 05:54 | The same thing would happen if you click
the Cancel button. I will refresh the
| | 05:58 | application in the browser so that it appears
in its default presentation and
| | 06:02 | once again you see the error message displayed.
So, now we have handled both
| | 06:06 | the close and the cancel behaviors. Now let's
do with the login behavior. Close
| | 06:12 | the application browser window and go back
to the code. Now before we do any
| | 06:16 | further coding go back to the top of the
application and you will notice that
| | 06:21 | there is a state that's been defined named
photos, which displays some photos
| | 06:25 | on the screen. So, when the Login event happens
I am going to authenticate the
| | 06:30 | user name and password. For this demonstration
I will authenticate by comparing
| | 06:34 | the values of the user name and
password to literal values.
| | 06:37 | In a full production application, you would
probably authenticate the values
| | 06:41 | the users types in against the Database and
LDAP server, the contents of the an
| | 06:46 | XML or some other security model. So, now
here is how we will handle the login
| | 06:52 | process. Place the cursor inside the loginHandler
method and then we are going
| | 06:57 | to compare the values that the user typed
in to some literal strings. I will
| | 07:01 | put in a conditional statement. If event.Login
that's the value object
| | 07:07 | event.Login.username and then I will put
in the double equals equality operator
| | 07:12 | and I will put in the value I am looking
for which is correct user, then I will
| | 07:18 | put in the double ampersand(&&) for the
And operator, then I will check the
| | 07:24 | password as well and I will check that
against a value of correct password.
| | 07:34 | Now I will add the braces. So, if the
user has logged in correctly I will
| | 07:38 | follow the two steps. First of all, I will
take the code that I originally used
| | 07:43 | in the closeHandler method to remove the
pop-up, I will copy that to the
| | 07:48 | clipboard and paste it into my conditional
clause, then I will change the
| | 07:54 | current state of the application to photos
and this will allow the user to see
| | 07:59 | the photos appear if they login correctly.
Now I will add an else clause to the
| | 08:04 | conditional section and once again I will
use the errorString property of the
| | 08:08 | pop-up window loginWin.errorString = Incorrect
login information. Notice that I
| | 08:18 | don't tell them whether the user name or
password was correct. I simply tell
| | 08:22 | them you passed in incorrect info.
| | 08:24 | So, now I will run the application one more
time. I will click into the User
| | 08:33 | Name text input and type in a value that's
not correct and I also type in an
| | 08:39 | incorrect password and I will try to click
Login and I will see the message
| | 08:44 | Incorrect login information. This time I
will type the correct information in,
| | 08:50 | correct user and correct password, I will
login and there is my application
| | 08:57 | authenticated and ready to use.
| | 09:00 | So, this is how you listen for the events
that out of a custom pop-up window.
| | 09:05 | The component itself can declare and dispatch
any custom events you want, you
| | 09:10 | can use a Value Object to wrap the data
from the component if you are sharing
| | 09:13 | data with the rest of the application and
then in the application you listen
| | 09:18 | for the events with the addEventListener
function passing in the name of the
| | 09:23 | event you want to listen for and then indicating
which event handler function
| | 09:27 | you want to use in declarator application.
| | Collapse this transcript |
|
|
2. Animating with Visual EffectsUsing simple effects and triggers| 00:00 | In this chapter of the video series, I am
going to describe the use of effects.
| | 00:05 | An effect in the Flex Framework is a programmatic
animation. Unlike Flash, Flex
| | 00:11 | and Flex Builder don't have a timeline. So,
when you want to cause animation to
| | 00:15 | happen you program them in ActionScript
and an effect is a preprogrammed
| | 00:19 | animation. There are a number of different
animations or effects that are
| | 00:23 | already a part of the Flex Framework and
you can play them in a number of
| | 00:26 | different ways. In this video I am going
to describe the use of effects in
| | 00:30 | association with Triggers. A trigger is
kind of like an event but instead of
| | 00:36 | executing ActionScript code as you would
with an event listener, you play an
| | 00:41 | effect with the trigger. For all of the demonstrations
in this chapter, I will
| | 00:45 | use a project from the exercises folder.
| | 00:47 | If you are following along with the exercises
you can import the project into
| | 00:51 | Flex Builder. Select File, Import, Flex
Project, click the Browse button next
| | 00:59 | to Archive file, navigate to the Chapter02
folder under Exercises and select
| | 01:04 | the project Chapter02BeginProject.zip. Complete
the import process, then go to
| | 01:12 | the Flex Navigator view and open the project
and then open the project source
| | 01:16 | folder. Then open the application file SimpleEffect.mxml.
Let's take a look at
| | 01:23 | the code first for this application. The
application has a Panel container
| | 01:28 | which in turn contains an image. The image
displays a particular JPG file
| | 01:33 | that's in the Assets folder of the project.
| | 01:36 | Within the control bar, there are two buttons
labeled Show and Hide. The Show
| | 01:41 | button executes a bit of ActionScript that
sets the visible property of the
| | 01:44 | image to true and the Hide button sets the
visible property to false. I will
| | 01:50 | run the application so we can see its initial
behavior. The image is displayed
| | 01:55 | within the panel. The black border around
the image is being caused by the
| | 01:59 | background color style of the panel.
When I click the Hide button, the
| | 02:04 | background color of the panel shows through
as black and when I click the Show
| | 02:08 | button, the visible property of the image
is set to true and therefore it
| | 02:11 | becomes visible again.
| | 02:13 | Notice that in the application's initial
state, the image visibility is abrupt,
| | 02:18 | it becomes visible or invisible instantly.
Using an effect, a programmatic
| | 02:22 | animation, you can animate and slow down
the shift from something being visible
| | 02:27 | to invisible. Let's go back to the code.
One way of playing an effect is to
| | 02:33 | create a trigger. A trigger, as I mentioned
is kind of like an event listener
| | 02:38 | except it plays an effect. It runs an animation.
For this image control I am
| | 02:43 | going to use two triggers named showEffect
and hideEffect and in fact if you
| | 02:48 | look in the documentation for any particular
visual component, you will find
| | 02:52 | the list of triggers in the documentation.
| | 02:55 | Here is the first example. I will add a
showEffect trigger and associate it
| | 03:00 | with the Fade class. A Fade class causes
an object's Alpha setting to go from 0
| | 03:06 | to 1, that is from fully transparent to fully
opaque or from 1 to 0, from fully
| | 03:12 | opaque to fully transparent. When you pass
in the name of an effect class in
| | 03:16 | this fashion, you are telling the control
to use the effect class with all of
| | 03:21 | its default properties and the Fade class
will automatically set what we call
| | 03:25 | its alpha to and alpha from properties
based on whether you are making the
| | 03:29 | object appear or disappear.
| | 03:31 | I will also add a hideEffect trigger and
set it to the same effect class Fade.
| | 03:37 | I will save the changes and run the application
and now, I will click the Hide
| | 03:42 | button to make the object go away and you
will see that it fades out of view
| | 03:47 | and then I click the Show button and it will
fade back into view. Going back to
| | 03:53 | the code I will show you another effect.
This one is called the Iris, the
| | 03:59 | purpose of the Iris effect is to mask the
object or unmask it, starting from
| | 04:04 | the center or from the outside. Take a
look at the result. I will run the
| | 04:09 | application and once again hide and show
the graphic. When I hide it, it
| | 04:14 | collapses inward and when I show it, it
unmasks from the center outward.
| | 04:19 | There are any number of effects that you
can use but again when you pass in the
| | 04:23 | name of the Effect class in this fashion,
you are accepting the default
| | 04:27 | properties of the effect. Its also possible
to create your own custom effect by
| | 04:33 | instantiating the effect class using either
MXML or ActionScript and then
| | 04:37 | setting its properties. Let's try that. I
will place the cursor above the Panel
| | 04:42 | container and then I will create an Iris
using MXML markup and I will give the
| | 04:48 | Iris object an id of myIris. This time
I will set a duration, the duration
| | 04:55 | property for all effects is the amount
of time you want to take to play the
| | 04:58 | effect. I will set it to a value of 2000,
which means 2 seconds because in the
| | 05:04 | Flex Framework, the duration is set in
terms of milliseconds, that's 2000
| | 05:09 | thousands of a second.
| | 05:10 | I will complete the MXML tag and then I
will go down to the image control and
| | 05:15 | change both the showEffect and the hideEffect
triggers. When you refer to an
| | 05:20 | instance of an effect class, you refer to
it using a binding expression. So I
| | 05:25 | will put in pair of braces and then within
the braces refer to the id of the
| | 05:30 | Iris object, myIris and I will do the same
thing with the hideEffect as well. I
| | 05:35 | will save the changes and run the application
and then once again I will hide
| | 05:44 | and show the graphic and you will see
that now the effect runs much more
| | 05:48 | slowly. It takes a full 2 seconds to either
hide or show. There is one more
| | 05:53 | application in the project that's worth
looking at this point. Open the
| | 05:57 | application EffectSelector.mxml, in this
application I have created instance of
| | 06:02 | some of the most commonly used effects
that are associated with hiding and
| | 06:06 | showing an object. The Fade, the Dissolve,
the Iris, the Zoom and then for
| | 06:10 | wiping effects WipeRight, WipeLeft, WipeUp
and WipeDown. Each has an id and
| | 06:17 | then towards the bottom of the application,
there is a set of radio button
| | 06:21 | controls, each of which is associated
with one of the effect objects.
| | 06:25 | Finally, in the image control which in this
application is at the bottom below
| | 06:29 | the panel, both the showEffect and the hideEffect
triggers are associated with
| | 06:33 | the effects selected through the radio
button group through the binding
| | 06:37 | expression effectGroup.selectedValue.
I will run the application and
| | 06:42 | demonstrate its behavior. This application
allows you to test various effects
| | 06:50 | and see what they will do. With the Fade
selected I will hide and show and you
| | 06:56 | will see it once again fade in and out. Now,
I will try the Iris again and hide
| | 07:02 | and show. And now I will show you some
of the wiping effects. This is a
| | 07:07 | WipeLeft, it's a masking effect which means
it shows or hides the object rather
| | 07:13 | then changing its dimensions, position
or other visual aspects.
| | 07:18 | Here is the WipeDown effect, I will select
it and then click Show and Hide.
| | 07:24 | Now, the Dissolve effect. The difference
between the Fade and the Dissolve is
| | 07:28 | that you associate a color with the Dissolve
and when you select the effect it
| | 07:33 | creates that color as a background and then
allows the Alpha of the object to
| | 07:38 | either go from 0 to 1 or from 1 to 0, using
the background as the transition
| | 07:43 | color. It will do this in both directions
and in this particular version of the
| | 07:48 | Dissolve I am using the color of black.
Finally, the zoom effect, the zoom
| | 07:53 | effect changes the size of an object from
the inside out or from the outside
| | 07:58 | in. With the zoom effect you will sometimes
see a little bit of a flash, every
| | 08:02 | time you show or hide the object.
| | 08:04 | For instance, when you show the object, every
once in a while you will see the
| | 08:07 | object appear quickly than disappear and
then show again. There are some things
| | 08:12 | you can do to solve that, but if you don't
like the use of the zoom effect, you
| | 08:16 | can instead use the Iris which is similar
in its visual feeling but doesn't
| | 08:20 | have that flickering side effect. So, this
has been a look at how to use basic
| | 08:25 | effects. In the next video I will show
you how to apply more customized
| | 08:29 | properties to a particular effect called
the Move effect that allows you to
| | 08:34 | animate the movement of an object on the screen.
| | Collapse this transcript |
| Customizing animation with effect properties| 00:00 | In this video I am going to describe how
to set and use properties of effect
| | 00:04 | objects. As I showed in a previous video,
you can create your own effect
| | 00:08 | objects by instantiating them using either
MXML or ActionScript and then you
| | 00:13 | can set the specific properties of each
effect class to modify its behavior.
| | 00:18 | For this demonstration I will use an application
from the Chapter02Begin
| | 00:22 | project named EffectPropertes.mxml. If
you are following along with the
| | 00:27 | exercises, open that file now. Then, go
take a look at it in Source view.
| | 00:33 | In this application I am once again displaying
an image with its source set to
| | 00:37 | the buckinghampalacesmall.jpg file. This
image is placed into an application
| | 00:41 | with its layout set to absolute and the X
and Y properties of 200 -- placed the
| | 00:46 | image 200 pixels from the left and top of
the application. There are already
| | 00:51 | hideEffect and showEffect triggers that
are bound to instances of the Fade
| | 00:55 | class and then as before two buttons that
set the visible properties of the
| | 00:59 | image to either true or false. In the current
version of the application when I
| | 01:04 | either hide or show the image, I am
using the Fade class to do so.
| | 01:09 | So, lets now go back to the code. As I
described earlier, you can set specific
| | 01:16 | properties of each object, every effect
class supports the duration property
| | 01:21 | which is set in terms of milliseconds. So,
if I set the duration of both Fade
| | 01:25 | classes to 1000 that means that each fade
will take one second. I will run the
| | 01:32 | application again, once again show and hide
the image and now it takes one full
| | 01:37 | second to either appear or disappear. Each
Fade class has its own unique set of
| | 01:42 | properties that allow you to determine
how its going to do what it does.
| | 01:46 | You can take a look at the documentation
for any class by placing the cursor in
| | 01:50 | the tag name and then pressing F1 in Windows.
I will press the F1 key and
| | 01:55 | restore the editor so I can see the Help
view and then in the relevant API
| | 02:00 | section of the Related Topics, I will click
the Fade class, that will open up
| | 02:05 | the help system for the fade class.
I will expand the Help editor by
| | 02:09 | double-clicking on the tab and then take
a look at the properties listing.
| | 02:14 | Notice that the first two properties listed
under the Fade class or alphaFrom
| | 02:18 | and alphaTo. These are properties that
are particularly relevant to this
| | 02:22 | particular class. The Alpha property for
any component when set to a value of
| | 02:26 | zero means it fully transparent and when
set to one means fully opaque.
| | 02:31 | So, the Fade class is used to go from an
alpha of zero to an alpha of one over
| | 02:36 | some amount of time. Let's take a look at
another useful effect called the Move
| | 02:42 | effect, I am going to change both of my
effects from Fade to Move. I will
| | 02:48 | restore the source code editor then press
F1 while the cursor is in the Help
| | 02:52 | tag, click on the link for the appropriate
tag Move and then double click the
| | 02:57 | Help tab to expand the help to full screen.
Now I will click on the properties
| | 03:02 | link within the documentation and then hide
the inherited properties because I
| | 03:07 | am really only interested and looking at
the properties that are specific to
| | 03:10 | this class.
| | 03:12 | The purpose of the Move effect is to move
an object around the screen. There
| | 03:17 | are properties named xBy, xFrom and xTo and
yBy, yFrom and yTo. The From and To
| | 03:24 | properties are absolute positions. For example,
if you wanted to move an object
| | 03:29 | from one specific position to another
you would set either the x or the y
| | 03:33 | versions depending on whether you want it
to move horizontally or vertically.
| | 03:37 | The By properties xBy and yBy indicate how
many pixels you want to move in each
| | 03:43 | direction. For a positive number for xBy
property means move to the right and a
| | 03:48 | negative means move to the left and for
the yBy, a positive number means move
| | 03:52 | down and negative means move up.
| | 03:54 | I am going to use the From and To properties
for both x and y, to move my image
| | 04:00 | across the screen to make it appear and
disappear. I will close the Help view
| | 04:05 | and then go back to the source code. For
the Move effect that I am using for
| | 04:08 | showing the object I will set these properties.
A negative value for the xFrom
| | 04:13 | property means that the object will start
off the screen to the left and then I
| | 04:18 | will add an xTo property and I will set
it to the final position of the image
| | 04:22 | object to 100 pixels from the left side
of the application. Now I will do the
| | 04:27 | same thing for the Move effect being used
to hide the object but I will reverse
| | 04:31 | the values.
| | 04:33 | The xFrom will be a positive 200 and the
xTo will be a negative 200. Because I
| | 04:38 | am not moving the object vertically at all,
it will retain its predeclared y
| | 04:43 | position of 200 pixels. I will save the changes
and run the application. Now I
| | 04:50 | will click the hide button to set the visible
property to false and the effect
| | 04:54 | will be to move the object off the screen.
Now I will show the image and once
| | 04:59 | again the Move effect causes it to slide
on to the screen from the left. This
| | 05:03 | is a bit of a trial and error process.
For example, you may notice that the
| | 05:06 | image slides off to a certain point and
then disappears and then when it's
| | 05:11 | being shown its appearing and then sliding
in, that's because the negative
| | 05:16 | number that I am using as the starting and
ending point for either effect is
| | 05:20 | not large enough. I need to make it wide
enough for the whole image to slide
| | 05:24 | completely off the screen. So I will close
the application and return to the
| | 05:27 | source code and I will change the negative
number from -200 to -300 for both
| | 05:34 | the myShowEffect and myHideEffect. I
will save the changes and run the
| | 05:37 | application again. Once again I will hide
the image and this time it slides
| | 05:44 | completely off the screen and I will
show the image and it starts off
| | 05:49 | completely off the screen and slides back
into position. Now, in the next video
| | 05:53 | I will show you how to use the same Move
effects but with easing functions that
| | 05:57 | cause an object to change it's pace of
movement or to come into a final
| | 06:01 | position and bounce into place.
| | Collapse this transcript |
| Using easing functions| 00:00 | In this video I am going to describe the
use of Easing functions. An Easing
| | 00:04 | function is a mathematical equation that
describes, in mathematical terms, how
| | 00:09 | an animation degrades or changes over time.
By default when you play an effect
| | 00:15 | its behavior is linear. That is if for instance
you are moving an object, the
| | 00:20 | amount of movement over a half a second
at the beginning of the effect is the
| | 00:24 | same as at the end of the effect. With an
Easing function you can have movement
| | 00:28 | that increases or degrades over time or for
another example have movement that
| | 00:32 | bounces into place.
| | 00:34 | For this demonstration, I will use an
application named EasingFuctions.mxml.
| | 00:40 | This is the same application that I finished
in the previous video. It uses two
| | 00:45 | Move effects, one to show and one to hide
the object and right now the movement
| | 00:49 | for either action is linear. When I click
the hide button, the object slides
| | 00:54 | off the screen and when I click the show
button its slides back into place.
| | 00:59 | Easing functions are built into the Flex
class library, each set of functions
| | 01:04 | is a member of a class which in turn
is a member of a package called
| | 01:07 | mx.effects.easing.
| | 01:09 | I am going to show you the behavior of two
of these classes. The first named
| | 01:13 | Exponential causes movement to degrade or
increase over time and the other that
| | 01:19 | I am going to demonstrate called Bounce causes
the Bounce effect that I talked
| | 01:22 | about. There are many other classes that
encapsulate various mathematical
| | 01:26 | approaches to animation. You can investigate
the documentation for each. Each
| | 01:31 | of these classes typically has three functions
that you can select from,
| | 01:34 | easeIn, easeOut and easeInOut. The easeIn
typically starts the motion slowly
| | 01:41 | and then accelerates and the easeOut goes
in the other direction, it starts
| | 01:44 | fast and then decelerates over time.
Here is how we use them.
| | 01:48 | I will go back to the source code and place
the cursor above the move effects.
| | 01:54 | In order to most conveniently refer to
the easing functions, I am going to
| | 01:58 | import the classes I want to use. I will
create a Script section and then
| | 02:03 | import mx.effect.easing and for the first
example I am going to use the
| | 02:10 | Exponential class. Now in order to pass
an easing function to one of the
| | 02:14 | effects, you use the easingFunction property
of the effect object and you refer
| | 02:19 | to the function by its class and the function's
name. For the showEffect I will
| | 02:24 | use Exponential.easeOut. When you type
in the names of the classes and
| | 02:30 | functions here you won't get code
help like you might be use to.
| | 02:33 | Instead you just have to make sure you spell
the name of the class and the name
| | 02:36 | of the function correctly and they are of
course case-sensitive. I will do the
| | 02:41 | same thing for the hideEffect. I will
set the easingFunction this time to
| | 02:45 | Exponential.easeIn. So, now I will save the
changes and look at the behavior. I
| | 02:50 | will run the application, click the Hide
button and now instead of moving off
| | 02:58 | in a linear fashion it starts off slowly
and then accelerates as it goes.
| | 03:03 | Moving onto the screen the behavior is the
opposite, it comes in fast and then
| | 03:08 | parks itself slowing into place.
| | 03:11 | Once again here is the Hide and here is
the Show. So that's the Exponential
| | 03:16 | class. Let's take a look at another one.
Another class that can be useful is
| | 03:21 | called the Bounce class. I am going to
change the import statement so that
| | 03:26 | instead of referring to the Exponential class
I will refer to the Bounce class
| | 03:30 | and then I will make the same change to
each of the easingFunction calls. For
| | 03:34 | each effect I will refer to the same function
name but I will call it from the
| | 03:38 | Bounce class. I will save the changes and
run the application. I will hide the
| | 03:45 | image and watch what happens, notice it
starts by bouncing slowly and then
| | 03:49 | takes off in the left direction and now
the more dramatic and interesting
| | 03:53 | effect is when you show it, where it will
just slide into place and then will
| | 03:58 | look like it bounced against a barrier
and then finally settles.
| | 04:02 | Seeing the effect again, it starts off shaking
and then moving and then sliding
| | 04:07 | into place and bouncing. Again there are
many other Easing function classes
| | 04:12 | that you can investigate and it's also possible
to call these easing functions
| | 04:16 | and customize their behavior by passing
in numeric values to each of their
| | 04:20 | properties. Take a look at the documentation
and some of the sample code that's
| | 04:25 | included in the Flex Framework for some
great examples of using Easing functions on effects.
| | Collapse this transcript |
| Using Sequence and parallel effects| 00:00 | In this video I am going to describe the
use of Compound effects. A Compound
| | 00:04 | effect is a wrapper effect that wraps around
the individual nested effects and
| | 00:09 | causes each of these nested effects to
execute either simultaneously or
| | 00:13 | consecutively. For this demonstration
I will use an application named
| | 00:17 | CompoundEffects.mxml. If you are following
along with the exercises you can
| | 00:21 | open this application from the Chapter02Begin
project. This is the same
| | 00:26 | application I worked on in a previous video.
It uses two Move effects to cause
| | 00:31 | an image to slide on and off the stage. When
I click the Hide button it slides
| | 00:36 | off and when I click the Show
button it slides on.
| | 00:40 | Notice in this version of the application
I am not using any Easing functions.
| | 00:44 | There are two types of Compound effects
known as Parallel and Sequence. A
| | 00:49 | Parallel effect plays two or more effects
simultaneously, while a Sequence
| | 00:53 | effect plays two or more effects one after
the other or consecutively. I will
| | 00:58 | first demonstrate a sequence effect.
I will create a new tag set named
| | 01:03 | mx:Sequence. Now I am going to take the
move with an id of myShowEffect and
| | 01:09 | move it into the sequence. I will select
the Move tag, release the mouse button
| | 01:14 | and then drag and drop the code
into the Sequence tag set.
| | 01:18 | Now, I am going to take the id property
that has a value of myShowEffect and
| | 01:23 | drag and drop that into the Sequence tag.
Now, whenever I make the image
| | 01:27 | appear, I will be running the whole sequence
of effects rather then the Move
| | 01:31 | effect by itself. I am going to change
the effect so that it consist of two
| | 01:36 | separate moves. The first move will be a
slide onto the screen as before but
| | 01:41 | this time it will slide across the screen
at the top. So, I am going to set two
| | 01:45 | new properties, I will set a yFrom of zero
and a yTo of zero. By setting the y
| | 01:53 | position both at the beginning and the ending
of the effect to zero that means
| | 01:57 | the component will stay at the top of
the screen for the whole move.
| | 02:01 | Now I will add a second Move effect after
the first. This one will also have a
| | 02:06 | duration of 1000 or one second and this
effect will cause the image to drop
| | 02:12 | down from the top of the screen into its
final position. I will use a yFrom
| | 02:16 | value of zero and a yTo value of 200,
which matches its y setting in the
| | 02:23 | original image declaration. I will be sure
to close the tag with the /> and now
| | 02:29 | I will run the application to see the result.
When I hide the image it still
| | 02:35 | slides directly off to the left. But now
watch what happens when I show the
| | 02:40 | image. It slides across and then drops down.
Let's the effect again, the hide
| | 02:47 | is the single move, the show is a sequence
of two moves. When you use a
| | 02:52 | Sequence effect, you can add pauses between
the internal effects using a
| | 02:57 | special kind of effect called Pause. The
only really useful property of the
| | 03:01 | Pause effect is its duration. I will add
a little bit of space between the move
| | 03:05 | effect declarations then I will add a tag
mx:Pause and set a duration once
| | 03:12 | again of 1000 for a one second. I will
save the changes and run the
| | 03:17 | application. I will hide the image
and then I show the image.
| | 03:27 | Once again hiding, and notice that when
I show the image, the image slides in
| | 03:32 | the place, pauses a second and then drops
down. So, that's how we use Sequence
| | 03:37 | effects. Like a Sequence effect, a Parallel
is a wrapper around two or more
| | 03:41 | effects but a Parallel place its nested
effects simultaneously. You can nest
| | 03:46 | effects in any order that you want. I am
going to add a Parallel wrapper around
| | 03:51 | the original move. I will create an mx:Parallel
tag set. Now I will take the
| | 03:57 | Move effect and drag it up into the Parallel,
correct all of my tabulation and
| | 04:03 | indentation and now within the Parallel I
am going to add one more effect named
| | 04:08 | Rotate.
| | 04:09 | The default behavior of the rotate effect
is to cause the object to rotate one
| | 04:13 | revolution clockwise, from an angle of
0 to an angle of 360. If you set the
| | 04:19 | angleFrom and angleTo properties and you
reverse them, saying angleFrom of 360
| | 04:24 | and an angleTo of 0, that would cause the
rotation to go counterclockwise. But
| | 04:29 | I want the default behavior, I will also
add a duration of 1000 to match the
| | 04:34 | Move effect. So, both of the effects are
playing over the duration of one
| | 04:37 | second. Let's see the result. I will save
and run the application. Once again
| | 04:44 | when I hide the image it just slides off
to the left. But now when I show the
| | 04:49 | image, it appears to roll on and then drop
down. The appearance of rolling is a
| | 04:55 | combination of the Move and the
Rotate played simultaneously.
| | 05:00 | So, that's a look at using Compound effects,
Sequence effects to play two or
| | 05:04 | more effects consecutively and Parallel effects
to play two or more effects simultaneously.
| | Collapse this transcript |
| Declaring effects inside components| 00:00 | In this video I am going to describe how
to declare effect within custom
| | 00:04 | components. As with any effect you can declare
these effects either using MXML
| | 00:08 | or ActionScript code. As in previous videos
I will be using the MXML approach
| | 00:14 | but this time instead of defining an effect
in an application that affects a
| | 00:17 | component instance, I will define the effect
inside the component and then call
| | 00:21 | it from the application. I will be using
the same set of tools but the overall
| | 00:26 | application architecture will
be a bit different.
| | 00:28 | For this demonstration I will be
using an application named
| | 00:31 | UseComponentEffect.mxml. If you worked through
the previous chapter about using
| | 00:36 | custom pop-up windows, this application
will look familiar. When the
| | 00:41 | application starts up, it prompts the user
for a user name and password. If a
| | 00:46 | user types in the correct user name and password,
they will see a photo gallery
| | 00:49 | but if we type in an incorrect user name
and password currently this components
| | 00:53 | simply turns red and displays an error message.
| | 00:55 | I am going to add a visual effect to this
component to make it shake back and
| | 01:00 | forth if the user types an incorrect information.
This will mimic the user
| | 01:04 | interface of Mac OS 10. When you enter the
user name and password information
| | 01:08 | to authenticate yourself on that Operating
System the dialog box basically
| | 01:12 | shakes its head back and forth to indicate
that the information was wrong. We
| | 01:16 | will do the same here. I will close the
application and open the component
| | 01:22 | LoginWindow.mxml from the windows folder.
This again is the same code that I
| | 01:27 | used in a previous chapter. It defines and
dispatches custom events to share
| | 01:32 | information about the user's action and the
data that the user has entered with
| | 01:36 | the rest of the application.
| | 01:38 | I will start by declaring a Sequence event.
You can place this anywhere within
| | 01:42 | the component code. I am going to place it
after the Script section but before
| | 01:47 | the form. I will create a Sequence and I
will give it an id of shakeEffect. Now
| | 01:54 | within the sequence I am going to do a series
of moves. The first move we will
| | 02:00 | use an xBy value of 5 pixels. That means
the entire window will move 5 pixels
| | 02:05 | to the right and I will set a duration of
15 milliseconds. Now, I am going to
| | 02:11 | clone that line of code by pressing Ctrl+Alt
and the Down arrow. If you are on
| | 02:15 | the Mac that would be Command+Alt
and the Down arrow.
| | 02:20 | In the next move I will go -10, meaning
go 10 pixels to the left. I will add
| | 02:28 | another move effect and that will be a 10,
meaning go 10 pixels to the right.
| | 02:34 | Now I will select these two move effects
and clone those and finally put in one
| | 02:39 | more move effect with an xBy value of -5.
| | 02:42 | So, now I have defined a sequence of moves
where I simply shake the object back
| | 02:46 | and forth by a few pixels and each move is
happening in 20th of a second or 50
| | 02:52 | milliseconds. So, the entire fact just takes
a fraction of a second. Now, I am
| | 02:58 | going to set a property of the sequence called
the target. The target property
| | 03:02 | indicates what object is going to be affected
when this sequence is played and
| | 03:07 | I will use a binding expression wrapped
around the value this, meaning that I
| | 03:11 | am going to animate the current instance
of the current component. So, that's
| | 03:16 | the definition of the component effect.
| | 03:18 | Now, I am going to create a public interface
that allows the application to
| | 03:22 | make this effect happen. I will go up
to the Script section and add a new
| | 03:27 | public function. The name of the function
is simply going to be shake. It will
| | 03:34 | receive no arguments and it will return
void and it is going to call the
| | 03:38 | following code, shakeEffect.play. Notice
the play method excepts a number of
| | 03:44 | optional arguments. Because I already defined
the target of the effect this,
| | 03:50 | that is the current instance of the current
component, I don't need to pass any
| | 03:54 | of these values in. I will simply call the
play method with no arguments. So,
| | 03:59 | that completes the definition of the effect
and creates the public interface to
| | 04:03 | call it from the application.
| | 04:05 | Save those changes and now go to the application
UseComponentEffect.mxml.
| | 04:12 | Locate the loginHandler method inside the
Script section. This is the code that
| | 04:16 | checks the users information and compare
it to certain values. We are looking
| | 04:21 | for values of correctUser and correctPassword.
If the user doesn't pass in
| | 04:26 | those values currently, we are just displaying
an error string which is turning
| | 04:30 | the object red and displaying the pop-up
error message. Go to the else clause
| | 04:34 | of this conditional statement and add the
following code, loginWin.shake. So,
| | 04:42 | now we are going to display the error string
but we are also going to tell the
| | 04:45 | window to shake itself.
| | 04:47 | Save the changes and run the application.
Click the Login button without
| | 04:55 | entering any password information and you
should see the pop-up window shake
| | 04:59 | back and forth very quickly at the same
time it turns red and displays the
| | 05:03 | pop-up error. Try it again, click Login
and once again you will see that the
| | 05:09 | dialog box shakes every time you click. Now,
type in the correct password which
| | 05:14 | is the word correctPassword with an upper
case P, click the Login button and
| | 05:21 | this time you see the gallery of photos.
| | 05:23 | So, that's how we encapsulate effects within
custom components. The declaration
| | 05:28 | of the effect is exactly the same as
when declaring it in the larger
| | 05:31 | application. In this case however, I used
the target property to refer to the
| | 05:36 | object I wanted to animate that was the
current instance of the current
| | 05:39 | component, created a public method that would
allow the application to make the
| | 05:43 | effect happen and then called that
method from the application.
| | Collapse this transcript |
| Using effects with view states as transitions| 00:00 | In this video I am going to describe how
to use Transitions. A Transition is an
| | 00:05 | effect that's applied during a move from
one view state to another. You declare
| | 00:10 | transitions using MXML and then they cause
effects to be played when you move
| | 00:14 | from one state to another. For this demonstration
I will use an application
| | 00:19 | named UseTransition.mxml. If you are following
along with the exercises, you
| | 00:23 | can open this application file from the
project. In the application source,
| | 00:28 | there is a view state named Detail. When
you first run the application you will
| | 00:33 | see four images displayed in a grid. When
you move the mouse over any of the
| | 00:37 | images and then press the mouse button,
you will see the image appear as part
| | 00:41 | of the new view state and when you release
the mouse button you go back to the
| | 00:46 | base state that displays just the
small versions of the images.
| | 00:49 | Notice that the change to the detail state
and the reverse and back to the base
| | 00:53 | state are abrupt, that is the larger
picture appears quickly and then
| | 00:57 | disappears quickly. I am going to add
Transition declarations to this
| | 01:01 | application, so that whenever the image appears
it's animated both zooming and
| | 01:06 | moving into place and when it disappears,
it goes away through a fading effect.
| | 01:12 | Go back to the source code and add some
code below the states property in the
| | 01:16 | application. You always declare each transition
within a transitions tag set.
| | 01:23 | This architecture is very similar to that
of the states. you start of with a
| | 01:27 | set of mx:transitions tags and then for
each transition that you want to
| | 01:31 | declare, you create a transition tag set.
| | 01:35 | The transition tag has two required properties
called fromState and toState.
| | 01:40 | Each of these properties can either name
a specific state, for instance you
| | 01:44 | could put in the two state value of detail
and then this transition would be
| | 01:48 | defined only when you are moving to that
particular state or you can use an
| | 01:52 | asterisk as a wild card to indicate that
either for the toState or the
| | 01:56 | fromState, you can use it for any state
transition. I am going to add a
| | 02:00 | fromState property of an asterisk meaning
going from anything and a toState
| | 02:06 | property of detail and this matches the
state name of detail that's already
| | 02:10 | been declared. Now, within the transition
we declare an effect. In this case I
| | 02:15 | am going to declare a parallel
effect that looks like this.
| | 02:18 | I will create the parallel and then I
will set a target. This is the same
| | 02:23 | target property I used in a previous video
to indicate which object I am
| | 02:27 | animating and I am going to use a binding
expression and refer to an object
| | 02:31 | that has an id of detailImage. The detailImage
object is the larger version of
| | 02:36 | the image that's being added when you
move to the detail view state. Now,
| | 02:40 | within the parallel we are going to do two
effects simultaneously, a Move and a
| | 02:46 | Zoom. First create the Move effect. Give
it an id of customMove. By adding an
| | 02:52 | id to an effect, we will be able to
modify it on the fly later on.
| | 02:57 | Set the xFrom property at 0 meaning you
are going to start from the left side
| | 03:01 | of the screen. Also set the yFrom value
to 0 and then set the xTo and yTo
| | 03:08 | values to the same positions of as the actual
image decoration. The xTo will be
| | 03:14 | 300 and the yTo will be 50. Now add a Zoom
effect. The purpose of a Zoom effect
| | 03:22 | is to start an object off, it's very small
and then expand it into place. You
| | 03:27 | declare the Zoom effect once again with and
MXML tag mx:Zoom and now I will set
| | 03:32 | some specific properties. I will set the
zoomHeightFrom value to 0 and the
| | 03:38 | zoomWidthFrom to 0 and these will be the
starting size of the object, and then
| | 03:43 | I will set the zoomHeightTo and zoomWidthTo
to values of 1, which means full
| | 03:48 | size.
| | 03:49 | You don't put in the actual pixel values
here. Zero means nothing and 1 means
| | 03:55 | the complete size of the object whatever
it might be. Once again, I will set
| | 04:01 | zoomHeightTo and zoomWidthTo to full size,
meaning 1. Lets just use that
| | 04:06 | transition initially. Save the changes and
run the application, try clicking on
| | 04:13 | any graphic and you will see that now the
image flies in from the top left
| | 04:17 | corner of the application and zooms to full
size at the same time. You can do
| | 04:22 | this for any of the images and if you look
at the code in the application you
| | 04:27 | will see that upon the mouse down event
on the image control we are capturing
| | 04:31 | whichever image is clicked on and supplying
that information to the detailImage
| | 04:35 | component.
| | 04:38 | Now let's add another transition and this
will be the transition that happens
| | 04:42 | when the image goes away. Place the cursor
after the first transition but still
| | 04:47 | within the mx:transitions tags. Create another
transition tag set and this time
| | 04:53 | set the fromState value to detail meaning
we are going away from that state and
| | 04:58 | the toState to once again an asterisk.
This transition is going to be a
| | 05:03 | sequence, where we fade the object out
and then remove the object from the
| | 05:07 | screen. This is how we are going to choreograph
the order of effects. If you
| | 05:12 | don't do this in the right order you will
see that object start to flicker and
| | 05:16 | then fade out. So, add a pair of mx:Sequence
tags, once again use the target
| | 05:23 | property to indicate what object
you are animating detailImage.
| | 05:28 | Now within the sequence, add a fade effect
and set the alphaFrom to 1 and the
| | 05:35 | alphaTo to 0, meaning that you are
going from fully opaque to fully
| | 05:39 | transparent. Now, add a tag called RemoveChildAction.
This means that you are
| | 05:44 | going to wait until after the fade has been
accomplished before you actually
| | 05:48 | remove the object from the display list of
the container, the application. Then
| | 05:54 | finally add one more fade. The purpose
of this fade effect is to reset the
| | 05:59 | alpha value or the transparency value of
the object to fully opaque. So, next
| | 06:05 | time you try to use the effects everything
will still work. Save your changes
| | 06:10 | and try running the application again. Once
again I will click on any of the
| | 06:14 | images and it will fly in from the top-left
of the application and then I
| | 06:19 | release the mouse and notice that it now
fades out of view. And this again will
| | 06:23 | work no matter which image you click on.
| | 06:26 | Click to make to fly in, release the mouse
button to make it fade away. Let's
| | 06:31 | make one more customization. Notice that
in the transition that's being used as
| | 06:37 | I go into the View state I am using a parallel
effect wrapped around a move and
| | 06:41 | a zoom and the move has an id of customMove.
I am going to use that id and
| | 06:48 | change the value of the xFrom and yFrom
so that instead of having the object
| | 06:52 | fly in from the top left of the application,
I am going to have it fly from the
| | 06:56 | position of the mouse click and here
is how we will accomplish that.
| | 07:00 | Scroll down to the Script section of the
application. Notice that there is a
| | 07:04 | method there named showDetail. The showDetail
method is an eventHandler
| | 07:09 | function, it's receiving an event typed
as mouseEvent and you will be able to
| | 07:13 | capture information about the location of
the mouse at the movement that the
| | 07:17 | mouse was clicked. Place the cursor inside
the function above the existing code
| | 07:22 | and we are going to change the xFrom and
yFrom properties of the move object
| | 07:27 | and set them to the values of stageX and
stageY properties of the event object
| | 07:32 | like this, customMove.xFrom = event.stageX.
So, that means we are setting the
| | 07:44 | xFrom property that is the horizontal starting
position of the move object
| | 07:49 | based on the horizontal position of the
mouse. Do the same thing for the Y
| | 07:53 | dimension, customMove.yFrom = event.stageY.
| | 08:01 | Save your changes and run the application.
Click on any of the images and this
| | 08:08 | time you will see that the image flies in
from wherever you click. Instead of
| | 08:12 | always flying in from the top-left corner
of the application we are now
| | 08:16 | capturing the position of the mouse click
and customizing the behavior so that
| | 08:21 | it looks like we are paying attention to
what the user is doing. Transitions
| | 08:25 | can be applied to many different kinds
of movements, from one view state to another.
| | 08:30 | Each transition takes an effect which is
very commonly a combo effect such as a
| | 08:35 | parallel or sequence but really can be any
effect you like. The purpose of the
| | 08:40 | transitions is to allow you to choreograph
and slow down the movement from one
| | 08:44 | state to another and make it easier for the
user's eye to track what's going on the screen.
| | Collapse this transcript |
|
|
3. Using Graphical Skins with Flash and FlexUsing the default Flash graphical skins library| 00:00 | In this chapter of the video series,
I am going to describe the use of
| | 00:03 | graphical skins, to customize the look and
feel of your Flex applications. A
| | 00:08 | graphical skin is a graphic built in either
Bitmap or Vector format. The
| | 00:13 | purpose of the skin is to change the look
and feel of a Flex component at
| | 00:17 | runtime. The Flex framework comes with
the set of pre-built graphical skins
| | 00:22 | that are delivered in flash format. You can
find a source FLA file and open it
| | 00:27 | in Flash CS3 if you have the product available.
I am going to navigate to the
| | 00:32 | Flex Builder 3 installation folder. On
windows the default location of this
| | 00:36 | folder is under program files, Adobe Flex
Builder 3. If you are working on the
| | 00:41 | Mac, you will find the same folder
under applications/FlexBulider3.
| | 00:46 | In order to find the FLA file that contains
the default skins, navigate to the
| | 00:51 | sdks folder, under the Flex Builder installation
folder. From there go to sdk
| | 00:57 | 3.0, from there to frameworks, to themes
and in this folder you will find a set
| | 01:06 | of themes which are combinations of skins
plus cascading style sheet files. The
| | 01:11 | first one listed alphabetically is called
AeonGraphical. This is the set of
| | 01:15 | graphical skins and styles that constitute
the default look of a Flex 3
| | 01:19 | Application. Navigate into that folder and
you'll find two files with CSS and SWF extensions.
| | 01:27 | The SWF file, is a compiled flash file that
contains the graphical skins for
| | 01:32 | default Flex applications and the CSS file
is the cascading style sheet file,
| | 01:37 | that binds the graphics into the applications.
In order to customize the
| | 01:41 | graphics for your own application, you can
use the source file located in the
| | 01:46 | SRC sub folder under AeonGraphical. This
is a flash file that you can open up
| | 01:51 | in Flash CS3 Professional or Flash 8. I
am going to open the flash file and
| | 01:56 | let's take a look at it. The flash file
consists of a stage, which contains
| | 02:03 | instances of all the different graphics
for each component in the Flex
| | 02:07 | framework. As an example, the Check Box
component involves eight different
| | 02:11 | icons. The icon for the Check Box component
for example has eight different
| | 02:16 | visual presentations.
| | 02:18 | There is a selected icon when it's disabled.
There is a selected icon for when
| | 02:23 | the mouse button is down, over and up and
then four different icons for each of
| | 02:28 | the states when the check box is unselected.
Each of these graphical icons is
| | 02:33 | built as a symbol in the Flash document
library. I'll go over to the Library
| | 02:38 | panel and go to the check boxes section
and here you will find the same eight
| | 02:42 | icons. They are labeled check box disabled
icon, check box down icon and so on.
| | 02:48 | So you can easily identify which icon is
used for which visual state. If you
| | 02:53 | want to customize the look and feel of your
application, one good approach is
| | 02:58 | to use Flash to built Vector graphics.
| | 03:01 | The nature of Vector graphics in contrast
to Bitmap graphics is that they can
| | 03:05 | easily resize. Their visual presentations
are calculated mathematically, rather
| | 03:11 | than bit by bit such as, as the case with
PNG, GIF or JPEG files. So in a Flex
| | 03:17 | application where you might need to stretch
a component, Vector graphics really
| | 03:20 | do the best job. If you want to take one
component's Skins from the default
| | 03:25 | library and create your own customize Flash
document, so you can customize your
| | 03:30 | look and feel for that component. Here
is a very simple way to do it.
| | 03:34 | Open the Aeongraphical.fla file in Flash
CS3 or Flash 8. Then go to the Stage
| | 03:41 | and select all of the objects that you want
to put into your new document. For
| | 03:45 | example I am going to select everything in
this range, the check box label, all
| | 03:51 | of the other labels, but I am also selecting
the Library Symbol Instances. Now
| | 03:56 | I am going to copy those to the clip board,
then I'll create a new Flash
| | 04:02 | document and then I'll paste the same object
on to the stage in the first frame
| | 04:08 | of the timeline. By pasting the object
instances that also causes the same
| | 04:14 | library symbols to be copied into the Flash
document. Now you can go into each
| | 04:18 | of these symbols and customize its look
and feel. For example, I am going to
| | 04:23 | select a check box selected up icon, I'll
right click on the library symbol or
| | 04:28 | Control+Click on the Mac and select Edit.
| | 04:33 | Then I am going to Zoom in to 800%, so I
can see exactly what the graphic looks
| | 04:38 | like. Notice that the graphics in this
movie clip symbol are made up of a
| | 04:42 | number of graphical objects. Am going to
click off the stage and then click and
| | 04:47 | select the Check Mark Graphic. I'll Delete
it and then I'll add my own graphic.
| | 04:53 | I'll click the text tool, click into the
graphic and set the size of the font
| | 04:57 | to a reasonable size. Now I'll put in letter
X to indicate that the value is
| | 05:03 | selected. I'll click off the text object,
select it again and then move it into
| | 05:12 | place so that it's approximately centered.
I would go through and do that with
| | 05:16 | each of these library symbols and then at
the end of the process, I would be
| | 05:20 | ready to actually create a SWT file that
could be imported and used in the Flex application.
| | 05:27 | Now in the next video I am going to use
a Flash document that's already been
| | 05:30 | customized and I'll show you how to
export this for use in Flex.
| | Collapse this transcript |
| Exporting a graphical skins library from Flash| 00:00 | In this video, I'm going to describe, how
to export a component library from
| | 00:04 | Flash, that's suitable for use in importing
into Flex Builder. For these
| | 00:08 | demonstrations, I'm going to use files that
are in a Flex Project, that's the
| | 00:12 | part of the Exercises folder. If you're following
along with the exercises, you
| | 00:16 | can import the project now, from the Flex
Builder menu select File, Import,
| | 00:22 | Flex Project, click the Browse button next
to Archive file and then navigate to
| | 00:27 | the Chapter03 folder under the Exercises
area and import the project
| | 00:32 | Chapter03BeginProject.zip.
| | 00:37 | Once the project has been imported, open
it in the Flex Navigator view and then
| | 00:41 | take a look at a folder within the project
named FlashContent. There are two
| | 00:46 | files with .fla extensions in this folder.
The first one contains the original
| | 00:51 | skins that have been extracted from the
Aon graphical resource file, if you
| | 00:55 | have Flash CS3 or Flash 8 installed in your
system, you will be able to open
| | 01:00 | this file and follow the export process with
me, right click on the fla file or
| | 01:06 | Ctrl+Click with the Mac and then select
Open With, System Editor, don't just
| | 01:12 | double click. In clips, typically that won't
work for this kind of file, after
| | 01:16 | a few moments the file opens in Flash CS3
Professional and you will see that,
| | 01:21 | this version of the file contains
the original graphical skins.
| | 01:25 | Now, switch back to Flex Builder and open
the other Flash file which is named
| | 01:29 | CheckBoxSkinsNew.fla, once again right click
on the file or Ctrl+Click on the
| | 01:35 | Mac and select Open with System Editor and
that should open the file in Flash.
| | 01:41 | This version of the file has modified graphical
skins, the graphical skin icons
| | 01:46 | are significantly larger and instead of
using a checkmark to display the
| | 01:51 | selected property. These customized versions
of the skins are now using text
| | 01:56 | objects with a particular font.
| | 01:58 | Notice once again, that each of the objects
on the stage is simply an instance
| | 02:02 | of a library symbol and you'll find the
Library symbols over in the Library
| | 02:06 | panel. Here is how you export these graphical
skins for use in Flex. In Flash,
| | 02:13 | you can export one symbol at a time to a
SWC file. What you really want is a
| | 02:18 | SWC file, that combines all of these symbols
together and makes them all
| | 02:21 | available to Flex at the same time.
| | 02:24 | So, to make that happen, create a new empty
symbol in the Library, go to the
| | 02:30 | Library panel and right click or Ctrl+Click
on the Mac and select New Symbol,
| | 02:36 | you can name the symbol anything you want,
but you should not include any
| | 02:40 | spaces or special character in it. I am going
to name the symbol CheckBoxSkins,
| | 02:46 | I'm using CamelCase syntax rather than spaces,
because of the restrictions on
| | 02:49 | the naming convention. The type must
be set to Movie clip. The goal is
| | 02:54 | essentially to export classes, that can be
read and recognized in Flex and only
| | 02:59 | Movie clips symbols serve that purpose,
click OK to create the symbol. That
| | 03:04 | will then take you into editing mode in
the new skin. In order to combine all
| | 03:08 | of the skinning symbols into one exportable
SWC file, drag one instance of each
| | 03:14 | of the existing symbols into the new symbol.
It doesn't matter where you put
| | 03:18 | the symbol instances. The user is
never going to see this file.
| | 03:22 | Again, the goal here is just to create a
library of each of the symbols that
| | 03:26 | you can easily export. The CheckBoxSkins
symbol, now contains at least one
| | 03:38 | instance of each of the other symbols.
Now, you are ready to export to SWC
| | 03:43 | format. Save your changes, I will select
File, Save from the menu, then go back
| | 03:48 | to the library panel and right click on the
CheckBoxSkins symbol. Select Export
| | 03:54 | SWC File from the menu, you can place the
SWC file anywhere you like, but I am
| | 03:59 | going to navigate to the Chapter03Begin
folder under my Workspace, where I am
| | 04:03 | actually working in Flex right now and
from there I will go down to the
| | 04:07 | FlashContent folder and I will save
the exported component library as
| | 04:12 | CheckBoxSkins.swc, it takes just a few
seconds for the export to happen, I'll
| | 04:20 | go back to Flex Builder and you will see
that the new SWC file has been created in the project.
| | 04:26 | In the next video, I will show you how
to import the graphical skins into a
| | 04:30 | Flex application and connect them up with
the Flex components, in this case the
| | 04:34 | CheckBox component that you want
to reskin and redesign.
| | Collapse this transcript |
| Importing Flash-based skins in Flex Builder| 00:00 | In this video, I am going to describe how
to import a set of graphical skins
| | 00:04 | that have been created in Flash and exported
as a component library in SWC file
| | 00:09 | format. In the previous video I showed you
how to create the SWC file, now if
| | 00:14 | you don't have Flash CS3 Professional or
Flash 8 Professional available. You
| | 00:18 | can still follow through this exercise if
you have the Exercise Files because
| | 00:22 | in the finished folder of the FlashContent
area, you will find a pre-built
| | 00:27 | CheckBoxSkins.swc file that contains everything
you need for this exercise.
| | 00:32 | So if you are following along with the exercises,
the next step is to open up a
| | 00:36 | Flex application. Go to the project in the
Flex Navigator view and go to the
| | 00:40 | source folder and open the file UseCheckBoxSkins.mxml.
This application
| | 00:47 | displays a set of CheckBox components wrapped
inside a panel; each of the four
| | 00:52 | CheckBox components has a different set
of states. There is one CheckBox that
| | 00:56 | has a Selected property of true, one that's
Selected and disabled and then two
| | 01:01 | others that combine the properties in various
ways. This allows us to see the
| | 01:06 | CheckBox presentation in its initial state,
both when the mouse is not anywhere
| | 01:10 | near the check boxes and you can also see
what happens when you manipulate the
| | 01:15 | check boxes using the mouse cursor.
| | 01:18 | Now I will go back to the application; Flex
Builder 3 includes the ability to
| | 01:23 | automatically import these graphical skins
from the component library and make
| | 01:28 | them a part of your application. Here are
the steps, from the Menu, select
| | 01:32 | File, Import, Skin Artwork. You can import
a number of different kinds of files
| | 01:40 | into Flex, you can import a folder of Bitmap
images that are built in PNG or
| | 01:45 | JPEG format for example or you can import
a SWF file that was built in
| | 01:49 | Illustrator or as in this demonstration
a SWC file that was built in Flash.
| | 01:55 | Select SWC or SWF file and then click
the Browse button, navigate to your
| | 02:00 | workspace area; my workspace is under lynda.com
under my C colon root and from
| | 02:07 | there flex3btb, Chapter03Begin, FlashContent
and I will select the component
| | 02:15 | library CheckBoxSkins.swc that I
created in the previous video.
| | 02:19 | Click the Open button and then indicate
where you want to create skin style
| | 02:24 | rules; this process is going to result in
generating some Cascading Style Sheet
| | 02:28 | code. You can indicate where you want to
create the CSS file, the default is to
| | 02:34 | create a CSS file with the same name as the
SWC file but with a .css extension
| | 02:39 | and by default it will be placed in the
source code root of your application.
| | 02:44 | Then indicate which application you want
to bind the CSS file to; in this
| | 02:49 | project they only have one application
UseCheckBoxSkins.mxml, then click the
| | 02:54 | Next button. The next step is to match
up the Symbol Class names
| | 02:58 | from the Flash component library with Style
Selectors and which skin matches
| | 03:04 | each symbol. If we use the default skinning
library that I showed in Flash as
| | 03:08 | the basis of your skinning library, Flex
Builder automatically recognizes the
| | 03:13 | Symbol Class names and matches them up with
the Style Selectors and the Skin Parts.
| | 03:18 | So for example the CheckBox_selectedUpIcon
Symbol Class matches the
| | 03:23 | selectedUpIcon Skin Part and this is an already
recognized style name that's a
| | 03:28 | part of the API or the public interface of
the CheckBox component. Notice that
| | 03:33 | there is no automatic selection for the wrapper
symbol, CheckBoxSkins. The only
| | 03:38 | purpose of that symbol was to be able to
create a single component library that
| | 03:43 | wrapped all of the others. We won't be
using that skin directly in the Flex
| | 03:46 | application; you also don't need to deal
with the special Symbol Class
| | 03:50 | fl.livepreview.LivePreviewParent. Click
Finish and you will see a few things
| | 03:56 | happen, first of all Flex Builder creates
the Cascading Style Sheet file that
| | 04:00 | you requested. In this CheckBoxSkins.css
and it generates the code with a
| | 04:06 | CheckBox selector matching the component
name and then 8 different skinning
| | 04:11 | property values.
| | 04:12 | Each of these property names matches a property
name supported by the CheckBox
| | 04:16 | component. Then there is a call to the embed
compiler directive that goes and
| | 04:21 | gets a class from SWC file and notice that
we are referring to the name of the
| | 04:26 | Symbol Class as it was generated from Flash.
Now go back to the application
| | 04:30 | itself to the MXML file, scroll down towards
the bottom of the file and you
| | 04:36 | will find a style declaration that's been
added to the application below any of
| | 04:40 | the other existing code, 'mx:Style source
=' and then a reference to the CSS
| | 04:45 | file. So that's how the MXML application
and the Cascading Style Sheets file
| | 04:50 | are bound together.
| | 04:51 | There is one other step in the process that's
a little less visible, in order
| | 04:55 | for these graphical skin classes to be
available to the project in the
| | 04:59 | application, the SWC file must be added
to the build path of your project and
| | 05:04 | this is handled automatically by the import
process as well. Go to the Menu and
| | 05:08 | select Project, Properties then navigate
to Flex Build Path and from there to
| | 05:14 | the Library Path tab and you will see that
your CheckBoxSkins.swc file has been
| | 05:19 | added to the Library Path of the project.
That's the third critical part of how this all works.
| | 05:25 | The SWC file is a part of the build path
therefore its classes are available to
| | 05:30 | the Flex compiler. The Cascading Style Sheet
file refers to those class names
| | 05:34 | from the Flash component library and associates
them with their respective
| | 05:39 | styles names and then again the application
binded altogether by incorporating
| | 05:44 | the Cascading Style Sheet file. I will save
the change and run the application
| | 05:50 | and you will see that this version of the
application now uses my new graphical
| | 05:53 | skins. I can click and select and see how
the CheckBox control is going to
| | 05:58 | appear using my new graphic design.
| | 06:01 | Now I will caution you throughout that I
am not a graphic designer, this is the
| | 06:04 | best I am able to come up with and if you
are going to follow this process of
| | 06:08 | incorporating new graphic designs into your
application, I recommend that you
| | 06:12 | get a great graphic designer who is acquainted
with Flash or if you decide to
| | 06:16 | go the route with Illustrator who knows Illustrator
inside and out and you will
| | 06:20 | be able to give your applications
a distinct look and feel that's very
| | 06:24 | different from the default Flex visual presentation.
| | Collapse this transcript |
|
|
4. Integrating Flash and FlexPreparing a Flash Document for Use in Flex| 00:00 | In this chapter of the video series I
am going to describe a variety of
| | 00:04 | approaches to integrating Flash content in
Flex applications. I will start with
| | 00:08 | the simplest of approaches loading a
basic Flash document using a Flex
| | 00:12 | component called SWFLoader. I will then move
on to the next level of complexity
| | 00:17 | embedding a Flash symbol and using it
from within a Flex application and
| | 00:21 | finally I will move on to the most advanced
approach which involves the tool
| | 00:25 | called the Flex Component Kit that you can
install into Flash CS3 and then use
| | 00:30 | to create an export Flex components
that are built in Flash.
| | 00:34 | For all of the exercises in this chapter
I will use a Flex Project that's part
| | 00:38 | of the Exercises Folder. If you are following
along with the exercises you can
| | 00:42 | import the project now from the Menu select
File, Import, Flex Project, click
| | 00:50 | the Browse button next to Archive file, navigate
to the Chapter04 folder under
| | 00:55 | Exercises and select Chapter04BeginProject.zip
and import it. Once the project
| | 01:02 | has been imported open the project in the
Flex Navigator view and start off in
| | 01:07 | the FlashContent folder. This folder has
a file called CarRace.fla; if you have
| | 01:13 | Flash CS3 available you can open this
file now. It's important to know that
| | 01:17 | this is a Flash file that was created in
Flash CS3 using ActionScript 3. If you
| | 01:23 | have an older version of Flash, Flash 8
for example, you won't be able to open it.
| | 01:27 | If you can't work through these exercises
directly, there are finished versions
| | 01:31 | of all of the Flash and exported SWF files
available in the finished folder
| | 01:36 | underneath FlashContent. If you do have Flash
CS3 available, right click on the
| | 01:41 | file or control click with the Mac and
select Open With, System Editor. As I
| | 01:47 | described in a previous video, if you try
to open a Flash file from within Flex
| | 01:51 | Builder simply by double-clicking it,
normally an error will occur. This is a
| | 01:56 | very simple Flash document, it has a set
of layers and each layer has a symbol
| | 02:01 | instance. When its run, this Flash document
shows a very simple car race.
| | 02:05 | I will preview by selecting File, Publish
Preview, Flash and you will see that
| | 02:13 | the cars move across the screen from left
to right until one of the cars hits
| | 02:17 | the finish line and then it stops. The
application has a tiny amount of
| | 02:22 | ActionScript code, I will show you the final
frame in the actions layer and it
| | 02:26 | simply has a stop command to stop the animation
after running through it once.
| | 02:32 | That's it, there is no complex logic in
this Flash document, its simply using
| | 02:37 | the Timeline and motion tweening to move
objects across the screen. In order to
| | 02:42 | use this document in a Flex application in
the most simple way, all you need to
| | 02:46 | do is publish it; before publishing for
this purpose make sure that you have
| | 02:51 | turned off the export of HTML and JavaScript
that's normally associated with a new Flash document.
| | 02:57 | Go to the Menu and select Publish Settings,
then take a look and make sure that
| | 03:02 | the HTML option is turned off. It should
be in this document because I prepared
| | 03:06 | it that way but for your FlashContent you
will probably want to turn off the
| | 03:11 | HTML output. Here's another thing to check
before you publish the document, new
| | 03:17 | documents built in Flash have a default Frame
rate of 12 frames per second. The
| | 03:22 | Flex framework runs at 24 frames per second,
so in order to make sure that the
| | 03:27 | Flash document and the Flex application that
hosts it are compatible with each
| | 03:31 | other, you should typically set your Flash
documents Frame rate to 24 frames
| | 03:36 | per second to match Flex. I will make that
change and then once again I will
| | 03:41 | preview it using Publish Preview, Flash.
| | 03:45 | Notice that this time the car has traveled
across the screen twice as fast,
| | 03:49 | that's how the animation will look when
you play this Flash document from
| | 03:53 | within the Flex application. Now you are
ready to publish, go to the Menu and
| | 03:57 | select File, Publish or press the keyboard
shortcut to do the same thing. Now
| | 04:03 | go back to Flex Builder and you will notice
that you now have a new CarRace.swf
| | 04:08 | file in the FlashContent folder. Take that
CarRace.swf file and copy it to the
| | 04:15 | clipboard, you can right click on the file
or control click with the Mac and
| | 04:19 | select Copy. Now go the source folder and
paste it, this SWF file is now a part
| | 04:27 | of the assets of your Flex application and
in the next video I will show you
| | 04:31 | how to use the SWFLoader component to load
the SWF file and display it as part of the Flex app.
| | Collapse this transcript |
| Displaying a Flash Document with SWFLoader| 00:00 | In this video I am going to describe how
to use a Flash document that's been
| | 00:04 | prepared for use in Flex by setting its Frame
rate to 24 frames per second and
| | 00:09 | then publish to a SWF file. For this demonstration,
I will use an application
| | 00:13 | named LoadSWFFile.mxml. If you are following
along with the exercises you can
| | 00:19 | open this application in Flex Builder; the
beginning application has some very
| | 00:23 | simple code, it has a VBox container with
a white background and padding
| | 00:28 | settings. In order to load a SWF file
into Flex you use a component named
| | 00:33 | SWFLoader, you can declare the SWFLoader
object using MXML code or
| | 00:38 | ActionScript; in this
demonstration I will use MXML.
| | 00:42 | You declare the SWFLoader object and then
you set its source property to the
| | 00:46 | location of the SWF file you want to load,
in this case its CarRace.swf. Save
| | 00:53 | your changes and try running the application,
as you run the application you
| | 00:58 | immediately load the SWF file and start playing
its animation. When you load a
| | 01:03 | Flash document in this fashion you don't
have a huge amount of control over the
| | 01:07 | document; for instance you can't pass data
in or listen for events coming out
| | 01:11 | of the document in this way. But you do have
Timeline control, that is, to say
| | 01:16 | you can call the standard Timeline functions
that are associated with movie
| | 01:20 | clips in the Flash environment.
| | 01:21 | In order to do that you have to get
a reference to the Flash document as a
| | 01:26 | movie clip and then you can call the functions
to control it. Let's see how to
| | 01:30 | do that, I will go back to Flex Builder to
the application Source code and then
| | 01:35 | I will add a Script section and within the
Script section I am going to create
| | 01:39 | a new private function named playAnimation.
The function will return void,
| | 01:45 | within the function I am going to get
a reference to the SWF object, its
| | 01:49 | referenced through a property called content
of the SWFLoader object. I will go
| | 01:54 | down to the SWFLoader declaration and add
id property so I can address it in my
| | 01:58 | code and I will set its id as loader. Then
within the function, I will declare
| | 02:04 | a variable named flashContent and I will
data type it as a class named MovieClip.
| | 02:10 | This is a Flex version of the MovieClip class
that exposes all of the Timeline
| | 02:14 | functions such as goto, gotoAndPlay, stop
and so on. I will initialize the
| | 02:20 | flashContent variable using this syntax,
loader.content as MovieClip. This now
| | 02:29 | gives me a reference to the Flash document
and I can control it. I will call
| | 02:34 | the gotoAndPlay method which you will
see actually shows up in the public
| | 02:38 | interface of the MovieClip class. There
are couple of different options here,
| | 02:42 | you can pass in a frame number or a frame
name, you can also pass in scene
| | 02:46 | names if you use scenes in your Flash
content. I will use the gotoAndPlay
| | 02:51 | function and pass in a value of 1 meaning
goto frame 1 and play the movie.
| | 02:56 | Next I will place the cursor under the
VBox container and add a new Button
| | 02:59 | control. I will set the Buttons label to
Play Movie and set its click event to
| | 03:07 | call my new function playAnimation. I
will save the changes and run the
| | 03:13 | application. Once again as the Flash document
starts up, the Flash movie loads
| | 03:20 | and plays but now I will play the Flex button
labeled Play Movie and you will
| | 03:26 | see that it has the effect of the sending
the play head of the Flash movie back
| | 03:30 | to frame 1 of its Timeline
and playing the movie.
| | 03:33 | So again this is the simplest approach
that you have available for
| | 03:37 | incorporating Flash content into a Flex
application, its worth looking at the
| | 03:41 | documentation for the MovieClip class.
I will place the cursor inside the
| | 03:45 | MovieClip data type and then press Shift
F2 to bring up the documentation and
| | 03:50 | then click on the list of Methods. These
are all the methods that you have
| | 03:53 | available, gotoAndPlay, gotoAndStop,
play, stop and so on.
| | 03:58 | The MovieClip class is actually a member
of the Flex framework, it's a wrapper
| | 04:03 | for the Flash document and while again it
doesn't give you great control over
| | 04:08 | the document, you can't get to the documents
data or call its public methods.
| | 04:12 | You can at least control the animation. Now
in the next couple of videos I will
| | 04:16 | show you a more fine tuned approach where
you expose Flash content as a symbol
| | 04:21 | and then embed it in a Flex application
which allows you to call its methods
| | 04:25 | and get to its data.
| | Collapse this transcript |
| Preparing a Flash Symbol for Use in Flex| 00:00 | In this video I am going to describe the
steps required to prepare a Flash
| | 00:04 | symbol for embedding in a Flex application.
Just as when working with Bitmap
| | 00:08 | images such as PNGs and JPEGs you have the
ability to embed Flash content in a
| | 00:14 | Flex application. This results in being
able to display the content instantly
| | 00:18 | rather than having to wait for it to download
from a web site. The tradeoff for
| | 00:22 | embedding content in this fashion is that
whatever the size of the SWF content
| | 00:27 | is, your Flex application size
will expand by that much.
| | 00:31 | Before you embed the content, you need to
turn it into a Flash symbol and then
| | 00:35 | link that symbol to an ActionScript class.
I am going to start with the
| | 00:39 | existing Flash document in the Chapter04BeginProject,
CarRace.fla. Now if you
| | 00:45 | don't have Flash CS3 available, you will
need to use a finished version of the
| | 00:49 | published SWF file I am about to create
and I have included that in the
| | 00:53 | finished folder under Flash content in a
file named CarRaceAsSymbol.swf but if
| | 00:59 | you do have Flash CS3 and you have access
to the Exercise Files you can follow
| | 01:03 | along. Right or control click on the file
CarRace.fla and select Copy, then
| | 01:10 | right or control click on Flash
content and paste.
| | 01:14 | You will be creating a new version of the
CarRace.fla file and I am going to
| | 01:19 | name the new version of the file CarRaceAsSymbol.fla.
Next open the new file in
| | 01:27 | the Flash authoring environment, right click
on the file or a control click on
| | 01:31 | the Mac and select Open With, System Editor
and that should open the file in
| | 01:37 | Flash. Now your next step is to create a
new movie clip symbol. The movie clip
| | 01:42 | symbol must be linked to an ActionScript
class; you don't have to create an
| | 01:46 | explicit ActionScript class, Flash will do
that for you if you follow the right
| | 01:51 | steps. Go to the Library panel and click
the plus button at the bottom or you
| | 01:57 | can also right or control click and select
New Symbol and create a new movie
| | 02:01 | clip symbol. In the Create New Symbol dialog,
set the Name of the new symbol to
| | 02:07 | mcCarRace; make sure the Type is set to
Movie clip, that's the only kind of
| | 02:12 | symbol that you can embed in a Flex application.
| | 02:15 | Then click the Advanced button and that
will open up all of the ActionScript
| | 02:18 | properties. Under Linkage, click Export for
ActionScript. You will be creating
| | 02:25 | an ActionScript class named for the symbol
mcCarRace and it will be based on
| | 02:29 | the Flash.display.MovieClip class. Now as
I mentioned you don't actually have
| | 02:35 | to create an explicit ActionScript class
file here. So just click Okay and you
| | 02:40 | should see this warning, indicating that
the class couldn't be found and so one
| | 02:44 | will be automatically generated for you in
the SWF file when it's published or
| | 02:48 | exported. If you see this warning, click
Okay and now you are editing your new
| | 02:53 | symbol. Now go back to the main document
Timeline, click the Scene 1 link above
| | 02:59 | the editing area and then select all of
the frames in all of the layers as
| | 03:03 | follows.
| | 03:05 | Click in the first frame of the first layer,
then hold down the Shift key and
| | 03:10 | click into the last frame of the last
layer. Right click anywhere in the
| | 03:14 | selected area or a control click on the Mac
and select Copy Frames. Go back to
| | 03:20 | editing the symbol, go to the Library panel
and right click or control click on
| | 03:24 | the Mac on the symbol you created and select
Edit. Go to the first frame of the
| | 03:31 | first layer, right or control click and select
Paste Frames and that will take
| | 03:37 | all of the content that was in the main
document and copy it over into the
| | 03:41 | symbol. It's very important in order for
this symbol to be compatible with Flex
| | 03:47 | for the top-left corner of all of the visual
content to be aligned with the
| | 03:51 | registration point in the center of the symbol.
| | 03:55 | Essentially that means that you want the
X and Y properties of the top objects
| | 03:58 | to be set at 0. To accomplish this easily
click into the first frame in the
| | 04:04 | first layer that contains visual content,
greencar. Hold down the Shift key and
| | 04:09 | click into the last layer, fist frame then
move the cursor down into the stage
| | 04:13 | area and click on any of the selected symbols.
Go to the properties area and
| | 04:19 | set the X and Y properties to values of
0 each. I am going to expand to full
| | 04:23 | screen so we can see the result. Notice that
the top-left corner of the top car
| | 04:28 | is on the registration point, that's exactly
what you want. Now that does not
| | 04:32 | affect what happens in the final key frames.
| | 04:35 | So the next step is as follows, go to the
course layer and lock it. Click the
| | 04:40 | link under the Lock icon and that will mean
that no matter what you do next you
| | 04:44 | won't be moving the finish line from its
current position which is correct.
| | 04:48 | Then go to the last frame for all of the
layers containing visual objects;
| | 04:52 | click into the last frame in the first visual
layer, Shift and click into the
| | 04:57 | last frame of the last visual layer and
then click on one of the car objects
| | 05:02 | and drag them into place. This will take
a little bit of eyeballing because you
| | 05:06 | want the images to appear so that the yellowcar
is just going over the finish
| | 05:11 | line at the end. With those objects selected
take a look at the Properties
| | 05:15 | view, I have been pressing the F4 function
key to show and hide all of the
| | 05:19 | panels.
| | 05:20 | Now with those cars still selected set the
Y value at 0 but leave the X value
| | 05:26 | alone; that will mean that the cars are
still in the same location vertically
| | 05:30 | but you have placed them horizontally where
you want them. To test the symbol
| | 05:34 | go back to the main document Timeline,
click on the Scene 1 link above the
| | 05:38 | editing area, select all layers below the
actions layers. Click into the first
| | 05:42 | layer, hold down the Shift key and click
the last layer, then click the trash
| | 05:46 | can icon at the bottom to delete all those
layers. Double-click the actions
| | 05:51 | layer name and change it to carrace because
now it's going to be the only layer
| | 05:56 | displaying the instance of this symbol. Then
click into the first frame of the
| | 05:59 | remaining layer, go to the Library panel,
drag in the instance of the symbol
| | 06:05 | and sets its X and Y properties at 0 each.
| | 06:09 | Save your changes and then preview your
document by selecting File, Publish
| | 06:15 | Preview, Flash and the carrace should play
correctly. Now you may notice that
| | 06:21 | at the end of the animation the content
went away; close the preview, go back
| | 06:26 | to the one remaining layer, click into the
second frame, Shift and click into
| | 06:31 | the last frame. Then right click and Remove
Frames and then try previewing your
| | 06:37 | document again. Select File, Publish Preview,
Flash and this time only the
| | 06:46 | component is doing the animation and you
should see the cars stop correctly.
| | 06:52 | So here are the critical steps that I followed,
I selected all frames and all
| | 06:56 | layers in the main document and then pasted
all of those frames and layers into
| | 07:00 | the movie clip symbol. I made sure that
the top-left corner of the visual
| | 07:04 | content of the symbol was at the main
registration point that is X and Y
| | 07:08 | properties of 0 and 0 and then when I created
this symbol, I set up the Linkage
| | 07:14 | properties so that I had a named class I
could refer to in my Flex application.
| | 07:19 | I didn't have to create an actual explicit
ActionScript class; that was done
| | 07:23 | for me by the Flash authoring environment.
| | 07:25 | The final step is to publish your document,
from the Menu, select File,
| | 07:31 | Publish. Then go back to Flex Builder
and you should find a file
| | 07:36 | CarRaceAsSymbol.swf has been created in
your FlashContent folder. Right or
| | 07:41 | control click on the SWF file and copy it,
go to the source folder and paste it
| | 07:48 | and now your SWF file is ready for embedding
in the Flex application and I will
| | 07:52 | show you how to do that in the next video.
| | Collapse this transcript |
| Embedding Flash symbols in Flex| 00:00 | In this video, I'm going to describe how
to embed a symbol built in Flash in a
| | 00:04 | Flex application. Before I start with the
demonstration, I need to describe one
| | 00:09 | serious limitation to this approach.
| | 00:11 | When you embed a symbol directly from
a SWF file, you loose access to the
| | 00:16 | ActionScript code that's a part of that
symbol, that is the ActionScript code
| | 00:20 | in the symbol is essentially ignored.
So this approach is best suited for
| | 00:24 | Flashed animations that loop infinitely,
where you don't need to execute any
| | 00:28 | ActionScript code that's inside the symbol.
| | 00:31 | You will however still be able to execute
movie clip functions using the movie
| | 00:36 | clip wrapper class that I demonstrated
in an earlier video.
| | 00:39 | For this demonstration, I'll use the EmbedFlashSymbol.mxml
application file
| | 00:44 | from the Chapter04Begin project. If you are
following along with the exercises,
| | 00:48 | you can open that application file now.
| | 00:51 | The application file is the same as I created
in a previous video. It uses the
| | 00:55 | SWF Loader component to load CarRace.swf
at run-time. I'll run the application
| | 01:01 | and show the current functionality. As the
application starts up it loads the
| | 01:06 | SWF file and plays its animation. When
you get to the end of the Flash
| | 01:10 | document's time-line, the animation stops
due to the Stop command that's in the
| | 01:15 | SWF file. You can click the Play Movie
command to restart the animation.
| | 01:21 | Now, let's go back to the application. In
the previous video, I created this
| | 01:25 | file, CarRaceAsSymbol.swf where the content
of the animation was in a symbol
| | 01:31 | instead of the main time-line of the document
and I made sure that I provided
| | 01:34 | Linkage Properties for this symbol so I could
refer to this symbol from within
| | 01:39 | my Flex application.
| | 01:41 | As I mentioned earlier, if you are following
along with the exercises but you
| | 01:44 | don't have access to Flash CS3, you can use
this version of the SWF file that's
| | 01:49 | in the Finished folder under FlashContent,
CarRaceAsSymbol.swf, and you would
| | 01:54 | just want to copy that SWF file to your source
folder before you go on with the
| | 01:58 | rest of the code. Let's go to the code now.
| | 02:01 | I return to the application file and
place the cursor inside the script
| | 02:05 | section. To embed a symbol, you use the
Embed metadata tag. As with all
| | 02:11 | metadata tags, it starts with the bracket
character. Then you put in the word
| | 02:15 | Embed and an opening parenthesis. You are
going to pass in two attributes. The
| | 02:20 | first is named 'Source' and it's going to
point to the SWF file that contains
| | 02:25 | the symbol you want to embed. I am going
to be using CarRaceAsSymbol.swf, then
| | 02:33 | put in a comma and add a symbol attribute.
The value for the symbol attribute
| | 02:38 | is the linkage ID of the Flash symbol. It's
not necessarily the symbol name as
| | 02:44 | it exists in the library in the Flash document,
instead, it's that class name
| | 02:48 | that was created when you
set Linkage Properties.
| | 02:52 | In my symbol, I used mc CarRace as both the
symbol name and as the linkage ID.
| | 02:57 | By using the same value for both, it's
one last thing to remember.
| | 03:03 | The next step is to also have the Bindable
tag. This is going to allow you to
| | 03:07 | easily pass the SWF file to the SWF Loader
through a bindable expression.
| | 03:12 | Finally, create a private variable and
name it flashSymbol. The name of the
| | 03:18 | variable can be anything, I am just naming
it flashSymbol so I can remember
| | 03:21 | what it is. And then data type it as a Class.
| | 03:25 | That's all the code you need to embed the
SWF file in the application. The
| | 03:29 | first line embeds it, the second makes
it bindable and the third declares a
| | 03:34 | variable, that's associated with the symbol
so we can refer to it in our
| | 03:38 | ActionScript and binding expressions.
| | 03:41 | Now, go down to the SWF Loader tag at the
bottom of the application. In the old
| | 03:46 | version, the source tag should to be pointed
to the full SWF file and loaded at
| | 03:50 | run-time. Replace that reference to a
binding expression, that refers to
| | 03:55 | flashSymbol, that is the name of the variable
that's associated with the symbol.
| | 04:00 | Save your changes and run the application.
You'll see that the application
| | 04:04 | starts up, and once again it plays the animation.
But now, instead of stopping
| | 04:10 | at the end of the animation what it hits
the last frame, it just continues, and
| | 04:16 | again, that's because when you embed content
in this fashion, ActionsScript
| | 04:20 | code in the time-line is ignored.
| | 04:23 | You can still control the movie's time-line
from outside. Every time I click
| | 04:28 | the Play Movie button, it goes back to the
first frame and continues playing,
| | 04:32 | and you could also add other buttons and
execute other time-line functions by
| | 04:37 | referring to the SWF Loader's content property
as a movie clip and then calling
| | 04:41 | any of the movie clip functions that I
demonstrated in an earlier video.
| | 04:45 | So this a nice approach again for Flash
animation that simply loops and where
| | 04:50 | all you need to do is control its time-line,
but for more sophisticated
| | 04:54 | integration of Flash with Flex, you are
going to want to create full Flex
| | 04:58 | components in the Flash environment, and
that's what I'm going to show you how
| | 05:02 | to do in the next few videos.
| | Collapse this transcript |
| Installing the Flex Component Kit in Flash CS3| 00:00 | In this next set of videos, I'm going to
describe how to take a Flash symbol
| | 00:04 | and export it as a Flex component from
the Flash authoring environment.
| | 00:09 | In order to do this, you need a little
bit of extra software that you can
| | 00:12 | download for free from the Adobe website.
The Flex Component Kit was available
| | 00:17 | for sometime at Adobe labs as a public data.
There are notes on left side that
| | 00:22 | indicate that the Flex Component Kit is a
part of the SDK that was delivered as
| | 00:25 | part of Flex Builder. However, the kit didn't
make it into the final delivery.
| | 00:30 | You can however get it from the Adobe
website if you know where to look.
| | 00:33 | I have included a text file in the project
and if you are following along with
| | 00:38 | the exercises, you can open it and for those
of you who don't have access to
| | 00:41 | the exercise files, I'll show it to you here.
| | 00:44 | Navigate to this web page
| | 00:45 | www.adobe.com/cfusion/entitlement/index.cfm?e=flex%5Fskins.
| | 00:58 | That will take you to a log-in screen where
you'll need to login with an Adobe ID. If you don't
| | 01:04 | have an Adobe ID, you can sign-up for
one for free. If you do have one, go
| | 01:08 | ahead and log in and you'll go to this page.
| | 01:11 | The Flex Skin Design Extensions and Flex
Component Kit for Flash CS3 download
| | 01:16 | page has links to a number of valuable tools.
In addition to the Flex Component
| | 01:21 | Kit for Flash that I'll be demonstrating
here, there are also links to skinning
| | 01:25 | libraries for FIREWORKS, FLASH, ILLUSTRATOR
and PHOTOSHO of particular interest
| | 01:31 | for graphic designers, there is a Skin Design
Extension for Illustrator that
| | 01:35 | you can download. I'm going to focus here,
on the use of the Flex Component Kit.
| | 01:40 | The link for that is at the bottom of the
page at least as of this viewing.
| | 01:43 | Click the link and download the kit which
will come to you as a ZIP file.
| | 01:47 | Now, I have already downloaded the kit.
As I mentioned, it comes to you as a
| | 01:50 | ZIP file and this ZIP file contains two files.
A readme.txt file that contains
| | 01:56 | some instructions and an MXP file which
is an Adobe Extension. The purpose of
| | 02:01 | an extension file is to add capabilities
to an Adobe application such as Flash
| | 02:07 | or Dreamweaver, extracts the
contents of the ZIP file.
| | 02:10 | For example, I simply dragged the MXP file
to my desktop where it's already
| | 02:15 | available as a non-zipped file. Then, start
up the Adobe Extension Manager. If
| | 02:20 | you are working on Windows Vista, you can
get to the Extension Manager by going
| | 02:24 | into the Start Menu and then start typing
Extension and look for Adobe
| | 02:29 | Extension Manager CS3.
| | 02:31 | If you are working on Windows XP or the Mac,
navigate to the application as you
| | 02:35 | do on those operating systems. And either
way open up the application. Before
| | 02:40 | you continue, make sure you've closed down
Flash CS3. You always want to close
| | 02:44 | down any application that you are about
to upgrade with an extension. Then go
| | 02:48 | to the Adobe Extension Manager Menu and
select File - Install Extension.
| | 02:54 | Navigate to the location where you
abstracted the file, select
| | 02:58 | FlexComponentKit.mxp and click Install. Review
the license agreement and if you
| | 03:04 | agree with it, except it and you'll see
very quickly a conformation that says
| | 03:08 | that the kit has been successfully installed.
| | 03:11 | Click OK, close the Extension Manager
and then restart Flash CS3.
| | 03:20 | Open up any Flash document. For this test,
you can create a brand new Flash
| | 03:24 | document, then go to the Commands Menu and
you should see these new choices,
| | 03:30 | convert symbol to Flex Component and
convert symbol to Flex Container.
| | 03:35 | If you see these menu selections, then
you are ready for the next steps.
| | 03:39 | In the next videos, I'll show you how to
prepare a symbol for use a as Flex
| | 03:42 | component and then how to export it as a
component library, and then finally
| | 03:47 | how to use it in your Flex application.
| | Collapse this transcript |
| Creating and exporting a Flex component in Flash| 00:00 | In the previous video, I described how
to download and install the Flex
| | 00:03 | Component Kit into Flash CS3, to allow you
to take Flash symbols and turn them
| | 00:09 | into Flex components.
| | 00:10 | In this video I'll describe the steps you
follow to take a Flash document with
| | 00:14 | symbols and export these components as a
Component Library that's compatible
| | 00:18 | with Flex 3.
| | 00:19 | I'll be starting in Flex Builder using
the Chapter04Begin project, and I'm
| | 00:24 | going to make a copy of the
file CarRaceAsSymbol.fla.
| | 00:28 | Now, for any reason you don't have this file,
you can get a copy of it from the
| | 00:31 | finished folder under FlashContent if
you are following along with the
| | 00:34 | exercises. I am going to select the file
CarRaceAsSymbol.fla, right-click or
| | 00:40 | Ctrl+Click with the Mac and select Copy,
then go to the Flash Content folder
| | 00:46 | and Paste.
| | 00:46 | You are prompted to assign the file a new
name. I'm going to name the new file
| | 00:52 | CarRaceAsComponent.fla. Then I'll select
the file in the Flex Navigator view,
| | 01:00 | right-click or Ctrl+Click on the Mac and
select Open With - System Editor.
| | 01:06 | Now I have my component open in Flash. Let's
take a look at the symbol that I
| | 01:09 | created in a previous video mcCarRace. This
is the symbol that encapsulates the
| | 01:14 | car race functionality including animations
and ActionScript code.
| | 01:19 | Right now, the current linkage properties,
set the class name as mcCarRace
| | 01:22 | which is what I selected previously
and the base class as
| | 01:26 | flash.display.MovieClip. The MovieClip
class is compatible with the Flash
| | 01:31 | environment. It represents a movie clip object.
In the Flex environment though,
| | 01:35 | you need a more complex component in order
to be able to easily add objects to
| | 01:40 | the Flex framework, that is Add Components
to Containers and so on.
| | 01:44 | So if you have already installed the Flex
Component Kit, this is a very simple
| | 01:48 | thing to do. I'll cancel out of the Linkage
Properties, go to the Flash Menu
| | 01:53 | and select Commands - Convert Symbol to Flex
Component. It takes just a moment
| | 01:59 | for the conversion to happen. The Output
view appears and shows you some
| | 02:03 | information about the steps that were taken
in the background. Close the Output
| | 02:06 | View and go back to the Library panel
and once again look at the Linkage Properties.
| | 02:12 | Notice, this time the base class is
mx.flash.UIMovieClip. The UIMovieClip which
| | 02:18 | is now the base or the super class for my
component is compatible with the Flex
| | 02:22 | framework, and any class that's derived from
UIMovieClip can be easily added to
| | 02:27 | a containership architecture in Flex.
| | 02:30 | Now, let's take one more step before I export
this for use in Flex. You can set
| | 02:35 | the class name as anything you want.
As with all good classes that you
| | 02:39 | typically use in the Flex environment,
it's a good idea to assign a package
| | 02:43 | name, that is a prefix to the class name
and following good object-oriented
| | 02:47 | conventions that we tend to follow in Flex
to uppercase the name of the class.
| | 02:52 | So I am going to change the name of the
class as it will be known in Flex to
| | 02:56 | flashcomps.FlashCarRace. I still haven't
created an explicit ActionScript
| | 03:02 | class, instead, when I save these linkage
properties, I'll be prompted and told
| | 03:07 | that a definition for the class couldn't
be found and so one will be
| | 03:10 | automatically generated. Click OK to save
your changes. Now, you are ready to export.
| | 03:16 | You can export to a component library in
a couple of ways. You can either go to
| | 03:20 | the Library panel and right or Ctrl+Click
on the symbol that you want to
| | 03:24 | export, and then select Export SWF file or
in a slightly simpler step, you can
| | 03:29 | simply publish the Flash document. I'll
select File, Publish and that's going
| | 03:36 | to generate both a SWF file and a SWC file.
| | 03:39 | The SWF file won't be used in this example,
instead, when I go over in to Flex
| | 03:44 | and integrate my component into the Flex
application, I'll be using the SWC file.
| | 03:49 | Now, I'll go over to Flex Builder and
take a look at the results. In the
| | 03:53 | FlashContent folder where I cerated my CarRaceAsComponent.fla
file. Here's the SWC file and here's the SWF file.
| | 04:01 | Now in the next video I'll show you how to
incorporate this SWC file into your
| | 04:05 | Flex application and how to instantiate
your new Flex component.
| | Collapse this transcript |
| Using Flash component libraries in Flex| 00:00 | In previous videos, I described how to download
and install the Flex Component
| | 00:04 | Kit into Flash CS3, and then how to use
the kit's capabilities to prepare and
| | 00:09 | export a Flash symbol as a Flex component.
The result was a SWC file, a
| | 00:14 | component library that you can then incorporate
into a Flex application.
| | 00:19 | In this video I'll show you how to incorporate
the SWC file and its symbols or
| | 00:22 | components into a Flex application. For
this demonstration, I'll use the
| | 00:27 | application file UseFlashSWC.mxml. If
you are following along with the
| | 00:32 | exercises, you can open up this MXML
file from the project now.
| | 00:36 | The application in it's beginning state has
a layout property of absolute and a
| | 00:40 | style name of plain. By setting the style
name to plain, the result of the
| | 00:44 | plain style name is to give the application
a white background, to match the
| | 00:48 | white backgrounds of the images in the Flash
component of using. There is also
| | 00:52 | a simple label control with a text property
of Flash CarRace and with its X and
| | 00:57 | Y properties set to 20 pixels each, and
the application, its beginning state
| | 01:01 | simply displays that label.
| | 01:04 | Here are the steps to incorporating the
Flex component from Flash. First, you
| | 01:08 | need to add this SWC file to your build or
library path. There are two ways to
| | 01:12 | do that. One way is to copy this SWC file
into the project's Libs folder. When
| | 01:18 | you build a project in Flex Builder 3, the
Libs folder is created automatically
| | 01:22 | and it's a part of the class or build path
automatically. So any SWC files that
| | 01:27 | you drop into that location will automatically
be available to the compiler.
| | 01:31 | On the other hand, if you can do it in that
way, any changes that you make in
| | 01:35 | Flash won't be published to the Libs folder
unless you configured Flash that
| | 01:38 | way. So another approach is to explicitly
add the SWC file to the build path of
| | 01:44 | the project. That's the approach I'll take.
| | 01:47 | I'll go to the Flex Builder Menu and select
the Project, Properties. Then I'll
| | 01:51 | select the Flex Build Path category, from
there click on the Library Path tab
| | 01:57 | and then click Add SWC.
| | 01:59 | In the Add SWC dialog click the Browse button
and navigate to the FlashContent
| | 02:04 | folder under your Chapter04Begin project,
My browsed window already came up to
| | 02:09 | that folder. Then I'll select CarRaceAsComponent.swc,
open it and click OK.
| | 02:15 | Then click OK to save your new project properties.
Every time you add a new SWC
| | 02:20 | file or the SWC file gets updated, the
project will be rebuilt and any
| | 02:24 | components in the SWC file will automatically
be available to your Flex application.
| | 02:29 | The next step is to add an instance of the
component. As with all MXML tags,
| | 02:35 | you do need to add a custom name space prefix,
mapped to the package in which
| | 02:39 | your component is stored. Flex Builder
3 however automates this process for
| | 02:44 | you. So, I'm going to place the cursor after
the mx label tag and before the
| | 02:48 | end application tag then type in a less
than (<) character and then start
| | 02:53 | typing the name of the component as it's
known in the Linkage Properties in Flash.
| | 02:58 | I named this class FlashCarRace. Notice,
that Flex Builder is already aware of
| | 03:04 | the component name and its package flashcomps
which I created in the Linkage
| | 03:08 | Properties in Flash. I'll select the
class and take a look up at the
| | 03:12 | application tag. Notice that Flex Builder
has automatically added a name space
| | 03:17 | prefix, matching the package name of the
component as I named it in Flash.
| | 03:23 | I'll add an ID property and simply call it
Race and then I'll also add x and y
| | 03:28 | properties. This is now a complete visual
component and you can place it on the
| | 03:32 | screen relative to the top left corner of
any absolute layout container; such
| | 03:38 | as the application with its layout is set
to Absolute or a Canvas perhaps. I'll
| | 03:42 | set the values to x of 100 and y of 100.
| | 03:48 | I'll save the changes and run the application
and there is my Flash component
| | 03:54 | running in a Flex application. So, now
I would like to show you a couple of
| | 03:58 | other interesting things you are able
to do with this component.
| | 04:01 | Just as I showed in an earlier video that
incorporated SWF files and embedded
| | 04:05 | symbols, you are able to execute simple
time-line commands with these
| | 04:09 | components. Each component that's extended
from the UIMovieClip class is this
| | 04:14 | one now is supports methods such as Play,
Stop, Go to and Play, Go to and Stop
| | 04:20 | and other functions that you might be
used to with the Flash time-line.
| | 04:24 | I'm going to place the cursor above the
label and add an Application Control
| | 04:28 | Bar with it's doc property set to True, and
then within the Application Control
| | 04:33 | Bar I'll add a button, set its label to
Replay and its click event handler to
| | 04:41 | call this function race.gotoAndPlay and
notice that the gotoAndPlay and
| | 04:46 | gotoAndStop methods are already available.
They are a part of the UIMovieClip
| | 04:51 | component and its descendants,
and I'll pass in frame one.
| | 04:58 | Add another button with the label of Stop.
Add a click event listener that
| | 05:05 | calls the Stop method and then one more button
this one with the label of Play
| | 05:12 | and this one we'll call race.play. I'll
save the changes and run the application.
| | 05:20 | I'll let the movie play for the first time
when it loads then I'll click the
| | 05:23 | Replay button, the Stop button to pause
it and the Play button to continue,
| | 05:29 | So, you see that when you expose a Flash
symbol as a Flex component, you
| | 05:34 | automatically get all the time-line behavior
that previously I had to add
| | 05:38 | additional code to execute.
| | 05:40 | So, that's a look at how to take a Flash
symbol and use it in a Flex application.
| | 05:45 | Now, there is one more interesting step
in this process. Once you've hooked
| | 05:49 | this up as a Flex component, you have the
ability to go back into Flash and
| | 05:53 | extend the capability to the component
adding whatever component style
| | 05:57 | ActionScript code you want including custom
properties, custom methods and
| | 06:02 | custom events.
| | 06:04 | I'll show you how to do that in the next video.
| | Collapse this transcript |
| Extending a Flash component with a custom class| 00:00 | In this video I am going to describe how
to extend the capabilities of Flash
| | 00:04 | symbol that you have exposed as a Flex
component and integrated into your Flex
| | 00:08 | application. Here are the steps I am going
to follow. First all, create a
| | 00:12 | custom ActionScript class. This custom
ActionScript class will extend the
| | 00:17 | UIMovieClip class that's currently used as
the base for my Flash symbol. Then I
| | 00:21 | go back over to Flash and I will re-link
my movie clip symbol to the new custom
| | 00:26 | ActionScript class. Then I will be able
to add custom functionality to that
| | 00:31 | class and I will be able then to call
that functionality in Flex.
| | 00:35 | The first step is to create the custom
ActionScript class. You could do this
| | 00:38 | step in either Flash or in Flex. Since Flex
Builder has better code generation
| | 00:43 | capabilities though, I will start there.
From the menu select File, New,
| | 00:50 | ActionScript Class. Set the package as
flashcomps and the name of the custom
| | 00:57 | ActionScript class as carRaceClass. You
can name the class anything you want
| | 01:02 | and you can put it in any package. Initially
this class is going to be created
| | 01:06 | in the source root of the Flex project.
But after it has been created I am
| | 01:10 | going to move it over to the folder
that contains my Flash content.
| | 01:14 | Click the Browse button to select a super
class and then start typing the name
| | 01:18 | of the UIMovieClip class until you find it
and then click OK and that fills in
| | 01:24 | the super class correctly, Click Finish and
that's your beginning ActionScript
| | 01:30 | class. Now close the class in Flex Builder,
go over to the Flex Navigator view
| | 01:37 | and drag to flashcomps folder that was
created in the source root into the
| | 01:41 | FlashContent folder, so that it becomes
unavailable to the Flash content. Now
| | 01:47 | go to the flashcomps folder within
the FlashContent folder, go to
| | 01:51 | CarRaceClass.as and select Open With,
System Editor and this should result in
| | 01:58 | opening the class in Flash.
| | 02:00 | Now you are ready to start adding custom
functionality to your Flex component.
| | 02:04 | I am going to create a new function which
is simply named go. It will be
| | 02:09 | function that calls the simple gotoAndPlay
function. So, its not going to do a
| | 02:13 | whole bunch, but you will see that you are
able to call it from Flex and you
| | 02:17 | will be positioned to be able to add additional
custom functionality later on.
| | 02:22 | I will create the function, I will make
sure it's public so I can call it from
| | 02:25 | the Flex application and I will name it
simply go and return void and within
| | 02:33 | the go function I call gotoAndPlay and pass
in a value of 1 for frame1 and I
| | 02:41 | will save the changes to the ActionScript class.
| | 02:45 | Now go back to the Flash file, CarRaceAsComponent.fla,
go to the library symbol
| | 02:51 | mcCarRace, right click on it or Ctrl+Click
on the Mac and select Linkage. The
| | 02:57 | name of the linked class as its known in
Flex is flashcomps.flashCarRace and
| | 03:03 | the base class is UIMovieClip.
Change the base class to
| | 03:07 | flashcomps.CarRaceClass. Make sure you
exactly match the case of both the
| | 03:13 | package and the class name, as you declared
it earlier. If you want to make
| | 03:17 | sure you typed it correctly, you can click
the Edit button next to the base
| | 03:21 | class name and in the background you should
see the Flash ActionScript editor
| | 03:25 | open and you should see the class. Click
OK to save your changes, then go back
| | 03:31 | to the Flash file CarRaceAsComponent.fla,
select File, Publish and this will
| | 03:38 | republish the SWF file and make the new class
generation available to your Flex
| | 03:43 | application. Go back to Flex Builder and
let's make a change in the code that's
| | 03:48 | calling the component. I am using the file
UseFlashSWC.mxml which I modified in
| | 03:54 | the previous video to instantiate
the CarRace object.
| | 03:59 | Go to the button labeled Replay, remove
the call to the gotoAndPlay function
| | 04:04 | and with the cursor right after the period
press Ctrl+Space and start typing go
| | 04:09 | and you should see the component's new custom
method go available. Select it,
| | 04:15 | save your changes and run the application.
Wait for the initial animation to
| | 04:22 | complete and then click the Replay button
and you should see that you are still
| | 04:27 | successfully restarting the animation.
Right now all I am doing is adding
| | 04:31 | additional layers of code, but the goal
here is to be able to add real custom functionality.
| | 04:37 | So, in the next video also you have to
share custom information from the
| | 04:41 | Flash-based Symbol component to the Flex
application by dispatching custom events.
| | Collapse this transcript |
| Dispatching and handling Flash Component events| 00:00 | In this video I'm going to describe how to
dispatch custom events to share data
| | 00:05 | from Flash symbols that you've exposed
as Flex components, and then how to
| | 00:09 | listen for and handle those events
in a Flex application.
| | 00:13 | The syntax will be exactly what you already
know how to do in Flex and because
| | 00:17 | both environments use ActionScript 3 as
their programming language, there
| | 00:21 | really aren't any major differences. The
goal however is to show you that this
| | 00:25 | a good way of integrating the components
with the Flex application and working
| | 00:30 | back and forth between the two environments.
| | 00:32 | For this demonstration, I'll continue to
use the files CarRaceAsComponent.fla
| | 00:38 | which contains the visual symbol and animation,
and CarRaceClass.as which is
| | 00:43 | the custom ActionScript class that
I created in the previous video.
| | 00:47 | If you are following along with the exercises,
you should first make sure that
| | 00:50 | you have gone through those previous exercises
so you have these files in this state.
| | 00:55 | Let's start off in CarRaceClass.as. As in
components that you build in the Flex
| | 01:00 | environment, if you are going to dispatch
custom events, you should declare
| | 01:04 | ahead of time that those events are going
to happen and you should indicate
| | 01:08 | what kind of event object will be dispatched.
You do this as in Flex with the
| | 01:14 | event metadata tag.
| | 01:15 | Now, because you are working in ActionScript
rather than MXML, you don't wrap
| | 01:20 | this in an mx metadata tag. You simply start
with the event metadata tag above
| | 01:25 | the class declaration.
| | 01:26 | I'm going to be declaring two different
events; one named Start and the other
| | 01:30 | named Finish and I'll dispatch each event
when the race begins and when it ends.
| | 01:36 | Here is the first declaration. The event
metadata tag will have a name of start
| | 01:44 | and a type of the standard Flash event
object, flash.events.Event.
| | 01:51 | Now if you are working in the Flash ActionScript
Editor as I am here, you have
| | 01:55 | to add your import statement explicitly,
unlike in Flex Builder it won't be
| | 01:59 | added for you. So I'll place the cursor above
the event declaration and add an
| | 02:04 | import statement for flash.events.Event.
| | 02:09 | Now I'm also going to add an event declaration
for the finish event, and this
| | 02:14 | one is going to use a class that's already
in the framework named Text Event.
| | 02:19 | The Text Event class is a standard event
class that you can use to dispatch an
| | 02:24 | event object containing a simple string value.
I'll declare the event with the
| | 02:28 | metadata tag, I'll give it a name of
finish, and I'll set it's type to
| | 02:34 | flash.events.TextEvent. Be careful to pay
attention to the case sensitivity
| | 02:41 | with an upper case T and an upper case
E and then as before, I'll add the
| | 02:46 | appropriate import statement, this
time for flash.events.TextEvent.
| | 02:52 | Now, whenever I explicitly restart the race,
I'm going to dispatch the start
| | 02:56 | event from this class. Move the cursor
into the go method right after the
| | 03:01 | gotoAndPlay call and add a new line of code
and call the dispatch Event method
| | 03:07 | and pass in a new Event object and in the
call to the event class's constructor
| | 03:12 | method pass in the name of the event
you are dispatching, start.
| | 03:17 | Save your changes, then go back to the Flash
file and re-publish the document.
| | 03:25 | Switch back to Flex Builder and if you
don't already have it open, open the
| | 03:29 | application file use FlashSWC.mxml if
you are following along with the exercises.
| | 03:36 | Now, we want to listen for the event
that might occur. Go to the Flash
| | 03:40 | CarRaceComponent, place the cursor after
the y property setting and press the
| | 03:45 | Spacebar. Start typing st and because you
declare to the start event in the
| | 03:52 | metadata tag you should see it in the list.
| | 03:55 | Select the start tag and type in a call
to the trace function and pass in a
| | 04:00 | simple string of Race started. Save your
change, restore your ActionScript
| | 04:08 | Editor size so that you can see the Console
view at the bottom, and then run
| | 04:13 | the Flex application in Debug mode.
| | 04:18 | Resize the Browser, so you can see the Flex
Builder Console in the background
| | 04:23 | and then click the application's Replay
button and in the Console you should
| | 04:28 | see the trace output Race started. So now
you can see that you can actually
| | 04:32 | listen for and handle events.
| | 04:35 | Let's go one step further though. Let's
go back to the application, first
| | 04:39 | closing the Browser so you terminate
the debugging session.
| | 04:44 | We'll go back to the Flash document, and
this time, I'm going to dispatch an
| | 04:47 | event from code that's in the time-line.
Now, for those developers who work a
| | 04:52 | lot in Flash, you might be thinking, why
would you put code in the time-line,
| | 04:56 | isn't it better to put it in the ActionScript
class itself? And my answer is,
| | 05:00 | absolutely it is, but some developers
do prefer to put the code in the
| | 05:04 | time-line and what I show you that it
is technically possible to dispatch
| | 05:08 | events from any ActionScript code
anywhere in the symbol.
| | 05:12 | Go to the symbols actions layer, now if
you don't see all these layers, make
| | 05:16 | sure that you are in the mcCarRace symbol.
Notice down here where I am pointing
| | 05:20 | the cursor that I am editing the symbol and
not the main document time-line. In
| | 05:25 | the actions layer, locate the final frame,
right or Ctrl+Click on the frame and
| | 05:30 | select Actions. Currently the code in this
frame only executes a stop method.
| | 05:36 | We now want to also dispatch an event that
tells the application not only that
| | 05:41 | the Race is finished but who won. Move
the call to the stop function down a
| | 05:46 | couple of lines and then add an import statement
for flash.events.TextEvent.
| | 05:54 | Then move the cursor after the call to the
stop function and you are going to
| | 05:58 | execute the following code.
| | 06:00 | First create an event object which I'll name
here eventObj and data type it as
| | 06:06 | a TextEvent class. Then instantiate it using
a call to this TextEvent class's
| | 06:13 | constructor method and pass in the name of
the event that you want to dispatch
| | 06:18 | which is finish.
| | 06:21 | Next, pass in the string value that you want
to send to the application, you'll
| | 06:25 | put this into the text property of the
TextEvent object. The code will look like this,
| | 06:31 | eventObj.text = "Yellow car won!"
| | 06:37 | Now in this application there isn't any suspense
because the yellow car always
| | 06:41 | wins, but in a more complete Flash symbol
that had a lot of logic to it, you
| | 06:45 | might be reporting a dynamic result.
| | 06:48 | Finally dispatch the event. Call the dispatch
event function and pass in
| | 06:53 | eventObj. Save the changes to the ActionScript
class and close the actions
| | 06:59 | panel. Go back to the Flash file if it's
not already active and re-publish.
| | 07:06 | Now go back to Flex Builder and in Flex
Builder you can now listen for the
| | 07:10 | finish event and handle it in some fashion.
Place the cursor above the
| | 07:16 | Application Control Bar and add a Script
section. Then create a function named
| | 07:21 | finishHandler. Data type it's event argument
as TextEvent and return void.
| | 07:32 | Now, within the finishHandler function, use
the alert class to display message
| | 07:37 | to the user to tell them who won the race.
The code will look like this, I'll
| | 07:42 | type in the Alert class name and press
Ctrl+Space and select the class that
| | 07:47 | causes Flex Builder to add the import statement,
then I'll select the show
| | 07:51 | method and I'll pass into the show method
event.text, then I'll pass into a
| | 07:57 | second argument a little string value
for the pop-up window's title.
| | 08:03 | Now, go down to the FlashCarRaceComponent
instance, move the cursor down a bit
| | 08:08 | so are in new line and press Ctrl+Space
to see the list of all available
| | 08:12 | members of the component and start typing
fi and you'll see the finish event
| | 08:18 | exposed. Select it, call the finishHandler
method and pass the event object.
| | 08:24 | Save your changes and run the application
and wait a moment till the
| | 08:28 | application loads and the car gets to the
end of the line and you should see
| | 08:32 | that the event is dispatched and handled
by the Flex application and the alert
| | 08:37 | pop-up window is displayed showing
the race results.
| | 08:40 | So this demonstration represents a more complete
integration between the Flash
| | 08:44 | symbol as a Flex component and the overall
Flex application. You can customize
| | 08:50 | your Flex symbols as much as you want now,
adding custom properties, custom
| | 08:54 | methods and whatever logic and functionality
you need, and then using the Flex
| | 08:59 | Component Kit, you can expose that as a Flex
component and use it in the Flex application.
| | Collapse this transcript |
|
|
5. Working with XML and E4XUsing the ActionScript XML class| 00:00 | In this chapter of the video series, I am
going to describe how to work with
| | 00:04 | XML formatted data using an aspect of the
ActionScript 3 programming language
| | 00:08 | known as E4X. E4X stands for ECMAScript for
XML and it represents an aspect of
| | 00:15 | the language that allows you to easily parse
and extract data from XML objects
| | 00:20 | and also modify those XML objects in application
memory at runtime. E4X is
| | 00:25 | similar in some respect to XPath, another
XML expression language, but whereas
| | 00:30 | XPath is used only to extract data from
XML objects, you can use E4X, both to
| | 00:35 | read and write the data in memory. It
also worth mentioning before I get
| | 00:39 | started with the demonstrations that like
ActionScript itself, E4X is compiled
| | 00:44 | part of the language and to demonstrate
it properly, you have to compile the
| | 00:49 | expression into your applications that you
use to extract or modify the data.
| | 00:53 | For the demonstrations in this chapter,
I will use a flex project that's part
| | 00:57 | of the exercises. If you are following along
with the exercises, you can import
| | 01:01 | the project now.
| | 01:02 | From the Flex Builder menu, select File,
Import, Flex Project. Click the Browse
| | 01:09 | button next to Archive file and then select
Chapter05BeginProject.zip. Import
| | 01:16 | the project, go to the Flex navigator
view and open the project, open its
| | 01:21 | source folder and then open the application
UsingXMLClasses.mxml. This
| | 01:28 | application starts with an empty script
section, an Application control bar
| | 01:32 | that's docked that contains a couple of
buttons with labels and a text area
| | 01:37 | control that will be used to output the results
of creating certain XML objects.
| | 01:42 | There are two primary XMLClasses that we
use in ActionScript to represent XML
| | 01:47 | and data, they are called the XML and the
XMLListClasses. There's also an older
| | 01:53 | version of the XMLClasses known now as XML
node and XML Document these are what
| | 01:59 | we call the legacy XML Classes. And they
represent functionality that was used
| | 02:03 | in ActionScript 2 that could navigate and
parse XML using document object style
| | 02:08 | programming. The new versions of the classes
XML and XMLList are compatible
| | 02:13 | with the E4X language.
| | 02:15 | The first thing I would like to show
you is that there are a couple of
| | 02:18 | different ways of creating XML objects in
memory. An XML object is instance of
| | 02:23 | an XMLClass and so one way to create an XML
object is simply to hard code it or
| | 02:29 | declare it directly in your ActionScript
code. Then outside the function, I am
| | 02:40 | going to create a variable and then data
type it as XML. I will declare it as
| | 02:45 | private, I will name it as xData, give it
an XML data type and then I am going
| | 02:52 | to initialize it within the init function.
I am also going to mark the object
| | 02:56 | as bindable so that I can use its information
in binding expressions with
| | 03:01 | visual controls.
| | 03:02 | Now within the init function, create the
XML object like this, xdata = and then
| | 03:10 | on the next line you can code any XML
structure you want. This is an XML
| | 03:14 | object, not a string. So you don't wrap
the XML content in quotes. I am going
| | 03:20 | to create a root element called data, a
sub element named row, and within the
| | 03:28 | sub element I will create sub elements
named firstname and lastname.
| | 03:40 | Now I am going to copy this row to the clipboard
and then paste it once, so I
| | 03:48 | have two row elements. Then I will fill
in the values. For the first row, I
| | 03:54 | will use a first name of Joe and a last name
Smith and then in the second row I
| | 04:00 | will use a first name of Mary and a last
name of Jones. So this is one way of
| | 04:05 | creating an XML object in memory. You declare
the object, if you want it to be
| | 04:10 | bindable, you indicate it with the bindable
metadata tag and then the data is
| | 04:15 | available for use in your application.
| | 04:17 | In this first example, I am going to display
the content of the XML object
| | 04:22 | using the text area control. I will go
to the text area control and set its
| | 04:26 | text property to a binding expression of
xData.tostring. Finally I will go back
| | 04:34 | up to the top of the application and add
an application complete event listener
| | 04:39 | and there I will call the init method.
| | 04:41 | So here are the steps, I have declared the
variable outside of any function, so
| | 04:45 | I can get to it from anywhere in the application.
Within the init function I
| | 04:50 | have initialized the object using XML markup.
If you like to make this very
| | 04:55 | clear that it's a complete ActionScript statement,
you can even add a semicolon
| | 04:58 | at the end. Again this is an object that's
being declared, not a string. In the
| | 05:04 | text area control, I will display the text
representation of the XML object
| | 05:08 | using the expression xData.tostring. I
will save the changes and run the
| | 05:13 | application and you should see that the
data is now displayed as XML in the
| | 05:20 | text area control.
| | 05:21 | Now in the next video, I will talk about
another type of XML object called XML
| | 05:25 | list which is a collection of XML notes.
| | Collapse this transcript |
| Extracting an XMLList with E4X| 00:00 | In this video I am going to describe the
use of an Action Script class named
| | 00:04 | XML list. The nature of the XML list class
is that it represents a collection
| | 00:09 | of XML nodes. You can create an XML list
object using hard coded ActionScript
| | 00:15 | code as I did in the previous example using
the XML class or more commonly, you
| | 00:20 | create an XML list by extracting it
from an XML object, using an E4X expression.
| | 00:26 | For this demonstration, I will use the application
using XMLlist.mxml, if you
| | 00:32 | are following along with the exercises,
you will find this application in the
| | 00:35 | Chapter05BeginProject. This is the same application
I worked on in the previous
| | 00:41 | video. It declares a variable named xData,
data typed as XML, then in the init
| | 00:47 | function, it initializes that object
using XML markup as part of an
| | 00:52 | ActionScript statement. In this demonstration
I am going to show you how to
| | 00:57 | declare an XML list object and then extract
a data for the XML list from the
| | 01:02 | XML object using E4X.
| | 01:05 | Create a new private function named getList,
make it return void. Within the
| | 01:13 | function declare a variable named xList data
typed as XMLList. Then extract the
| | 01:20 | value of that variable using the following
syntax, start the expression with
| | 01:25 | xData, the name of the XML object variable
and then walk down to the repeating
| | 01:31 | elements of the XML object, row. Notice
that you don't refer to the root
| | 01:36 | element data. When you are working with
E4X expressions, the variable that
| | 01:41 | refers to the XML content refers to the
element already. So you wouldn't say
| | 01:45 | xData.data.row, xDAta already represents
the root element that is the data
| | 01:51 | element. Next place of breakpoint on the
final line of the getList function
| | 01:57 | that is the line with the closing brace,
then scroll down to the application
| | 02:01 | control bar container and locate the button
labeled getList, add a click event
| | 02:06 | listener and call the new function getList.
Run the application in Debug mode.
| | 02:18 | When the application starts up, the xData
object is initialized and its string
| | 02:23 | representation is shown in the text area.
Now click the getList button, that
| | 02:28 | should trigger the breakpoint in Flex Builder.
Go over the Flex Builder and if
| | 02:32 | prompted to switch to the Flex Debugging
perspective, click yes. Then go to the
| | 02:37 | variables view and double click its tab.
Here is the variable that was declared
| | 02:41 | within the function xList. Take a look
down at the bottom of the variables
| | 02:45 | view. You may need to scroll upward to see
all of its content, but you will see
| | 02:49 | the complete set of row elements is represented.
| | 02:55 | You can also go back up to the variables
view and open the tree and you will
| | 02:58 | see that the xList variable consist of multiple
items, rows, each with an index
| | 03:03 | number indicating that XML objects position
within the list. So you can see
| | 03:08 | that you have successfully extracted just
the repeating rows and are now
| | 03:11 | representing that data in an object in memory.
Resize the variables view so you
| | 03:17 | can see the other views and then terminate
your Debugging session and return to
| | 03:22 | the Flex Development perspective. Output
the string representation of the
| | 03:27 | XMLList to the text area control, like this,
out.text = xlist.tostring. Save
| | 03:38 | the changes and run the application this
time in normal mode. When the
| | 03:44 | application starts up, click the getList
button and you should see that the
| | 03:47 | text area control now displays the string
representation of the list of XML
| | 03:52 | objects rather than the entire XML objects.
| | 03:55 | So that's your first simple introduction
to the world of E4X. The E4X
| | 04:00 | expression, xData.row, successfully retrieves
and returns a list of XML nodes.
| | 04:07 | You can represent that data in any variable
that's data typed as XMLList,
| | 04:12 | powerful E4X expression syntax that you can use.
| | Collapse this transcript |
| Retrieving XML in E4X format with HTTPService| 00:00 | In this video, I am going to describe how
to retrieve XML formatted text files
| | 00:05 | and parse them in to a format that can be
read with E4X. For this demonstration
| | 00:09 | I will use an application named
ImportWithHTTPservice.mxml. If you are
| | 00:14 | following along with the exercises, you
can open this file from the project.
| | 00:19 | This version of the application has an empty
init function. The controls at the
| | 00:23 | bottom of the application, the Application
control bar with the buttons and the
| | 00:27 | text area are the same as in
the previous application.
| | 00:31 | In this application I am going to retrieve
a file named invoices.xml that you
| | 00:35 | will find in the data folder under the source
code root. This file has a root
| | 00:39 | element named invoices and repeating elements
named invoice and then a mixture
| | 00:45 | of customer and items element in each
invoice. If you watched the Flex 3
| | 00:50 | essential training video series, you learned
that the HTTPservice control is
| | 00:55 | able to retrieve XML formatted data, parse
it and return the data in a format
| | 01:00 | that you can use in your ActionScript code.
In that video series, I used the
| | 01:04 | HTTPservice element to retrieve data as
a set of objects, that is, an object
| | 01:10 | tree that contained a mixture of
objects and array collections.
| | 01:14 | In this video I am going to show you how
to retrieve the data and instead
| | 01:17 | return it as a true XML object that's compatible
with E4X. Place the cursor
| | 01:23 | after the script section and create an HTTPservice
object, give it an ID of XML
| | 01:30 | service and a URL pointing to the location
of the XML file, data/invoices.xml.
| | 01:39 | Add a result event handler and call a function
that you will need to create
| | 01:43 | named result handler and pass the event
object. Next go to the script section
| | 01:50 | and create that function, name it result
handler, set it up to receive a single
| | 01:56 | event argument, data typed as the result
event class and return void.
| | 02:03 | Make sure at the top of the script section,
that Flex Builder added the
| | 02:06 | required Import statement for the result
event class. Now place the cursor
| | 02:11 | inside the init method and send the request
for the HTTP service using the
| | 02:15 | syntax xmlService.send. Place a breakpoint
on the last line of the
| | 02:22 | resultHandler function, that's the line
with the closing brace, then run the
| | 02:27 | application in Debug mode. When you hit
the breakpoint and the application is
| | 02:31 | suspended, if Flex Builder prompts you to
go to the Flex Debugging perspective,
| | 02:35 | click yes. Then go to the variables view.
| | 02:39 | In the variables view, navigate to the
event.result object. The default
| | 02:44 | behavior of the HTTPservice component is
to parse and return the data as a set
| | 02:48 | of objects. The top level node or the root
element of the XML is returned as an
| | 02:53 | object wrapped inside a class called ObjectProxy
and then within that data
| | 02:59 | structure, you will find that any element
that only occurs once within any
| | 03:03 | particular level of the XML hierarchy,
it's returned once again as an
| | 03:07 | ObjectProxy.
| | 03:08 | But any element that occurs at least twice
such as the invoice element is
| | 03:13 | returned as an array collection. This is
what we call the object structure of
| | 03:17 | XML and well the object structure can be
useful in certain circumstances, in
| | 03:23 | many cases, you are going to instead want
to return the data as true XML. So
| | 03:27 | let's terminate the Debugging section. Go
to the Debug view or the console view
| | 03:31 | and click the red terminate button, return
to the Flex Development Perspective
| | 03:37 | and go back down to the declaration
of the HTTPservice object.
| | 03:41 | In order to return the data as a true
XML object, set the HTTPservice
| | 03:46 | components result format property to a value
of E4X, save the changes and run
| | 03:52 | the application in Debug mode again. When
you hit the break point, once again
| | 03:57 | go into the Flex Debugging perspective,
take a look at the variables view and
| | 04:02 | look at event.result. This time it comes
back as a true XML object and as I
| | 04:08 | showed in a previous video, if an object
is data typed as pure XML, it's
| | 04:13 | compatible with E4X expressions. So restore
the size of the variables view and
| | 04:17 | once again terminate the Debugging session.
Go back to the Development
| | 04:22 | perspective, place the cursor inside the
resultHandler function and now you are
| | 04:27 | going to save the results that are returned
from the HTTPservice request to the
| | 04:32 | pre-declared xData variable which has been
marked as bindable and data typed as XML.
| | 04:38 | With the cursor inside result handler add
this code, xData = event.result as
| | 04:46 | XML. The compiler doesn't know that event.result
will be returned as an XML
| | 04:50 | object. It expects a generic ActionScript
object, so the 'as' operator
| | 04:55 | explicitly declares that this will be an
XML object and from this point on
| | 05:00 | everything should bind together correctly.
Save your changes and run the
| | 05:03 | application again, this time in normal mode,
not Debug and as the application
| | 05:08 | starts up, it loads the data, retrieves
it and then due to the binding
| | 05:13 | expression in the text area control, the
string representation of the XML
| | 05:17 | object is displayed. Go back to the code
and take a look at the getList function.
| | 05:23 | In this version of the getList function,
the E4X expression that's retrieving
| | 05:27 | data is xData.invoice. And once again we
are walking down directly from the
| | 05:32 | root element to the repeating elements and
because there are at least two of
| | 05:37 | them, they are returned as an XML list.
Run the application again, once again
| | 05:42 | see that the full XML content is returned
and displayed and now click the
| | 05:47 | getList button. And you will see that you
are retrieving now only the list of
| | 05:50 | XML objects, multiple invoices.
| | 05:54 | So that's how you use the HTTPservice component
to retrieve an XML file and
| | 05:59 | represent it in Flex application memory
a true XML object that's compatible with E4X.
| | Collapse this transcript |
| Modifying XML data with E4X| 00:00 | In this video I am going to give a brief
demo of how to modify XML formated
| | 00:04 | data in application memory in Flex,
using an E4X expression. For this
| | 00:09 | demonstration, I use the application file
ModifyXMLData.mxml. This is the same
| | 00:16 | application I had been working on in the
previous videos. It now retrieves data
| | 00:20 | using the HTTP service component, and
saves it as an XML object that's
| | 00:25 | compatible with the E4X language. In the
previous video, I showed how to save
| | 00:29 | the datas in XML object, using the Result
Event Handler of HTTP service
| | 00:33 | component, and then how to extract data,
using a simple E4X expression. In this
| | 00:39 | case, this expression was extract in data.
In this video I am going to show you
| | 00:43 | how to use a simple E4X expression
to change the data.
| | 00:47 | Create a new private function in the script
section of the application. Name it
| | 00:52 | changeData. Return void, and then within
the function, modify the text value of
| | 01:00 | the first name element of the first customer
in the first invoice. Here's how
| | 01:05 | the syntax works. I will start off with
xData, (that's the name of the XML
| | 01:10 | object .invoice) xData.invoice and then
I will use a ray style syntax to
| | 01:15 | indicate that I want to address the first
invoice element in the external data
| | 01:19 | object. Then refer to the first customer
in the first invoice, using similar
| | 01:23 | syntax. I am now referring to the first
customer in the first invoice.
| | 01:29 | Finally, refer to the firstname element of
that customer, and change the value
| | 01:35 | of that elements text note, using any literal
strength. I will pass in a value
| | 01:40 | of "Michael". Then to see the result, output
the string representation of the
| | 01:45 | first invoice. As before, use the text
area control with an id, and set its
| | 01:51 | value using the expression xData.invoice 0.toString.
| | 02:00 | Go down to the ApplicationControlBar to the
button with a label of "Change Data," and add a
| | 02:05 | quick event listener, and handle the event
by calling the new "changeData"
| | 02:09 | function. Run the application. When the
application first starts up, it loads
| | 02:16 | the external formated file using the HTTPservice
component and delivers it as
| | 02:21 | an XML object. The text area control using
it's binding expression displays the
| | 02:26 | string representation of the XML.
| | 02:29 | Click the Change Data button, and you
will that the first invoice, first
| | 02:33 | customer, firstname element has been
successfully modified to a value of
| | 02:37 | Michael. So that's a look at a simple E4X
expression that modifies data. Now in
| | 02:43 | the next couple of videos I will go through
a whole set of example expressions,
| | 02:46 | that you can try out in your own applications,
and show you what their results
| | 02:50 | are. So you can see some of the
flexibility of E4X expression syntax.
| | Collapse this transcript |
| E4X expressions for parsing data | 00:00 | In this video I am going to describe
the variety of operators and other
| | 00:04 | expression elements you can use in E4X to
extract data from an XML object. For
| | 00:10 | this demonstration, I'll use two files.
The application is named
| | 00:14 | E4XParsing.mxml. If you are following along
with the exercises you can open it now.
| | 00:20 | This component uses an ActionScript class,
named E4XParsingHelper. This
| | 00:25 | ActionScript class has two static functions
named getExpressions and evalE4X.
| | 00:30 | The getExpressions function returns an array
collection of strings. These are
| | 00:35 | simple labels that will be used to display
to the user which expression is being evaluated.
| | 00:40 | The evalE4X static function actually executes
each E4X expression. If you want
| | 00:46 | to add new expressions to this sample
application, or change any of the
| | 00:50 | expressions to see what happens, you would
modify the element both in the
| | 00:53 | getExpressions method and in the evalE4X method.
| | 00:56 | For example, the first label that's
returned in the array collection
| | 01:01 | xInvoices.invoice matches the expression
that's returned in the function
| | 01:06 | evalE4X. Now we'll go back to
the application and run it.
| | 01:11 | When you run the application, it displays
the XML that's being searched on the
| | 01:15 | left, in the top left corner and then a
set of possible E4X expressions and
| | 01:20 | again these values are being retrieved from
the helper class's static method. I
| | 01:24 | am going to go through each of these
expressions, talk about what they do and
| | 01:28 | then show you the result.
| | 01:30 | As I described in a previous video, the
simplest of E4X extraction expressions
| | 01:35 | start with the root element represented by
the XML object itself, in this case
| | 01:40 | xInvoices. When you use a single dot, that's
called the child accessor operator
| | 01:46 | and it means that you are walking down to
the named element. xInvoices.invoice
| | 01:50 | means go get the invoice elements, that
are direct children of the root element.
| | 01:56 | I'll click on that expression and in
the right result pane, you'll the
| | 02:00 | returned XML consisting of all invoice
elements. When you are dealing with
| | 02:04 | elements that repeat, that is, where there
is more than one element of the same
| | 02:08 | name in that position, you can use array
syntax to indicate which one item you
| | 02:13 | want to retrieve.
| | 02:14 | The expression xInvoices.invoice 1 means
retrieve the second invoice element
| | 02:21 | within the root element, as with all
the arrays and other indexing in
| | 02:25 | ActionScript, indexing starts at zero. So
an index position of 1 means give me
| | 02:30 | the second item.
| | 02:32 | The next example is this extended dot syntax
to walk down the XML tree a little
| | 02:36 | bit further. xInvoices.invoice 0 means the
first invoice, .customer means give
| | 02:42 | me the customer element within that invoice.
If you take a look at the actual
| | 02:47 | XML that we are searching, you'll see that
the invoice only has one customer
| | 02:51 | and that's what's being returned.
| | 02:53 | The next example uses the descendant accessor
operator. The .. operator means
| | 02:59 | go down to this named element, wherever
it is in the XML hierarchy. It does a
| | 03:04 | deep search of the XML structure, so if you
know which element you want by name
| | 03:08 | and you know that it won't be repeated in
any other level of the XML hierarchy,
| | 03:13 | you don't have to walk down
one element at a time.
| | 03:15 | Xinvoices. that customer means give me all
the elements named customer anywhere
| | 03:20 | in the XML hierarchy regardless of level.
The next example uses a predicate
| | 03:25 | expression. A predicate is like a filter
or a query, it's a way of saying
| | 03:30 | return this element by name but only where
it's particular sub- element or
| | 03:35 | aptitude equals a particular value.
| | 03:37 | In this example we are saying, give me
all customer elements where the last
| | 03:42 | name of sub-element has a text value of 'Jones'.
And in the result you see that
| | 03:47 | that's what returned. You can also return
a particular element that only has a
| | 03:51 | text note by using it's toString method.
| | 03:53 | Here we are saying, give me all line items,
where the string node, that is the
| | 03:58 | text node of the element equals a value of
'Mouse' and this expression returns
| | 04:04 | two line items in the result panel. Using
predicate expressions you can also
| | 04:08 | compare values to attributes. In order to
refer to an attribute, rather than an
| | 04:13 | element by name, use the @ character as
a prefix. So this expression means,
| | 04:18 | give me all line items where their price
attributes are less than eight.
| | 04:22 | If you are working with numeric values,
as you are here, you can indicate
| | 04:26 | whether you are doing a numeric or a string
comparison by the presence or
| | 04:30 | absence of quotes around the value. In
this example that's highlighted, the
| | 04:34 | number eight doesn't have quotes. So this
is a numeric evaluation. I am asking
| | 04:38 | for all items where the price attribute
is less than eight numerically and I
| | 04:43 | get these three items back, where
the price is less than eight.
| | 04:47 | But if you wrap the number eight with quotes,
then you are saying that it's a
| | 04:51 | string evaluation and now you are comparing
the value of each price attribute
| | 04:56 | to this string eight. And notice that you
also now get back a line item element
| | 05:00 | where the price is 21.41, it's more than
eight numerically but it starts with a
| | 05:06 | value of less than eight in
terms of string values.
| | 05:09 | So these were the various operators that
you can use in E4X expressions. If you
| | 05:14 | compare this to the kind of code you would
have to write in old style document
| | 05:18 | object model code, you can see that you can
extract data with very simple, very
| | 05:23 | concise expressions that might otherwise
take five or ten lines of ActionScript
| | 05:28 | code to execute.
| | 05:29 | Now in the next video, I'll show you some
other examples of this kind of E4X
| | 05:34 | expression but this time modifying
data in the XML structure.
| | Collapse this transcript |
| E4X expressions for modifying data | 00:00 | In this video I am going to describe various
methods you can use to modify XML
| | 00:05 | data at runtime using E4X expressions. For
these demonstrations, I will use an
| | 00:10 | application named E4XChanging.mxml and
it's associated ActionScript helper
| | 00:15 | class which you will find in the helpers
folder named E4XChangingHelper.as.
| | 00:22 | Let's talk about the application first, when
you first start the application up
| | 00:26 | it retrieves an XML file and then displays
its string representation on the
| | 00:31 | right side. You will see that it's the
same XML file I used in the previous
| | 00:35 | exercise. This time the goal is to modify
the data in memory and then display
| | 00:40 | the results in this panel. Now let's go
back to the code, whenever the user
| | 00:45 | selects an item from the list of available
expressions, this evaluate function
| | 00:50 | is called from the application.
| | 00:52 | The first step at line 38 is to make a copy
of the existing XML data object.
| | 00:58 | The XML class has a method named copy which
results in cloning the XML object
| | 01:04 | so that the new version is completely detached
from the old one. This allows us
| | 01:08 | to make changes to the new version without
disrupting or disturbing the old
| | 01:12 | data. So this copy of the data is named
tempXML. The next step is to make a
| | 01:17 | call to a static method of the helper class
named evalE4X which passes in the
| | 01:23 | index of the selected expression. In
this function we will receive the
| | 01:27 | temporary XML object as an argument and
the index, we evaluate the index and
| | 01:33 | then we modify that XML data
object and then return.
| | 01:38 | The XML data object which is being modified
by reference is then displayed as a
| | 01:42 | string representation in the text area control.
Let's take a look at the first
| | 01:47 | example in action; once again as the application
starts up we display the
| | 01:51 | string representation of the original XML
and heres the first expression, very
| | 01:56 | similar to the one that I demonstrated
earlier. In this expression, I am
| | 02:00 | changing the value of the firstname element
of the customer in the first
| | 02:04 | invoice. Right now that customer is Maria
Smith; let's see what happens when I
| | 02:10 | click on the first expression. The result
is that the firstname element has been changed.
| | 02:16 | Each time you make a change, you can go
back to the original by clicking this
| | 02:19 | button at the bottom labeled Show Original
and you will go back to the original
| | 02:23 | data and you will be ready for the next example.
In the next expression we are
| | 02:28 | doing something very similar to the first,
we are modifying a particular value
| | 02:32 | but this time we are changing the value of
an attribute rather than an element.
| | 02:36 | The syntax lineitem 0 .@price means change
the value of the price attribute in
| | 02:43 | the first lineitem, that lineitem is currently
21.41. I will select the element
| | 02:50 | and the result is to change the price to 12.5.
| | 02:55 | Now notice that even though in the expression,
I said price equals 12.50, this
| | 03:00 | was truncated down to 12.5 and this is because
the numeric value is evaluated
| | 03:06 | as a number. If you want to retain the full
string, you should wrap the value
| | 03:11 | with quotes as in the next example. This
expression is saying change the price
| | 03:16 | attribute of the first lineitem to a string
of 12.50 and there is the result.
| | 03:23 | So, once again as I showed in the previous
video, when you modify data the
| | 03:28 | quotes have meaning, if you wrap quotes
around a numeric value that means you
| | 03:32 | are treating it as a string and if you eliminate
the quotes, that means you are
| | 03:35 | treating it as a number. You can also use
an E4X command or expression to add elements.
| | 03:41 | Let's go back to the original XML data by
clicking the Show Original button and
| | 03:46 | I will show you that the customer element
has elements of firstname and
| | 03:50 | lastname. You can add an element any time
you want by pretending it already
| | 03:55 | exists in your E4X expression. The fourth
expression in the list says the
| | 04:00 | customer.city element of the first invoice
equals Seattle. Notice the use of
| | 04:05 | the single equal's operator, this is the
assignment operator in ActionScript
| | 04:09 | rather than the quality operator and if
that element doesn't exist, running
| | 04:14 | this expression will create it. I will select
the expression and then show you
| | 04:18 | in the XML data that results that the city
element has been created and then
| | 04:24 | once again I will go back to the original.
You can do the same thing with attributes.
| | 04:28 | In the fifth expression in the list, we are
saying set the value of the inStock
| | 04:33 | attribute to a value of true. If you go to
the first lineitem you will see that
| | 04:37 | it doesn't have an inStock attribute but
by selecting that expression, the
| | 04:42 | attribute is added. So you can add elements
and attributes using E4X
| | 04:47 | expressions by simply pretending they already
exist and setting their values.
| | 04:52 | The last three expressions in the list use
an operator named delete; you can
| | 04:56 | use the delete operator to remove whole elements
or attributes of elements from
| | 05:01 | the XML content. Lets once again go back
to the original and then select the
| | 05:06 | first delete expression; this says delete
xInvoices.invoice 1 . Remembering
| | 05:13 | that all indexing starts at 0, this means
in English remove or delete the
| | 05:17 | second invoice. I will click the expression
and the second invoice is removed
| | 05:23 | from the XML structure.
| | 05:24 | Notice that the remaining XML structure is
well formed and intact, so there is
| | 05:29 | an intelligent parsing of the XML structure
and then the particular node that
| | 05:33 | you refer to is removed. Once again I will
go back to the original and this
| | 05:39 | time I am going to delete a number
of items, this syntax delete
| | 05:43 | xInvoices.invoice 0 , the first invoice
.items.lineitem refers to all elements
| | 05:51 | named lineitem within that particular items
parent element. I will select the
| | 05:55 | expression and you will see that the items
element is now empty. So this allows
| | 06:00 | you to remove more than one element at the
same time if they all match in some
| | 06:05 | fashion, in this case by the element name.
| | 06:08 | Finally going back to the original one
more time, you can also delete a
| | 06:11 | particular attribute from an XML structure
by using the delete operator and
| | 06:16 | then in the expression referring to the
particular attribute you want to
| | 06:19 | remove. This one says remove the quantity
attribute from the first lineitem in
| | 06:25 | the items element, in the first invoice;
that would be this value of quantity
| | 06:30 | equals 4 and let's see if it works. I
will select the expression and the
| | 06:35 | attribute is deleted.
| | 06:37 | So these are various methods that you can
use to modify XML data in application
| | 06:41 | memory at run-time. You can use E4X for extracting
data as I showed earlier and
| | 06:47 | you can also it to manage or modify the data
whenever you want and then if you
| | 06:52 | want to save the data, say to a file or push
it into a database you can always
| | 06:56 | use the XML classes to string method to
get the string representation of that
| | 07:01 | XML object for saving in some format.
| | Collapse this transcript |
| Using XML namespaces with E4X| 00:00 | In this video, I am going to describe
how to use XML namespace objects to
| | 00:04 | distinguish between elements that have the
same name in an XML structure. For
| | 00:09 | this demonstration, I will use the application
E4XWithNamespaces.mxml. If you
| | 00:15 | are following along with the exercises, you
can open this now in Flex Builder;
| | 00:18 | take a look at the script section of this
file. There is a variable declaration
| | 00:23 | right in the script section outside of any
functions, the name of the variable
| | 00:26 | is xTravel, its data type is an XML object
and it has a root element named
| | 00:31 | travel and within the root elements begin
tag there are three names based
| | 00:36 | declarations.
| | 00:37 | The actual URIs that is the namespace strings
are unimportant here, what's
| | 00:42 | really important to us is the XML prefixes.
Each of these prefixes identifies a
| | 00:47 | particular a namespace or a particular
group of elements that can be
| | 00:52 | distinguished from each other and then
within the journey element there are
| | 00:56 | three travel time elements that use
those namespaces. There is a
| | 01:00 | train:traveltime, a plane:traveltime and
a car:traveltime and they each have
| | 01:06 | three different values. When you are parsing
XML that uses namespaces you have
| | 01:10 | to know how to use a namespace object to
qualify your search and distinguish
| | 01:15 | between elements of the same name.
| | 01:18 | At the bottom of the application there is
a set of RadioButtons grouped within
| | 01:21 | a panel. When the user clicks on one of
the RadioButtons, the itemClick event
| | 01:26 | handler of the RadioButtonGroup control calls
the getTravelTime method. Here we
| | 01:31 | extract the value of the RadioButton that
was clicked and save it in this
| | 01:35 | vehicle variable. Our job is to use that
value and XML namespaces to do a
| | 01:41 | qualified search for a value based on a
combination of namespace and element name.
| | 01:46 | Here are the steps; first I am going to
declare one namespace object for each
| | 01:52 | XML namespace prefix that I want to use
in my searches. For each one I will
| | 01:57 | declare a variable, I will start off
with private var and then give the
| | 02:02 | variable a name, I will call the first
one trainNS for namespace and I will
| | 02:08 | data type it as a namespace object. I will
initialize it using this syntax, I
| | 02:13 | will start with xTravel which is the name
of the variable referencing the XML
| | 02:17 | object and then I will call its namespace
function and I will pass in the
| | 02:22 | prefix that I want to associate this
namespace object with as a string.
| | 02:29 | Notice that the XML namespace as a string
here matches the prefix in the actual
| | 02:34 | XML declaration. Now I am going to clone
that line of code a couple of times
| | 02:39 | and I will change the namespace object
name and the namespace prefix as a
| | 02:44 | string so that they match up. The second
one will be for the plane namespace
| | 02:49 | and the plane prefix and the third will
be for the car namespace and the car
| | 02:55 | prefix. I now have one namespace object
for each of the namespace prefixes
| | 03:01 | declared in the XML file. Now I am
ready to do a search, go to the
| | 03:06 | getTravelTime function and place the cursor
after the declaration of the
| | 03:10 | vehicle variable.
| | 03:11 | The next step is to create a switch statement
that evaluates the vehicle
| | 03:16 | variable and then looks at three possible
cases. The first one is for the value
| | 03:22 | of plane, the second for the value of train
and the third for the value of car.
| | 03:30 | Let's go to the first case, I am going to
use the planeNS namespace object to
| | 03:35 | qualify my search for the traveltime element
in the XML content and then I am
| | 03:40 | going to save the results of my search
to the pre-declared variable result
| | 03:44 | string. This value is being displayed
through a binding expression in the
| | 03:48 | panel; going back to the code I will
place the cursor after the case
| | 03:51 | declaration and I will set the value of
the resultString variable using this
| | 03:56 | E4X expression.
| | 03:57 | I will start off with the xTravel variable
name that represents the root
| | 04:01 | element of the XML content. Then I will
walk down to the journey element,
| | 04:06 | that's its child element and then I will
use the namespace object to qualify my
| | 04:10 | search. I am looking for a planeNS::traveltime.
Now make sure that you match
| | 04:19 | the element name here traveltime to the name
of the element as it's declared in
| | 04:23 | the XML content. This is very highly case
sensitive and you got to get it
| | 04:27 | right. The double colon operator is used
to qualify the element name; so in
| | 04:33 | English we are saying give me the value
of the traveltime element that's a
| | 04:37 | member of this namespace object and this
namespace object in turn is associated
| | 04:43 | with the train namespace string as it's
declared in the call to the namespace function.
| | 04:49 | After that command, add a break command
so you don't continue through and
| | 04:52 | execute the rest of the switch statement.
Then copy and paste these two lines
| | 04:58 | and paste them after each case, then go
back to each of those commands and
| | 05:05 | change the namespace that we are using to
qualify your search; for the second
| | 05:09 | one use trainNS and for the third one use
carNS. So that's all with the code,
| | 05:17 | when the user selects a particular value
through the RadioButtonGroup, you will
| | 05:21 | evaluate what they selected and then use
the appropriate namespace object to
| | 05:26 | qualify your E4X expression.
| | 05:28 | Run the application, notice that the initial
return string has a value of
| | 05:33 | Choose a vehicle and you should now be
able to click on any particular
| | 05:37 | RadioButton and you will be doing qualified
E4X search of the XML data. So
| | 05:43 | that's a look at how to use namespaces in
E4X expressions. The most critical
| | 05:48 | parts to remember are the double colon operator,
that's used to separate the
| | 05:51 | namespace object from the element name
you are looking for. The use of
| | 05:56 | namespace objects to hold that information
and the use of the XML objects
| | 06:01 | namespace function to initialize the namespace
object and associate it with a
| | 06:05 | particular namespace prefix. Using these
tools you will be able to navigate and
| | 06:10 | extract data from any XML file,
no matter how complex.
| | Collapse this transcript |
|
|
6. Using the Tree and MenuBar ControlsUsing the Tree control with XML data| 00:00 | In this chapter of the video series I am
going to describe the use of Tree and
| | 00:04 | MenuBar controls. These are visual controls
in the Flex class library that
| | 00:09 | distinguish themselves from other list style
controls that you might use, such
| | 00:13 | as the data grid, list, horizontal list
and tile list. Those controls which I
| | 00:18 | described in some detail in the Flex 3 Essential
training video series use data
| | 00:23 | that you might get from an SQL statement
from a database. That sort of data is
| | 00:28 | stored in rows and columns and presented
in the DataGrid or other styles of lists.
| | 00:34 | The Tree and the MenuBar controls in
contrast use hierarchical data that's
| | 00:39 | typically stored as XML. Now in the previous
chapter of this video series, I
| | 00:44 | described how to work with XML using
the E4X aspect of the ActionScript
| | 00:48 | language and we will be combining those skills,
that is, the ability to extract
| | 00:52 | data from XML using E4X with a look at the
visual controls that use that sort
| | 00:57 | of data. For the demonstrations in this chapter,
I will be using a Flex Project
| | 01:02 | from the Exercises folder. If you are following
along with the exercises you
| | 01:06 | can import it now. From the Flex Builder
menu select File, Import, Flex
| | 01:13 | Project, click the Browse button next
to Archive file, navigate to the
| | 01:18 | Chapter06 folder under Exercises and select
the file Chapter06BeginProject.zip.
| | 01:26 | Import the project, go the Flex Navigator
view and open the project, open its
| | 01:32 | source folder and then open the application
file UseTreeControl.mxml. I run the
| | 01:41 | application so we can see its initial presentation.
This application has two
| | 01:46 | empty panels shown side by side, the first
has a title of Photos by Location
| | 01:53 | and the second has a title of Photo Detail.
Our job will be to fill these
| | 01:57 | panels in with other visual controls. By
the time these exercise are done, we
| | 02:02 | will have a treecontrol in the first
panel and a detail presentation of
| | 02:07 | selected data from the treecontrol in the
right panel. I will go back to the
| | 02:11 | source code, notice this application already
has an HTTPService component
| | 02:17 | declared, it has a URL attribute that's
pointing to a file called
| | 02:20 | slideshow.xml, a result event listener
that's calling a method called
| | 02:25 | resultHandler passed in the event object
and its result format property is set
| | 02:30 | to e4x.
| | 02:32 | Go to the resultHandler function and add
a break point on the last line, that
| | 02:36 | is, the line with the closing brace. Then
run the application in Debug mode, as
| | 02:43 | the application starts up, it retrieves the
XML content and if you are prompted
| | 02:47 | to switch to the Flex Debugging
perspective, click
| | 02:50 | Yes. Then in the Flex Debugging perspective,
go to the Variables view and
| | 02:56 | inspect the event objects result property
and as I showed in the previous
| | 03:00 | chapter of this video series, because
the result format property of the
| | 03:04 | HTTPService control is set to e4x, we will
receive a true XML object that can
| | 03:10 | be parsed using E4X expressions. Restore
the Variables view to its original
| | 03:16 | size and terminate your Debugging session.
| | 03:19 | Then go back to the Flex Development perspective,
here are the tasks I am going
| | 03:25 | to accomplish in this application. First,
I am going to declare a variable
| | 03:29 | that's bindable, data type is an XML list.
You can use either an XML object, an
| | 03:36 | XML list or another kind of object called
an XML list collection as the data
| | 03:41 | provider for a Tree or a MenuBar control.
Typically you make these data objects
| | 03:46 | bindable just as you might within a ray
collection for a DataGrid. So I will
| | 03:50 | place the cursor above the resultHandler
function and add a [Bindable] metadata
| | 03:54 | tag and then I will declare a private variable
and I will name it xLocations,
| | 04:01 | data typed as XMLList. Now go down to the
resultHandler function and fill in
| | 04:08 | the value of that variable using the
following syntax, xLocations =
| | 04:14 | event.result, that expression points to
the root element of the XML document
| | 04:20 | and then we will walk down to the repeating
element which is named location.
| | 04:25 | This xLocations variable now contains the
data that I would like to display in
| | 04:28 | the Tree control. Now go down to the Panel
that has an id of locationPanel,
| | 04:35 | make a little bit of space between the panel
tags and declare a Tree control.
| | 04:41 | Give it an id of locationTree and set its
dataProvider property using a binding
| | 04:47 | expression to the xLocations variable that
you just declared and filled in.
| | 04:55 | Make the Tree expand to fill the entire
panel, set its width and height
| | 04:59 | properties to 100% each. Save your changes
and run the application now, you
| | 05:09 | will see that the Tree control is created
but the display isn't quite what you
| | 05:14 | want. Notice that each node of the Tree
displays all of the XML for that
| | 05:20 | particular location node, without further
instruction the Tree control doesn't
| | 05:25 | know how to break down the XML content and
extract the appropriate label for each node.
| | 05:30 | So that will be the next step; close the
application and then take a look at
| | 05:36 | the XML file that we are using, it's
in the data folder and its name is
| | 05:40 | slideshow.xml. Notice that this XML file
structure has been designed so that
| | 05:47 | each element that's going to represent a
node in the Tree has an attribute with
| | 05:51 | the same name; I have named it label here.
You must provide this information to
| | 05:57 | the Tree control so that it knows how to
extract and present the label for each
| | 06:01 | node. Go back to the UseTreeControl.mxml
file and add one more attribute to the
| | 06:07 | Tree. The name of the attribute will be labelField
and the value will be an E4X
| | 06:14 | expression of @label.
| | 06:17 | As I described in the E4X chapter, the @
character before an identifier means
| | 06:23 | look for an attribute name rather than an
element name. Save your changes and
| | 06:28 | run the application. Now the Tree control
is doing what we want, there is one
| | 06:34 | node for each item in the XML list that
was retrieved from the XML object and
| | 06:39 | within each of those nodes there are child
nodes that represent the different
| | 06:43 | photos that we would like to display.
| | 06:46 | So that's a look how to create a basic
Tree control and associate it with
| | 06:49 | hierarchical data in XML format. Now in the
rest of the videos of this chapter,
| | 06:54 | I will show you how to do a few more advanced
things with the Tree control
| | 06:57 | including how to re-skin it, that is how
to provide replacement graphics for
| | 07:01 | these folder and document graphics you see
by default and also we will apply
| | 07:06 | these principles to the MenuBar control.
| | Collapse this transcript |
| Controlling leaf and branch labels| 00:00 | In this video, I am going to describe the
use of a special feature of the Tree
| | 00:04 | control that allows you to dynamically determine
the label that's applied to
| | 00:08 | each node of the Tree. I will be using
a property called labelFunction. The
| | 00:13 | architecture of the labelFunction property
for the Tree control is very similar
| | 00:17 | to that for the DataGrid and other list
type controls. But you will see that
| | 00:22 | the kind of data that's passed into the
labelFunction is a bit different. You
| | 00:26 | create a labelFunction so that it will be
called each time a node of the Tree
| | 00:30 | control is rendered.
| | 00:31 | For this demonstration, I will use an application
named ControllingLabels.mxml.
| | 00:37 | If you are following along with the exercises
you can open this file now. This
| | 00:42 | is the same application that I was just
working on in the previous video. The
| | 00:46 | Tree control is inside a panel and it has
a labelField property that uses an
| | 00:52 | E4X expression to indicate what value should
be displayed as the label for each
| | 00:56 | node of the Tree. I am going to replace
the labelField property with a
| | 01:00 | labelFunction. To get started, go to the
Script section and create a new
| | 01:06 | private function named getTreeLabel. When
you use the labelFunction property,
| | 01:13 | each time the Tree control renders a node;
it will call this function and pass
| | 01:18 | in the underlying XML object that's being
used for that node. So when the
| | 01:24 | function is called a single argument
will be passed in; you can name it
| | 01:28 | anything you want but its data type should
be XML and the return data type of
| | 01:33 | the labelFunction should always be String.
| | 01:38 | Here's the effect I would like to achieve,
if the current node is a location
| | 01:42 | node I want to uppercase its label but
if the current node is a photo node,
| | 01:48 | that is, a child of the location I want
to return the label in its original
| | 01:52 | form. So in this next step I am going
to use a function of the XML object
| | 01:57 | called name which returns the name of the
current element. The code will look
| | 02:02 | like this, if (item.name() has a value of
location and then put in a pair of
| | 02:11 | braces and then I am going to return the
label attributes value at uppercase
| | 02:16 | like this, return item.@label.toUppercase.
Put in an else clause and in the
| | 02:30 | else clause we are going to assume that instead
of the location we got a child
| | 02:33 | element or the photo and so here we will
return the item label intact.
| | 02:40 | Now go down to the Tree control within
the panel, remove the labelField
| | 02:45 | property, we are not going to use that
anymore and instead put in a
| | 02:49 | labelFunction. You pass in the name of the
function that you want to call; you
| | 02:57 | are not actually calling the function at
this point, you are just passing a
| | 03:01 | reference to it to the Tree control and
then it's up to the Tree control to
| | 03:05 | actually call the function whenever it's
needed. So I will pass in the name of
| | 03:09 | the function which I named getTreeLabel;
make sure you spell this correctly, it
| | 03:16 | is highly case sensitive. Save your changes
and run the application and this
| | 03:22 | time when you present the Tree control you
should see that the locations are
| | 03:26 | uppercased but the labels for the child nodes
that is for the photos, are their
| | 03:31 | original mixed case. So you can see that
the labelFunction is working.
| | 03:36 | Now whenever you use a labelFunction, it's
sometimes instructive just to put a
| | 03:40 | trace statement and then see how often it's
being called. So I am going to go
| | 03:44 | back to the function getTreeLabel and I
am going to add a trace statement and
| | 03:49 | each time the function is called I am
going to output a value to the Flex
| | 03:52 | Builder console. It will be concatenated
string that starts off with a literal
| | 03:56 | value of Formatting and then we will output
item.@label. Save your changes and
| | 04:05 | this time run the application in Debug mode.
| | 04:09 | As the application starts up and starts
rendering the various nodes of the
| | 04:13 | Tree, in the console in Flex Builder, in
the background you should see the
| | 04:18 | trace output happening. Now open one of the
parent nodes and you should see the
| | 04:24 | trace method happening again; close the
node and you will see it happening
| | 04:28 | again, open and so on.
| | 04:31 | So what you will see is that this function
is being called a lot. The guideline
| | 04:35 | for a labelFunction is very simple, keep
it short, don't do anything complex in
| | 04:41 | the labelFunction, keep it to just one
or two lines of very simple, very
| | 04:45 | concise code that gets the data, formats
it and returns it as a string and this
| | 04:51 | allows you to customize the appearance of
your Tree control and the labels that
| | 04:55 | it uses for its various nodes.
| | Collapse this transcript |
| Using graphical skins with Tree controls| 00:00 | In this video, I'm going to describe the
use of custom graphical skins that you
| | 00:04 | can use to replace the default folder and
document graphics that are used in a
| | 00:08 | Tree Control. For this demonstration,
I'll use an application named
| | 00:12 | TreeSkins.mxml.
| | 00:14 | This is the same application I've been working
on in the previous videos. It
| | 00:19 | currently opens the XML file, retrieves
data and applies it as the data
| | 00:24 | provider for a Tree Control. Let's take another
close look at the Tree Control.
| | 00:30 | When you first create a Tree Control,
regardless of whatever kind of data
| | 00:33 | you're actually displaying, the branches
that's the parents nodes, that have
| | 00:37 | child nodes display folders.
| | 00:40 | There are two graphics associated with each
parent note, a Closed folder and an
| | 00:45 | Open folder and then the child nodes knows
as Leaves display a document. Now,
| | 00:52 | if your data doesn't consists of folders
and documents, you can create your own
| | 00:56 | custom graphics and apply them as graphical
skins. I've already created a few
| | 01:01 | skins that we can try out.
| | 01:03 | I've placed them in the Skins folder under
the Source Root. I'm going to open
| | 01:08 | one of them now in Fireworks. Notice that
the graphical skin is very small.
| | 01:14 | I've created my graphical skins for the
Tree Control using dimensions of 16
| | 01:18 | pixel square. Notice that Fireworks shows
you the size of the graphic that's
| | 01:23 | currently displaying.
| | 01:24 | I've created two icons for the folder, one
for its open state and one for its
| | 01:29 | closed stated and then I've also created
icon for the leaf that's for each
| | 01:34 | photo. That's again that same size, 16 pixelsx16
pixels. So, I'm going to close
| | 01:41 | Fireworks and go back to the code. In order
to use a graphical skin, you create
| | 01:47 | Style Embedding code.
| | 01:49 | Now, you can create this code yourself
or as I showed you in the previous
| | 01:53 | chapter, you can use flexible import capability
to generate the required style
| | 01:59 | code. I'm going to do the latter. I'll go
to the Menu and select File, Import,
| | 02:06 | Skin Artwork. Now, when I demonstrated this
capability in an earlier chapter, I
| | 02:12 | was working from a SWC file generated in Flash.
| | 02:15 | This time, I'm working from a set of Bitmap
images that are in a simple folder.
| | 02:20 | So, I select the option Import Skins
from folder or images. Then you'll
| | 02:25 | navigate to the Skins folder under the
Source Root of the current project,
| | 02:29 | which I've already selected. Down at the
bottom of the Wizard, you set the
| | 02:34 | option for how you want to create
the skins style roots.
| | 02:37 | You always create them in an external Style
Sheet and here I'm creating a new
| | 02:42 | Style Sheet file named skins.css. I'm
going to apply the styles to the
| | 02:47 | application TreeSkins.mxml. Click Next, so
there are three graphic files in the
| | 02:55 | selected folder. I'm going to check them
all by clicking the Check All button
| | 03:01 | and then I need to indicate explicitly what
kind of Style Selector I'm going to
| | 03:05 | use and what aspect of that Style Selector
I'm going to apply the skin to.
| | 03:10 | Let's start with the icon_location_closed_gif
file. Set the Style Selector to
| | 03:16 | Tree, make sure that you spelled correctly
with an uppercase T, then pull down
| | 03:21 | the list of available parts of skins and
you'll the various icons that are part
| | 03:27 | of the Tree Control displayed.
Select folderClosedIcon.
| | 03:29 | Now, repeat these steps for each of the other
images. Set the Style Selector to
| | 03:37 | Tree, pull down the list and for the icon_location_open.gif
file, select
| | 03:44 | folderOpenIcon and once again, for the third
one set Style Selector to Tree and
| | 03:51 | the skin part for this one
will be defaultLeafIcon.
| | 03:55 | That's it, click the Finish button and
Flex Builder will take the following
| | 04:00 | steps. First of all, it creates a new file
called skins.css, let's take a look
| | 04:06 | at the code generated. For each icon skin,
it embeds the graphic as a part of
| | 04:12 | the application using the Embed Compiler
Directive. The source actually points
| | 04:16 | at the actual location of the graphic file.
| | 04:20 | Then in the application file, ThreeSkins.mxml,
you find at the bottom of the
| | 04:25 | application a new style tack has been created
with the source attribute. Now,
| | 04:30 | my preferences to put my style declarations
up at the top, so I'm going to cut
| | 04:34 | that declaration to the clipboard, then
go back up toward the top of the
| | 04:39 | application and I always place my style
declarations after my script section.
| | 04:44 | That's just the convention I typically follow,
then I'll save the changes and
| | 04:49 | run the application. You should see that
the different nodes for each location
| | 04:56 | display the Folder Closed icon, open the
icon and you'll see that it switches
| | 05:02 | to the open graphic which has the little
lights on and the buildings and each
| | 05:07 | of the photo nodes is displaying the
appropriate graphic for that node.
| | 05:11 | So, that's a look at how to reskin a Tree
Control, how to provide custom
| | 05:16 | graphics that represent the type of data
that you're representing in the tree
| | 05:20 | rather than the document and photo graphics
that the Tree Control uses by default.
| | Collapse this transcript |
| Handling Tree events| 00:00 | In this video, I'm going to describe the
use of events that are dispatched by
| | 00:04 | the Tree Control as these are navigates
and selects nodes from between. For
| | 00:09 | this demonstration, I'll use an application
named TreeEvents.mxml, this is the
| | 00:15 | same application I've been working
on throughout this chapter.
| | 00:18 | I'm representing XML formatted data in a
visual Tree Control which allows the
| | 00:22 | users to select from any level of the XML
and I've already implemented the
| | 00:26 | custom skinning graphics that represent the
different nodes. Now, when the user
| | 00:33 | selects any item from a Tree Control,
you'll get an event named Change.
| | 00:37 | When the Change event occurs, you can
react by getting a reference to the
| | 00:41 | underlying data of the Tree selected node.
Then you can use that data and
| | 00:45 | represent it visually, store it or do anything
else you want. I'm going to
| | 00:49 | start this demonstration by creating
a new bindable variable.
| | 00:53 | If you're following along in the exercises,
you can open TreeEvents.mxml and
| | 00:57 | add a new bindable variable within the
script section named xPhoto. This is
| | 01:03 | going to contain a reference to the currently
selected XML node for the
| | 01:07 | currently selected visual node of
the Tree. Data type it as XML.
| | 01:12 | Now, the next step is to create an Event
Handler function. As I mentioned, the
| | 01:17 | event is going to be dispatched when the
user selects a node is named Change.
| | 01:22 | Create a new private function named changeHandler
and data type its event
| | 01:28 | argument as ListEvent and as with all Event
Handler functions, we turn void.
| | 01:36 | Now, the next step within the Event Handler
function is to get a reference to
| | 01:40 | the currently selected XML node. Declare
a new variable named selectedXML, data
| | 01:46 | typed as XML and get its reference using
this expression, event.target which
| | 01:53 | currently references the Tree Control,
.selectedItem as XML.
| | 02:00 | Now, before I go any further with the code
of this function, going to do a
| | 02:03 | little bit debugging and tracing, so I
can see what kind of node is being
| | 02:07 | selected. Add a call to the trace function
and add a literal string of "You
| | 02:13 | selected a" close the quote, add a concatenation
operator, a + and then trace
| | 02:20 | the name of the currently selected
node, selectedXML.name.
| | 02:26 | Now, go down to the Tree Control within the
first panel, add an attribute based
| | 02:30 | change Event Listener and call the changeHandler
function passing an event
| | 02:35 | object. Now, you're ready to do a little
bit of debugging and tracing. Save and
| | 02:41 | run the application in debug mode, arrange
your browser window that's
| | 02:45 | displaying the application so that you
can also see the counsel in the background.
| | 02:50 | Then go to the tree and click on one of
the parent nodes. You should see the
| | 02:53 | counsel show a traced output of You selected
a location. Now, open that node
| | 02:59 | and select one of its child objects and
you should see the trace output, You
| | 03:03 | selected a photo. Each time you select another
photo node, you should see the
| | 03:07 | same message and if you go back to the parent
node, you should see the output,
| | 03:12 | You selected a location.
| | 03:14 | So, now you know that you're correctly detecting
whether you're on the location
| | 03:18 | or the photo element. Now, the next step
is to put in a conditional clause that
| | 03:23 | decides whether to save the selected XML
object as xPhoto and you're only going
| | 03:28 | to do that if in fact, you got a photo
from what the user selected.
| | 03:32 | So, add a conditional clause after the trace
statement and use this syntax. If
| | 03:38 | selectedXML.name has a value of photo and
then within that conditional clause,
| | 03:47 | assign the value of xPhoto from selectedXML.
Now, if the user selected a parent
| | 03:55 | node that is a location, you don't want
to display a photo in that case. So,
| | 04:00 | put in an else clause and set the
value of xPhoto to null.
| | 04:05 | Now, it's time to add some visual controls
to show the result. Go to the panel
| | 04:10 | at the bottom of the application with the
title of Photo Detail, add an Image
| | 04:15 | Control and set its source property using
a combination of a literal string
| | 04:19 | pointing to the location of your graphic
file that will be assets/ and then a
| | 04:25 | binding expression pointing at the source
attribute of the xPhoto object.
| | 04:30 | That will be xPhoto.@source. Also, in order
to make sure that the Image Control
| | 04:37 | only appears when it has something to display,
set its visible property using a
| | 04:41 | binding expression of xPhoto not equal to
null. So, now the image control will
| | 04:47 | only appear if in fact there's something
selected from the Tree.
| | 04:51 | We'd also like to show the label of the
selected photo, go to the panel
| | 04:56 | containers, start tack and add a status property
using a binding expression of
| | 05:01 | xPhoto.@label, these are e-forex expressions
that are extracting the
| | 05:07 | appropriate attribute for each purpose.
The status property of the panel is a
| | 05:11 | simple string that appears to
the right of its title.
| | 05:14 | The source property is a string also and
it's going to be loading the photo at
| | 05:17 | runtime from the local disk or from the
web when you deploy the application.
| | 05:22 | Save your changes and run the application
in normal mode this time. Notice now
| | 05:28 | that when you click on an item which represents
the location, nothing happens.
| | 05:31 | But, when you open up the Tree and select
the photo node, the actual selected
| | 05:36 | photo is displayed in the right panel.
You now have a good photo browsing
| | 05:40 | application that you can use that displays
the contents of the XML file using
| | 05:44 | the Tree Control and displays the selected
detail using a standard Image Control.
| | Collapse this transcript |
| Using the MenuBar control| 00:00 | In this video I am going to describe the
use of the Menu Bar control. The Menu
| | 00:05 | Bar control is very similar to the Tree control
in that it's designed to use an
| | 00:09 | XML formated data provider so that it
can display hierarchical data.
| | 00:13 | For this demonstration I will use the Application
UseMenuBar.mxml. If you are
| | 00:18 | following along with the exercises you
can open this application now. This
| | 00:22 | application starts off in a very similar
fashion to the ones I have been
| | 00:25 | working on in this chapter. It retrieves
the same XML data that contains
| | 00:29 | location and photo information and saves
it as a variable named xLocations and
| | 00:34 | then extracts data to an XML list.
| | 00:38 | Now when use a Menu Bar typically you put
it at the top of the application. So
| | 00:42 | I have created an ApplicationControlBar
container with it's dock property set
| | 00:46 | to true. I will place the cursor between
the tags of the ApplicationControlBar
| | 00:51 | and then declare a MenuBar and I will give
it an id of myMenu and then I will
| | 00:56 | set it's dataProvider using a binding expression
to the xLocations XML list.
| | 01:02 | Close the tag with a slash greater than(/>)
and then as with the Tree control I
| | 01:07 | have to specify for the MenuBar which attribute
or element should be used to
| | 01:12 | provide the label for each node of the menu.
I will use labelField attribute
| | 01:17 | this time rather than labelFunction and
I will pass in the E4X expression at
| | 01:22 | label. Meaning that I want to use the label
attribute of each XML element to
| | 01:27 | provide the label for it's equivalent menu node.
| | 01:29 | I will save the changes and run the application
and you should see the each
| | 01:34 | node in the XML list that I used as the
dataProvider creates a top level menu
| | 01:39 | and then the child elements of that XML node
are used as the sub menu. So I now
| | 01:44 | have four items on the menu and each has
it's own sub menu. Just as with the
| | 01:49 | Tree control you have the ability to customize
the labels on each of the menu
| | 01:53 | nodes using the label function property
and a custom ActionScript function,
| | 01:58 | that returns a formated string.
| | 01:59 | You also have the ability to provide skinning
and custom item renderers just
| | 02:03 | like you would in a List control. Now in
the next video and the last in this
| | 02:07 | chapter, I will show you how to handle
the events of the MenuBar and react
| | 02:11 | when the user has selected
an item from the menu.
| | Collapse this transcript |
| Handling MenuBar events| 00:00 | In this video I am going to describe how
to listen for an event that occurs
| | 00:04 | when the user select an item from the menu
bar, and how to get information
| | 00:08 | about that event and react accordingly.
| | 00:11 | For this demonstration I will use the Application,
MenuBarEvents.mxml. If you
| | 00:15 | are following along with the exercises, you
can open this file now. This is the
| | 00:20 | same application that I worked on in the
previous video. It uses an XML file to
| | 00:25 | populate a menu bar which is wrapped inside
an ApplicationControlBar and docked
| | 00:30 | to the top of the application. As the user
navigates the menu bar, the control
| | 00:35 | dispatches an event named item click. In
contrast to the tree control, with the
| | 00:40 | menu bar, the item click event only happens
when you are on a terminal leaf of
| | 00:44 | the external structure.
| | 00:46 | So for example, when the user selects London,
as I am doing here, an item click
| | 00:51 | event does not happen. But when the user
select an item under London, such as
| | 00:55 | London Bridge, then the event is dispatched.
So here are the steps I will
| | 01:00 | follow to listen for the event and react.
Go to the Script section and add a
| | 01:06 | new private function, named itemClickHandler.
When the item click event is
| | 01:12 | dispatched by the menu bar, the event object
is data typed as a class named
| | 01:16 | MenuEvent. The MenuEvent class is a member
of a package that must be imported,
| | 01:23 | in order for it's classes to be used. So
when you select MenuEvent from the
| | 01:27 | list of available classes, Flex photo should
add an import statement for you.
| | 01:34 | Within the event handler function, you
can get a reference to the selected
| | 01:37 | item, using the item property of the event
object. So to clear a variable name
| | 01:43 | selectedMenu, data typed as XML, and get
its reference from event.item as XML.
| | 01:54 | Add a call to the trace function, and
type in a literal string of "You
| | 01:58 | Selected, and then can catenate
that to an E4X expression of
| | 02:06 | selectedMenu.@lable. And this will allow
you to trace and verify what you are
| | 02:13 | getting from the selection on the menu. Now
go down to the MenuBar control, and
| | 02:18 | add an event listener that calls that function.
The event listener looks like
| | 02:22 | this. ItemClick = "itemClickHandler (event)"and
pass the event object. Now run
| | 02:29 | the application in debug mode. Arrange
the browser that's displaying the
| | 02:34 | application, so that you can see the console
view of Flex Builder in the
| | 02:37 | background. Click on the top level item,
and you will notice that you don't get
| | 02:41 | any console output. But now click on the
item from the sub menu and you should
| | 02:47 | see a trace message in the console indicating
which item you selected.
| | 02:52 | So now you know that you are correctly getting
a reference to the XML object
| | 02:56 | underlying the selected menu item. Close
the browser and return to Flex
| | 03:00 | Builder, go back to the itemClickHandler
function. Now the only remaining step
| | 03:06 | for this application is to save the selected
menu object as the xPhoto object
| | 03:12 | that was already declared. All the
code to create the visual detail
| | 03:17 | presentation is already in this application.
So I will use this syntax. Xphoto
| | 03:23 | = selectedMenu. I am taking the XML object,
I am saving it to this predeclared
| | 03:29 | xPhoto variable, and then the visual output
at the bottom of the application
| | 03:34 | within the panel, uses an image control
to display the photo itself, and a
| | 03:39 | status property of the panel to display
the label. This part of the code is
| | 03:44 | exactly the same as for the version of the
application that used a tree control
| | 03:48 | to navigate the XML content.
| | 03:51 | Save your changes and run the application
this time in normal mode. Try
| | 03:59 | selecting an item from the menu, I will
choose New Orleans and Riverboat, and
| | 04:04 | you should see the selected photo and its
label displayed in the panel. So this
| | 04:10 | is how we use a menu bar, and detect it's
events. We use the item click event,
| | 04:15 | which generates an event object data typed
as MenuEvent. The event object has
| | 04:20 | an item property which we can use to get
a reference to the selected XML, and
| | 04:24 | then we can get whatever values we want out
of the XML, displaying information
| | 04:29 | visually, or using that information to
navigate around the application as needed.
| | Collapse this transcript |
|
|
7. Integrating Flex with ColdFusionInstalling ColdFusion on Windows| 00:00 | In this chapter of the video series I am
going to describe how to integrate
| | 00:03 | your Flex applications with Adobe ColdFusion.
ColdFusion is a rapid application
| | 00:08 | server platform that runs on multiple operating
systems. It's based in JAVA in
| | 00:13 | the background but developers use a proprietary
language called ColdFusion mark
| | 00:17 | up language, to write the server side code,
and integrate with server side
| | 00:20 | databases. In this video I am going to describe
how to install ColdFusion on
| | 00:24 | Windows, and then in the next video I will
describe how to install it on the Mac.
| | 00:28 | You can download ColdFusion for free from
the Adobe website at this URL,
| | 00:32 | www.adobe.com/products/coldfusion. From this
page click the download free trial
| | 00:40 | link, and after signing in with an Adobe
ID which is free, you will come to
| | 00:45 | this download screen. SELECT the appropriate
version of ColdFusion for your
| | 00:49 | operating system. If you are developing
on the Windows platform, you'll
| | 00:52 | probably want this version, English/Windows,
or if you have 64-bit Windows,
| | 00:57 | there is a version for that as well. There
are also separate versions for Mac
| | 01:00 | OS X. Once again for 32 or 64-bit installation.
Now probably I am only going to
| | 01:06 | be demonstrating the installation of ColdFusion
on Windows, and the Mac in this
| | 01:09 | video series. The instructions I am going
to give you should work on any of the
| | 01:13 | other supported platforms as well.
| | 01:16 | After downloading the ColdFusion, start up
the installation. Click OK from the
| | 01:19 | first screen, and after a few moments you
will see an informational dialog.
| | 01:24 | Click Next, take a look through the License
Agreement, and if you accept it
| | 01:28 | ,click the appropriate button ,and click
Next again. Then you'll come to the
| | 01:31 | Serial Number screen. If this is your first
time using ColdFusion, I recommend
| | 01:35 | you can figure it as the Developer Edition.
This version of ColdFusion requires
| | 01:39 | no serial number, and you can use it
as long as you want to on your own
| | 01:43 | development system. You will be able to
develop and test with it, but this
| | 01:47 | version won't be usable for deployment.
| | 01:49 | To deploy the applications you build with
ColdFusion, you will even need to go
| | 01:52 | get your own copy of the ColdFusion software,
or rent website space at an ISP,
| | 01:57 | that supports ColdFusion. On the Next
screen you are asked for the
| | 02:01 | configuration. Again, if this is your first
time using ColdFusion, choose the
| | 02:05 | Server configuration. This installs ColdFusion
as a complete self contained
| | 02:09 | server, including an underlined application
server named Jrun, and a
| | 02:13 | development Web server that you can use if
you like. On the Next screen you are
| | 02:16 | prompted for the various services that you
want to install. If you are working
| | 02:20 | on windows, you will see an option for .NET
integration Services, and for all
| | 02:24 | platforms you also see an option to include
Life Cycle Data Services ES. I
| | 02:29 | recommend that you leave all these options
selected, and then click Next, and
| | 02:33 | then select it directly into which you
will be installing ColdFusion. The
| | 02:36 | Default is C:/ColdFusion8, I will be accepting
that option, and throughout the
| | 02:42 | exercises in this chapter, I will be referring
to that as the installation
| | 02:46 | folder. Click Next, go through the options
for Life Cycle Data Services ES,
| | 02:51 | including reviewing the License Agreement,
and just as with ColdFusion itself,
| | 02:55 | there is a free version of Life Cycle Data
Services. This is called the express
| | 02:59 | edition, and it can be used for free without
any serial number or registration.
| | 03:03 | There are some significant limitations on
Life Cycle Data Services Express, and
| | 03:07 | it's worth reading through the
license for this product.
| | 03:10 | In the next screen you are asked which Web
Server you would like to use. I am
| | 03:14 | going to be demonstrating the use of ColdFusion
with the built-in Web server.
| | 03:18 | If you are working on windows, and you
already have Internet information
| | 03:21 | services or IIF installed, you will be able
to select the connector for that
| | 03:25 | Web server. But if you don't have the Web
server installed, I recommend the
| | 03:28 | built-in Web server. Click Next, and
now you are prompted for password
| | 03:33 | information. Type in any password you like.
I am typing just the word password,
| | 03:38 | and click Next again, and on the next screen
you are prompted for Enabling RDS.
| | 03:43 | RDS stands for the Remote Development Service,
and it's a service that allows
| | 03:47 | you to connect to the ColdFusion server for
debugging, data source information,
| | 03:52 | and a lot of other features.
| | 03:54 | If you're going to work through all of
these exercises in this and the next
| | 03:56 | chapter of this video series, you will definitely
need RDS to connect the Flex
| | 04:01 | builder from ColdFusion. So Enable RDS, and
once again Enter a password. Click
| | 04:08 | Next again, review the summary information,
and then click Install. The
| | 04:13 | installation process takes a few minutes,
but at the end of the process, you
| | 04:17 | are prompted to configure the ColdFusion
server. The installation happens in
| | 04:22 | two major steps. The primary installation
may take up to 10 to 15 minutes, but
| | 04:26 | then one's the primary installation is completed,
you will be prompted to go
| | 04:30 | into a configuration and administration
screen. Once you see this screen
| | 04:34 | labeled installation complete, you will
be ready to go to the configuration
| | 04:38 | wizard. Make a note that in the installation
screen it shows you the primary
| | 04:42 | URL of the ColdFusion administrator, which
is a Web application that you use to
| | 04:46 | configure the ColdFusion server.
| | 04:48 | I recommend that you leave the Launch Configuration
wizard option selected, and
| | 04:52 | then click Done. That will result in navigating
to a Web browser and opening
| | 04:57 | the Configuration Wizard. You will be prompted
for the ColdFusion administrator
| | 05:02 | password that you registered during the
installation process. Enter the
| | 05:05 | password, and click Login, and then it will
take a few more minutes to complete
| | 05:10 | the configuration process. I recommend that
you leave the browser undisturbed
| | 05:14 | during this process, and it may take up
to three or four minutes to complete.
| | 05:19 | When the configuration process is complete,
you will be prompted to click OK,
| | 05:22 | to open the ColdFusion Administrator. Click
the OK button, and the ColdFusion
| | 05:27 | Administrator Interphase appears. Again,
this is a Web application that allows
| | 05:31 | you to configure and manage your ColdFusion
server. If you would like to be
| | 05:34 | able to get back to the screen easily from
your browser window, Bookmark or Add
| | 05:38 | a Favorite in Internet Explorer. So I am
going to select Bookmark, Bookmark
| | 05:43 | This Page and click OK, and anytime I like,
I can now get back to this screen.
| | 05:48 | So that's to look how to install ColdFusion8
on Windows. In the next video I
| | 05:53 | will show how to do the same thing on the Mac.
| | Collapse this transcript |
| Installing ColdFusion on Mac OS X| 00:00 | In this video, I am going to describe the
steps for installing ColdFusion 8 on
| | 00:04 | Mac OS X. As I described in the previous
video, where I described how to
| | 00:08 | install ColdFusion on Windows, you can
download ColdFusion from the Adobe
| | 00:12 | website, starting at the URL I am
displaying on the screen now
| | 00:15 | http://www.adobe.com/products/coldfusion
From this page, Click the Download
| | 00:24 | Free Trial link. You will need to login with
a free Adobe ID, and then download
| | 00:28 | the version of ColdFusion for Mac OS X.
| | 00:30 | I have already downloaded the file, which
comes to you as a zip file, and when
| | 00:35 | you extract the zip file, you'll get a ColdFusion
8 Installer. Double-click on
| | 00:39 | the Installer to start it up, and the first
screen you will see indicates that
| | 00:43 | you are installing ColdFusion using English.
Click OK to go to the next screen.
| | 00:48 | On the Informational Introduction Screen,
Click Next, review the License
| | 00:52 | Agreement and if you accept it, select the
appropriate Radio button and click Next again.
| | 00:57 | ColdFusion 8 can be installed as the
Developer Edition. This version of
| | 01:01 | ColdFusion can be installed on any number
of systems and used for as long as
| | 01:05 | you want. It's limited in terms of how
many concurrent connections to the
| | 01:08 | server you can use. But you can use it
for developing and testing without
| | 01:11 | paying any license fee.
| | 01:13 | Click the Next button, and on the Installer
Configuration Screen, select Server
| | 01:17 | Configuration. This means that you are installing
ColdFusion with an underlying
| | 01:21 | Jrun application server and if you want to
use it a built-in web server. Click
| | 01:26 | the Next button, and then confirm that
you don't already have ColdFusion
| | 01:30 | installed in the Server Configuration
and Click Next again.
| | 01:33 | On this screen, you select which sub-components
you want to install. There are
| | 01:37 | fewer options on Mac OS X than there are
in Windows. For example there is no
| | 01:41 | .NET integrations since the .NET framework
isn't available on the Mac.
| | 01:45 | However, you can choose as many items here
as you like. I recommend that you
| | 01:49 | deselect the options start ColdFusion on
system in it, and then at the end of
| | 01:53 | the installation process, I'll show you
how to start up ColdFusion manually.
| | 01:57 | I do recommend that you install the ColdFusion
8 Documentation and the Adobe
| | 02:01 | LiveCycle Data Services ES optional install.
Click Next. Now indicate where you
| | 02:06 | want to install ColdFusion. On Mac, the
default installation folder is
| | 02:11 | Applications/ColdFusion 8, and I recommend
that you use the default. Click Next.
| | 02:16 | On the next couple of screens, review
the options for the LiveCycle Data
| | 02:19 | Services if you selected that option, and
as with ColdFusion itself, you can
| | 02:24 | leave this Serial Number blank. And that
installs a trial version of LiveCycle
| | 02:28 | Data Services. After 120 days, it becomes
an express edition which can be used freely.
| | 02:35 | Click Next and indicate whether you need
to migrate settings from a previous
| | 02:38 | version of ColdFusion. I haven't installed
ColdFusion on this system before. So
| | 02:42 | I will leave the option set
to No, and Click Next.
| | 02:45 | Now indicate which Web Server you want to
use. I recommend for these exercises
| | 02:50 | that you use the built-In Web Server.
That will allow you to follow the
| | 02:54 | exercises and use the same path and port
numbers that I am using. So I have
| | 02:58 | selected Built-In Web Server and Click Next
again, and now I am prompted for
| | 03:02 | password information. You need to enter
two passwords. The first password is
| | 03:07 | for the ColdFusion Administrator. A web
application that allows you to
| | 03:11 | configure and manage your ColdFusion
installation.
| | 03:14 | On the next screen, Enable RDS. RDS, the
remote development service, allows you
| | 03:19 | to connect to ColdFusion from Flex Builder.
So that you can see the structure
| | 03:23 | of your data sources and other useful information.
Once again you'll need to
| | 03:29 | enter a password twice.
| | 03:31 | Here is the summary screen that tells you
about all the selections you have
| | 03:34 | made. Click the Install button to run
the installation. The primary
| | 03:38 | installation takes quite a few minutes,
but when it's completed, you will be
| | 03:42 | prompted to go into a Web Browser. When
you get to the Installation Complete
| | 03:46 | screen, you are prompted to launch the configuration
wizard. A browser based
| | 03:50 | application that completes the configuration
of the ColdFusion install.
| | 03:53 | Before you Click the button to continue,
note the URL on the screen that
| | 03:58 | indicates where you can address the ColdFusion
Administrator. Click the Done
| | 04:02 | button to continue, and after a moment
the ColdFusion Configuration and
| | 04:06 | Settings Migration Wizard opens in a browser.
You will need to enter the
| | 04:10 | ColdFusion Administrator password that
you put in during the installation
| | 04:14 | process. Then Click Log in.
| | 04:18 | On Mac OS X, it takes just a few moments
to complete the configuration, and
| | 04:22 | when the process is done, you will see this
screen that prompts you to Click OK
| | 04:25 | to open the ColdFusion Administrator.
| | 04:27 | Click the OK button and the ColdFusion Administrator
Application opens. Now,
| | 04:32 | before I conclude this video, I am going
to show you how to stop and start
| | 04:35 | ColdFusion on Mac OS X. I am going to
close the browser and then I will
| | 04:40 | navigate to the Macintosh hard disk, from
there to Applications and from there
| | 04:44 | to the ColdFusion 8 Folder that was
created during the installation.
| | 04:48 | The Mac OS X version of ColdFusion includes
this application, the ColdFusion
| | 04:52 | Launcher. Open the Application, and you
will see that it has three buttons.
| | 04:57 | Start ColdFusion 8, Stop ColdFusion 8 and
Web Server Connector Utility. If
| | 05:02 | during the installation, you indicated
that you didn't want ColdFusion to
| | 05:05 | launch upon system initialization, you
will need to use this application to
| | 05:09 | start ColdFusion each time you want to do
a development and testing with it.
| | 05:13 | So I am going to stop ColdFusion by Clicking
the Stop button and it takes just
| | 05:16 | a few moments for the server to stop in
the background. Once the process is
| | 05:20 | completed, you will see this message, ColdFusion
8 has been stopped. Then you
| | 05:24 | can Click the Start button again, and
the ColdFusion will startup again.
| | 05:28 | Once you see a message indicating that ColdFusion
has been correctly started,
| | 05:32 | you can once again navigate to the ColdFusion
Administrator which you will find
| | 05:36 | at http://localhost:8500/cfide/administrator.
Each time you go to the
| | 05:49 | administrator, you will need to enter your
administrator password which you've
| | 05:52 | created during the installation process.
Then you will be able to work with all
| | 05:58 | the administrative options setting up data
sources and other configurations.
| | Collapse this transcript |
| Installing and configuring a sample database| 00:00 | In this video, I am going to describe how
to import a database into ColdFusion
| | 00:04 | that you will be able to use throughout
the exercises about integration of
| | 00:07 | ColdFusion and Flex. If you are following
along with the exercises, start off
| | 00:12 | in the Exercises folder. Navigate to the
Assets folder and from there to
| | 00:17 | ColdFusion. You will find a folder there
named Flex3btb. This contains a
| | 00:21 | variety of files including files that you
are about to use to create a database
| | 00:25 | and also some ColdFusion codes that
you will be calling from Flex.
| | 00:29 | Copy that folder to the clipboard. Now
navigate to the web root of your
| | 00:34 | ColdFusion server. On windows the
ColdFusion root by default is
| | 00:38 | c:\ColdFusion8\wwwroot on Mac
OS X the location is
| | 00:45 | \applications\ColdFusion8\wwwroot. This
assumes that you have installed
| | 00:51 | ColdFusion using the server configuration
and the development web server. If
| | 00:55 | you have another configuration, you will
need to adapt these instructions as
| | 00:59 | needed. Now, Paste that Flex3btb folder underneath
the www root folder and now
| | 01:06 | you are ready to create a data source
to point to the data base.
| | 01:10 | Go to the ColdFusion Administration, make
sure that you have your ColdFusion
| | 01:14 | Server turned on and then login to the ColdFusion
Administration Login page. In
| | 01:19 | the ColdFusion Administration interface
go to the Data Sources section which
| | 01:23 | you will find under the Data & Services
section of the menu. Now add the Data
| | 01:28 | Source Name. Set the Data Source
name as you see on the screen.
| | 01:32 | Flex3btbContacts and set the Driver type
to Apache Derby Embedded. This is
| | 01:39 | JAVA-based database that is used in
ColdFusion for sample databases.
| | 01:43 | It's compatible with all of the operating
systems on which ColdFusion is
| | 01:47 | delivered including Windows and the Mac.
Click the Add button and then set the
| | 01:52 | database folder using the flex3btb folder
as the root. For example on Windows
| | 01:58 | it's starts of with c:\ColdFusion8wwwrootflex3btb
and on Mac it would be
| | 02:04 | c:\application\ColdFusion8\wwwroot\flex3btb
and then add a new contacts folder
| | 02:12 | at the end.
| | 02:13 | This folder doesn't already exist.
It's about to be created by the
| | 02:16 | Administrator. Select the option, Create
Database and then click Submit and
| | 02:23 | after a couple of seconds you should see
the message data source updated
| | 02:26 | successfully. And if you navigate back to
the web root to the flex3btb folder
| | 02:31 | you should find this folder contacts which
has now been populated with number
| | 02:35 | of files that are the database.
| | 02:38 | Okay, now you are ready to actually create
the database table and data. With in
| | 02:42 | this flex3btb folder, there is a subfolder
named database, which contains .CFM
| | 02:48 | and a .CFC file. You are going to execute
the CFM file which in turn will call
| | 02:52 | functions of the CFC file. Go back to the
browser and navigate to the following
| | 02:57 | URL. 127.0.0.1:8500\flex3btb, you should
see a listing of the folders under
| | 03:07 | that folder. Click in to the database link
and you will find the CFC and CFM
| | 03:12 | file and click on CreateDatabase.cfm. It
takes just a moment to execute the
| | 03:18 | code and create the table.
| | 03:20 | You should now be ready to move on to
the rest of this chapter and start
| | 03:22 | learning about integration of Flex
applications with ColdFusion.
| | Collapse this transcript |
| Installing CFEclipse| 00:00 | In this video I am going to describe how
to install CFEclipse, a free plug-in
| | 00:04 | for the Eclipse environment that allows
you to easily Create and Edit
| | 00:08 | ColdFusion code. CFEclipse is completely
free and can be downloaded from
| | 00:13 | www.cfeclipse.org. You can install it from
directly within the Flex Builder
| | 00:19 | environment, whether you have installed
Flex Builder using the standalone or
| | 00:23 | the plug-in architectures. To install CFEclipse
go to the Flex Builder Menu and
| | 00:27 | select Help SoftwareUpdates, Find and Install.
On the Feature Updates screen
| | 00:33 | select Search for new features
to install and click Next.
| | 00:36 | In the Updates Sites to visit screen you
might see CFEclipse item listed
| | 00:40 | already. This happens if you installed
the ColdFusion extensions for Flex
| | 00:45 | Builder, during the initial installation
of Flex Builder or if you install
| | 00:48 | those extensions later. If you do not see
the CFEclipse item there, follow these steps.
| | 00:54 | Click New Remote Site give your New Update
Site a name such as MyCFEclipse and
| | 01:00 | set the URL as follows www.cfeclipse.org/update,
now the error message you see
| | 01:10 | comes because Eclipse already knows that,
that URL is being used by another
| | 01:14 | update site and it won't let me enter it
twice. So, I'll Cancel out of this
| | 01:18 | dialog, but if you are able to click OK
that means you need to add eclipse to
| | 01:22 | your list of sites.
| | 01:24 | Next make sure that your CFEclipse site is
selected and click Finish. It takes
| | 01:29 | just a moment for eclipse to go out of
the site and check for available
| | 01:32 | updates. Open the tree of available items,
and then go to releases and you will
| | 01:38 | see that there is an item listed as CFEclipse.
The most recent version at the
| | 01:42 | time with this recording was 1.3.1.6. Select
the releases item and click Next.
| | 01:49 | Then reviewed the license agreement which
is based on the Eclipse Public
| | 01:53 | Licenses and if you accept it, select the
appropriate radio button and click
| | 01:57 | Next again. Finally click Finish.
| | 02:00 | On the high speed internet connection it
takes just a few moments to download
| | 02:03 | the CFEclipse code. You will then see a
Feature Verification screen that asks
| | 02:07 | you if you want to go ahead with the installation.
Click Install All if you
| | 02:11 | want to continue and after a few moments
the installations should be complete.
| | 02:16 | Whenever you install plug-in into the Eclipse
Environment you should restart
| | 02:19 | Flex Builder 3 and Eclipse. This ensures
that when you restart the application
| | 02:24 | you'll have all the features of the new
plug-in. So, I'll click Yes, and Flex
| | 02:29 | Builder closes and then restarts.
| | 02:32 | Now, in the next video I'll show you how
to create a new CFEclipse project that
| | 02:36 | points to the code in your
CodeFusion environment.
| | Collapse this transcript |
| Creating a CFEclipse project| 00:00 | In this video I am going to describe how
to create a CFEclipse project, that
| | 00:04 | allows you to navigate and modify your ColdFusion
code from within the Eclipse
| | 00:08 | and Flex Builder environment.
| | 00:10 | If you have been following along with the
exercises in this chapter, you have
| | 00:13 | already installed ColdFusion and created
a database and a data source and
| | 00:17 | copied code to the ColdFusion site.
| | 00:19 | Now from the Flex Builder Menu follow these
steps. From the Menu select File -
| | 00:24 | New - Other. From the dialog that appears
go to the CFEclipse section and open
| | 00:31 | it and select CFML Project. Then click
Next. Give the project a name of
| | 00:37 | flex3btbCF. So that will be the name of
the project for the ColdFusion code.
| | 00:44 | Deselect the option, use default location,
click the Browse button and then
| | 00:49 | navigate to the location of the flex3btb
folder under the ColdFusion webroot.
| | 00:54 | On Windows that will under C:\ColdFusion8\wwwroot\flex3btb;
on Mac that will be
| | 01:04 | under \Applications\ColdFusion8\wwwroot\flex3btb.
| | 01:12 | Click Finish. When prompted to open the
CFEclipse perspective, click Yes.
| | 01:17 | Now go to the Navigator view on the left
and open the project. You will see all
| | 01:22 | the folders within the project including
the database folder that contain the
| | 01:26 | files that created the database and a cfc
folders that contains a couple of other files.
| | 01:32 | Notice these other folders that are part
of this directory. This particular
| | 01:35 | directory and folder structure was created
in Dreamweaver and as a result it
| | 01:39 | has some additional directories that aren't
relevant to the world of Eclipse,
| | 01:43 | but that you will sometimes
see in a ColdFusion site.
| | 01:46 | Now open the file, PersonServiceTest.cfm.
This file calls a function of a
| | 01:52 | ColdFusion component called getPersonData.
It calls it twice and dumps the
| | 01:56 | results to the screen each time. The first
time the ColdFusion is called, it
| | 02:02 | executes a query and returns all of the data
from the person table was created
| | 02:06 | in our previous video.
| | 02:08 | The second time it uses a lastname property
to filter by a single character,
| | 02:12 | and as a result it returns only those records
for the lastname column of the
| | 02:16 | record starts with the letter f.
| | 02:18 | Now configure you project so that you can
easily browse to pages from within
| | 02:23 | Flex Builder. Go to the project root flex3btbcf,
right-click on the project
| | 02:29 | name or Ctrl+Click on the Mac
and select Edit URL.
| | 02:33 | Now enter the equivalent URL that will allow
you to browse to the root of this
| | 02:38 | project. It will be localhost:8500/flex3btb/
be sure to include the closing
| | 02:49 | slash (/), otherwise the browsing
won't work correctly.
| | 02:52 | Click OK and then click back on the PersonServiceTest.cfm
file. Now go to the
| | 02:59 | toolbar where you will see a couple of buttons
labeled 1 and 2. These buttons
| | 03:03 | will allow you to browse to the page
using one of the browsers.
| | 03:07 | Click the number 1 and you should successfully
navigate to the page and see all
| | 03:12 | of the data dumped out on the screen.
This is being executed using a
| | 03:15 | combination of a cf query and a cf dump tag.
| | 03:19 | Now scroll down to the bottom of the page
and you will see a second record set,
| | 03:22 | and in this record set only those records
where the last name starts with the
| | 03:26 | letter F are included.
| | 03:27 | So if you have that much working you are
now ready to integrate the ColdFusion
| | 03:31 | code with your Flex applications, and in
the next video I will describe how to
| | 03:36 | set up a Flex application that integrates
with the ColdFusion Server.
| | Collapse this transcript |
| Creating Flex/ColdFusion projects in Flex Builder| 00:00 | In this video, I am going to describe how
to create a Flex Builder project
| | 00:04 | that's associated with the ColdFusion Server.
When you create a Flex Project
| | 00:08 | that's associated with ColdFusion, you provide
information not only about where
| | 00:12 | you are storing your flex source code, but
also where your ColdFusion Server is
| | 00:16 | and how you are going to test your
application at runtime.
| | 00:19 | If you are following along with the exercises,
go to Flex Builder and create a
| | 00:22 | brand new project from scratch. From the
menu select File, New, Flex Project.
| | 00:29 | Set the project name as Chapter07Begin.
You can use the default project
| | 00:35 | location for the location of your source
code and leave the application type
| | 00:39 | set to Web application.
| | 00:41 | Now from the Application server type list
select ColdFusion. Leave the option
| | 00:46 | Use remote object access service selected
and then also select ColdFusion Flash
| | 00:50 | Remoting. Click Next, on this screen
you indicate the location of your
| | 00:55 | ColdFusion Server. The default settings are
for the server configuration known
| | 01:00 | here as the Standalone ColdFusion
installation type.
| | 01:03 | If you installed ColdFusion using the standard
settings, you will be able to
| | 01:06 | accept these default settings. On the
Mac, check to make sure that the
| | 01:10 | ColdFusion root is \applications\ColdFusion8
and check the same thing for the
| | 01:15 | Web root. The Root URL should be exactly
the same for either Windows or the
| | 01:20 | Mac, http://localhost:8500. Make sure that
your ColdFusion Server is running
| | 01:28 | and then click the Validate Configuration
button and you should see this
| | 01:31 | message at the top of the screen, The Web
root folder and root URL are valid.
| | 01:36 | The next setting is for the Output folder.
This is the location of the debug
| | 01:41 | version of your application. Notice that
when you create a flex project that's
| | 01:45 | associated with ColdFusion, the output folder
is placed under the web root. You
| | 01:49 | can place this folder anywhere you like within
the Web root and you can name it
| | 01:53 | anything you want. The default name is
the name of the project followed by -debug.
| | 01:58 | Now I will click the Next button. This is
the final configuration screen and
| | 02:02 | it's the same as the one you see with non-ColdFusion
projects. Set your main
| | 02:07 | application file as FlexWithColdFusion.mxml
and then click Finish. After a few
| | 02:14 | moments your project and application are
created. Now place the cursor inside
| | 02:19 | the application text and create a label and
set its text property to Hello from
| | 02:25 | ColdFusion. I am going to set the font
size of my label to 12 pixel, so it
| | 02:33 | looks nice and large on the screen and
also set the layout property of the
| | 02:37 | application to vertical. Save your changes.
| | 02:41 | Now each time you save your changes the
application is built as it always is,
| | 02:46 | but the bin-debug folder which is shown
here as a linked folder that's what
| | 02:50 | that little icon means, is actually a pointer
to the physical folder under your
| | 02:54 | ColdFusion Root, C:\ColdFusion8\wwwroot
and so on. So now when you test your
| | 03:01 | application, let's see what happens. I will
run the application in normal mode.
| | 03:06 | The browser opens and presents my application
with the label Hello from
| | 03:10 | ColdFusion and the location of the application
from which I am pulling it is
| | 03:14 | through the web server at localhost:8500.
| | 03:18 | This is particularly important when you
are working ColdFusion or other
| | 03:21 | application servers because that allows
you to download the application from
| | 03:25 | the web server at runtime rather than opening
it from the local disk and this
| | 03:29 | way you will see exactly the same behavior
during your testing as the users
| | 03:33 | will see when they are actually
using the application.
| | 03:35 | So now we have our entire working environment
set up and in the next set of
| | 03:39 | videos, I will show you how to use the
Remote Object Component of the Flex
| | 03:43 | Framework to make calls to ColdFusion
component functions.
| | Collapse this transcript |
| Calling CFC functions with RemoteObject | 00:00 | In this video, I am going to describe how
to use the Remote Object Component to
| | 00:04 | make calls to ColdFusion CFCs over the
web. A ColdFusion Component provide
| | 00:09 | services that you can call remotely. The
purpose of the remote object component
| | 00:13 | in the Flex Framework is to make these calls
using a Binary Protocol called AMF
| | 00:18 | or Action Message Format. This Binary Protocol
behaves in a similar fashion to
| | 00:23 | a web service call, but unlike web service
calls which use pure text to format
| | 00:27 | the requests and responses, the AMF format
being binary is much smaller and
| | 00:32 | faster. AMF is directly supported by ColdFusion
on the server and by the Flex
| | 00:38 | Framework on the client. So what is the
best way to make calls to ColdFusion
| | 00:42 | functionality from a Flex Application.
| | 00:44 | If you are following along with the exercises,
you have already installed and
| | 00:48 | tested a ColdFusion component called PersonService.cfc,
which you will find in
| | 00:53 | the flex3btbCF project, under the CFC folder.
This component contains a single
| | 00:58 | function called getPersonData. It executes
a query wrapped in a cfquery tag and
| | 01:04 | it has a conditional clause checking for
an argument named lastname. If the
| | 01:08 | argument is passed in then this query filters
for only rows that start with
| | 01:13 | whatever value you pass in and if not
passed in, it executes a query and
| | 01:16 | returns all of the data from the database table.
| | 01:20 | Before you can call a ColdFusion component
from a Flex application, you have to
| | 01:24 | know the CFC address as it will be known
to Flex. This is known in Flex as the
| | 01:29 | source property and you can inspect the
ColdFusion component in a browser to
| | 01:33 | find out what that source property value
is. Go to the CFC and then click the
| | 01:38 | Browse button in Flex Builder CFE clips perspective.
You need to enter your RDS
| | 01:43 | or Administrator password. These are the
passwords that you set up during the
| | 01:47 | installation process for ColdFusion and
after you have authenticated yourself
| | 01:53 | to the ColdFusion service, you will see
documentation for the ColdFusion Component.
| | 01:58 | Noticed that the ColdFusion Component
name is listed at the top in large
| | 02:01 | characters but right above it is the complete
path or source of the CFC as it
| | 02:07 | will be known to Flex. So select that
text which consists of the folder
| | 02:11 | location of the CFC in dot notation starting
from right after the web root,
| | 02:16 | that's flex3btb.cfc and then the name of
the CFC without the .CFC extension.
| | 02:24 | Copy that to the clipboard. You will
need that in your Flex Code.
| | 02:28 | Now I will go back to Flex Builder and go
to the Flex Project Chapter07Begin.
| | 02:33 | Go to the source folder, right click on it
or Ctrl+Click on the Mac and select
| | 02:39 | New MXML Application. Name the application
UseRemoteObject.mxml. Set the layout
| | 02:47 | to vertical and click Finish.
| | 02:49 | When the application code appears on the
screen, place the cursor between the
| | 02:55 | application tags and declare an instance
of the RemoteObject component. The
| | 03:01 | RemoteObject component is one of the three
RPC components. RPC standing for
| | 03:05 | Remote Procedure Call and again, this
is the component that allows you to
| | 03:09 | communicate very quickly with ColdFusion.
Set its id property to myService.
| | 03:15 | Each remote object component requires
a destination property.
| | 03:19 | The destination for ColdFusion CFCs is always
the same, ColdFusion and then set
| | 03:25 | the source property and paste in the
value that you copied from the CFC
| | 03:30 | documentation. It should be flex3btb.cfc.PersonService.
Close the remote object
| | 03:38 | tag. This is now the definition of the location
of the ColdFusion component.
| | 03:43 | Now you can call any of the components of
the CFC using a syntax combining the
| | 03:47 | id of the remote object plus the name of
the method that you are calling from
| | 03:51 | the CFC, in this case getPersonData.
| | 03:54 | So now the next step is to add a Button,
give it a label of Get Data and a
| | 04:03 | click event listener that calls the remote
CFC function, using the syntax
| | 04:09 | myService.getPersonData. Be sure to include
the opening and closing parenthesis
| | 04:15 | at the end of the call and then close the
tag of the Button. There are two ways
| | 04:21 | to capture the data that's returned from
the ColdFusion Server, Binding
| | 04:25 | Expressions and Event Handlers. I am going
to use a Binding Expression in this
| | 04:29 | example because it's the simpler syntax.
| | 04:33 | Create a DataGrid and set its dataProvider
using the following binding
| | 04:37 | expression, myService.getPersonData.lastResult.
The syntax of the binding
| | 04:48 | expression always follows the same pattern.
You start with the id of the remote
| | 04:53 | object component then the name of the method
that you called and then last
| | 04:58 | result as a property of the method object.
Even though, ColdFusion itself is a
| | 05:02 | non case sensitive environment, in the Flex
environment it's critical that you
| | 05:06 | match the case of how you called the
method to the case of the binding
| | 05:10 | expression reference to the method. So
notice I am using exactly the same
| | 05:14 | spelling of the method name in both cases
and if you miss that, if you don't
| | 05:18 | match them exactly, the data
won't appear correctly.
| | 05:21 | Now I am ready to test the application.
I will run the application in normal
| | 05:25 | mode and then I will click the Get Data button
and after a few moments the data
| | 05:29 | appears in the Data Grid. Noticed that you
can now scroll up and down and see
| | 05:34 | all of the data that's return from the
ColdFusion Server. Now in the next
| | 05:37 | video, I will show you how to use an Event
Handler to capture the data, which
| | 05:41 | gives you a lot more flexibility and power
in how you deal with the date when
| | 05:44 | it's returned.
| | Collapse this transcript |
| Handling the RemoteObject result event| 00:00 | In this video, I am going to describe an
alternative approach to handling data
| | 00:04 | returned from an RPC component call such
as the Remote Object Component. For
| | 00:08 | these exercises, I will be using application
files that are available in the
| | 00:12 | Exercises folder.
| | 00:13 | If you are following along with the exercises,
go to the Exercises folder which
| | 00:17 | I have installed on my desktop and navigate
to the Chapter07 folder and from
| | 00:22 | there to the folder Chapter07Begin. You
will find three files there. Select
| | 00:27 | them and copy them to the clipboard. Now
I will go back to Flex Builder. Go to
| | 00:33 | the source folder within the Chapter07Begin
project and paste the files into
| | 00:37 | your project. Then open the application
file UseResultEvent.mxml. This is the
| | 00:45 | same application that I worked on in the
previous video where made a call to a
| | 00:49 | remote ColdFusion component function called
getPersonData and then used a
| | 00:53 | binding expression to display the
data in the DataGrid control.
| | 00:57 | In this exercise, I am going to change
the approach to handling the data to
| | 01:00 | using the Result Event. Whenever you get
data back from a remote server using
| | 01:05 | any of the RPC components, that is Remote
Object, Web Service or http service,
| | 01:10 | the RPC component despatches the result event.
The event object it's despatched
| | 01:15 | is an instance of a class named Result
Event and this class has a result
| | 01:19 | property which points to your data. You can
use this event to capture and save
| | 01:23 | the data persistently, so that's then available
to the entire application for
| | 01:28 | the lifetime of the user session.
| | 01:30 | Follow these steps. First create a Script
section, below the Application start
| | 01:35 | tag and above the RemoteObject. The next
step is to declare a variable while
| | 01:39 | you save the data persistently. Make
it bindable by adding the bindable
| | 01:43 | Metadata tag and then declare the variable
using this syntax, private var
| | 01:52 | myData and data type it as an ArrayCollection.
The next step is to create an
| | 01:58 | Event Handler function. Create a new function
named resultHandler. Set its
| | 02:05 | event argument, data typed as ResultEvent.
Notice that with both the
| | 02:10 | ArrayCollection and the ResultEvent class,
as I select the class from the list
| | 02:15 | of available classes, Flex Builder adds
the required import statements. The
| | 02:20 | resultHandler function will return void as
to all good Event Handler functions.
| | 02:25 | Now I will go to the Remote Object Component
and add an Event Handler. Use
| | 02:30 | this syntax, result="resultHandler and pass
the event object. Now when the data
| | 02:37 | is returned from the Remote Server, the
event object will be passed into the
| | 02:41 | resultHandler function. Add a break point
on the last line of the function.
| | 02:46 | That's the line that has the closing brace.
Then save and run the application
| | 02:50 | in debug mode. When the application appears
click the Get Data button. If you
| | 02:56 | see this request to switch to the Flex
Debugging perspective, click Yes and
| | 03:01 | then go to the Variables view, expand it
to full screen and inspect the event
| | 03:06 | object. You will see that the event object
is data typed as result event.
| | 03:11 | Navigate down to the result property which
is an ArrayCollection and within
| | 03:15 | that object you will see all the rows
that are returned from the remote
| | 03:19 | database through the CFC function. Whenever
a CFC function returns a query
| | 03:24 | object that is an object created by the cfquery
tag, it's automatically exposed
| | 03:28 | in the Flex environment as an instance
of the ArrayCollection class.
| | 03:32 | Now resize your variables view and terminate
the debugging session. Then go
| | 03:37 | back to your source code in full screen.
Since we now know that the events
| | 03:42 | result property is an Array Collection containing
the data, we can assign that
| | 03:47 | to the existing myData variable, like
this, myData = event.result as
| | 03:55 | ArrayCollection. We have to tell the compiler
explicitly that the object being
| | 04:00 | returned is an Array Collection. It won't
know it without that syntax.
| | 04:04 | Now I will go down to the DataGrid component
and change its dataProvider, so
| | 04:08 | that instead of using the full binding expression
pointing to the name of the
| | 04:12 | method and the last result property, we simply
point to myData. So here are all
| | 04:18 | the steps that we declare a Bindable
variable, data typed as an
| | 04:22 | ArrayCollection, we create a resultHandler
function that passes the data to
| | 04:26 | that variable and then the data is available
for binding to visual controls
| | 04:31 | such as a DataGrid.
| | 04:33 | Run the application again, this time in normal
mode. Click the Get Data button
| | 04:39 | and you should see the data appear on the
Data Grid, just like it did before.
| | 04:43 | Using a result event handler takes a bit
more code than a binding expression
| | 04:47 | but there are enormous benefits. First of
all, you have the opportunity in an
| | 04:51 | Event Handler function to inspect, modify
and massage data before you display
| | 04:56 | to the user. Also, you have effectively
decouple the visual controls such as
| | 05:01 | the Data Grid from the component that's getting
the data from the server, such
| | 05:05 | as the remote object. This is a good
software design architecture.
| | 05:09 | By separating the components that get the
data which we call the model from the
| | 05:13 | components that present the data and allow
the user to interact with it, which
| | 05:16 | we called the view, you can more effectively
manage and maintain your
| | 05:20 | application in the future without it becoming
brittle. When you have components
| | 05:24 | that use binding expression that directly
to the data acquisition components
| | 05:29 | such as remote object, you are tightly coupling
the components and that kind of
| | 05:33 | application turns out to be very bugproof.
| | 05:36 | So this is how we use the Result Event to
separate the components and to allow
| | 05:41 | ourselves to save data persistently after
it's been returned from the server.
| | Collapse this transcript |
| Handling the RemoteObject fault event| 00:00 | As I described in the previous video, when
an RPC component such as remote
| | 00:04 | object, sends a request to a Remote
Server and the data comes back
| | 00:08 | successfully, it despatches an event named
Result. When things go wrong though
| | 00:13 | it despatches another event called Fault
and you can listen for an handle this
| | 00:17 | Fault Event to react to problems that can
occur during communication with the server.
| | 00:22 | For this demonstration, I will use the
application UseFaultEvent.mxml. If you
| | 00:27 | are following along with the exercises,
you will find this file in the
| | 00:29 | Exercises folder under the Chapter07Begin
area. Open the application and you
| | 00:34 | will see that this is the same application
I worked on in the previous video.
| | 00:37 | It's currently listening for and reacting
to a result event to handle and
| | 00:42 | capture the data that's return
from the Remote Server.
| | 00:45 | In order to handle a fault event, add an
eventHandler function that expects an
| | 00:49 | event argument, data typed as the Fault
Event class. Use this code, private
| | 00:56 | function faultHandler and pass an event argument
to the function, data typed as
| | 01:02 | faultEvent and return void as with all
event handler functions. As with the
| | 01:08 | result event and ArrayCollection classes,
the fault event must be imported and
| | 01:13 | if you follow the steps that I did, Flex
Builder will add the required import
| | 01:17 | statement for you.
| | 01:18 | Now go to the remote object declaration
and then add a fault event listener.
| | 01:23 | Put in a fault attribute and in the action
script code call the faultHandler
| | 01:28 | function and pass the event object. The
next step is to debug and inspect the
| | 01:33 | event object. Place a break point on
the last line of the faultHandler
| | 01:36 | function, that is the line with the closing
brace. Then go down toward the
| | 01:41 | bottom of the application and add a new Button
component with a label of Cause
| | 01:46 | Fault. Add a click event handler and this
time call a remote CFC function that
| | 01:54 | doesn't exist, using this syntax, myService.noSuchMethod.
Because I am trying
| | 02:04 | to call a function or a method that is
not defined in the CFC, that will
| | 02:08 | trigger in exception at the server level
and that exception will bubble back up
| | 02:12 | to the Flex application causing the fault event.
| | 02:15 | Now save your changes and run the application
in debug mode. Click the Cause
| | 02:20 | Fault button and that will trigger the exception
at the server due to trying to
| | 02:24 | call function that isn't defined. Switch
back to Flex Builder if necessary and
| | 02:28 | if prompted go to the Flex Debugging perspective.
Go to the Variables View and
| | 02:34 | open the event object which is data typed
as fault event. Noticed that it has a
| | 02:39 | fault property which is data typed as a
class named fault and this object has
| | 02:43 | properties named faultCode, faultDetail
and faultString. Each of these
| | 02:48 | properties contains a string value and
you can use any combination of these
| | 02:52 | values to get information about
the nature of the problem.
| | 02:55 | Now to actually handle the fault, you have
a number of options. Probably the
| | 02:59 | simplest approach is simply to share the
fault information with the user, using
| | 03:03 | a pop-up window generated by the alert
class. So restore the size of the
| | 03:08 | Variables View and terminate your debugging
session, then go back to the Flex
| | 03:12 | Development Perspective and place the cursor
inside the faultHandler function.
| | 03:18 | Call the Alert class's show method. Pass
in the following two arguments to the
| | 03:25 | Alert.show method, event.fault.faultString
is a longer message that you can
| | 03:34 | display in the body of the pop-up window
and event.fault.faultCode is a shorter
| | 03:41 | value that will fit nicely into the
title of the pop-up window.
| | 03:46 | Check to make sure that Flex Builder has
added the required import statement
| | 03:49 | for the Alert class, if not, add it yourself.
Save your changes and run the
| | 03:54 | application, this time in normal mode.
Click the Cause Fault button and you
| | 03:59 | should see the pop-up window generated by
the Alert class displaying the fault
| | 04:03 | information. Click OK to clear the pop-up
window and then click the Get Data
| | 04:08 | button and you should successfully retrieve
and display the data in your application.
| | 04:13 | So these are the two most commonly used events
of the Remote Object Component.
| | 04:17 | The Result Event handle successful communication
and retrieve all the data from
| | 04:21 | the server and the Fault Event handles exceptions
that can occur when something
| | 04:26 | goes wrong either at the server
or at the client level.
| | Collapse this transcript |
| Passing arguments to CFC functions| 00:00 | In this video, I am going to describe how
to use ColdFusion functions that
| | 00:04 | require parameters or arguments. I
will be using the application
| | 00:08 | PassParameters.mxml. If you are following
along with the exercises and you
| | 00:12 | don't have this application, you can
find it in the Exercises folder
| | 00:16 | Chapter07Begin sub-folder. Open the application
and take a look at it. It's the
| | 00:22 | same application I have been working on
in previous videos. It retrieves data
| | 00:25 | from the server using a call to the
CFC function getPersonData.
| | 00:30 | Let's take another look at the CFC function
that's being called. Go to the
| | 00:34 | flex3btbCF project that references all of
your ColdFusion code and opened the
| | 00:39 | file PersonService.cfc. Here is the code
for the getPersonData function. It
| | 00:45 | executes a query and then has a conditional
clause that looks for an argument
| | 00:49 | called lastname. If that argument exists,
it filters the return value based on
| | 00:54 | the value that's passed in, only returning
data where the value of the argument
| | 00:58 | matches the beginning of the last
name column of the row.
| | 01:01 | So let's go back now to the application.
There are three ways to pass in
| | 01:05 | arguments to a ColdFusion function. The first
is called explicit arguments. In
| | 01:11 | this approach, you pass in values in exactly
the same order in which they are
| | 01:15 | declared in the CFC function. So for example,
let's say that you only want to
| | 01:19 | retrieve data where the last name column
starts with the letter F. Go to the
| | 01:24 | getPersonData function and pass in a value
of the letter F wrapped in single
| | 01:28 | quotes. Save your changes and run the application.
Click the Get Data button
| | 01:35 | and you will see that you only get back
the data for the values that you
| | 01:38 | wanted. Now it would also be nice to do
this more dynamically and for this
| | 01:42 | purpose I have provided a custom component
that you can plug into the application.
| | 01:48 | If you are following along with the exercises,
go the Exercises folder to the
| | 01:52 | Assets folder and look at a folder named
Components. There you will find a
| | 01:56 | component named CharacterSelector.mxml.
Copy it to the clipboard. Go back to
| | 02:03 | Flex Builder, to the Flex Navigator Project,
go to the source folder and add a
| | 02:07 | new folder there, named Components and then
paste the component into the new folder.
| | 02:17 | The CharacterSelector custom component presents
two button bars, each populated
| | 02:22 | with a button with a particular character
on it. Combined they present the
| | 02:26 | letters A through Z. Go back to the PassParameters.mxml
file. Place the cursor
| | 02:32 | after the DataGrid component and add an instance
of this new custom component.
| | 02:37 | Start off typing the less than character
than char and you should see the
| | 02:42 | CharacterSelector custom component is available.
Select it to fill in the tag,
| | 02:47 | set its id property to selector and then
listen for an event that's despatched
| | 02:51 | by this custom component called select. Use
this syntax, select= and then when
| | 02:59 | the event occurs call the following
action script code,
| | 03:02 | MyService.getPersonData and pass
in a value of event.text.
| | 03:11 | The text property of the event object
for this component will contain the
| | 03:15 | character that they clicked on. Close the
tag and run the application. The
| | 03:21 | CharacterSelector component displays these
two button bars. You can still click
| | 03:25 | the Get Data button, which in this case
is still filtering on the letter F or
| | 03:30 | you can now click on any of these buttons
to see a filtered list of data passed
| | 03:34 | back from the server.
| | 03:37 | So that's one approach to passing arguments.
Here is another approach. You can
| | 03:41 | also pass arguments by name, by wrapping
them inside an action script object.
| | 03:46 | Go to your Script section and create a new
function named getDataByLastName.
| | 03:53 | Set up the signature of the function to receive
an argument named filter, data
| | 03:57 | typed as a string, returning void.
| | 04:00 | Now within the function, you are going to
create an action script object and
| | 04:04 | then give it a named property that matches
the name of an argument expected by
| | 04:08 | the ColdFusion function. Here are the steps.
We will create a variable named
| | 04:13 | params, data typed as an Object and instantiated
using the Object class's no
| | 04:19 | arguments constructor method. Next, we
will add a named property called
| | 04:24 | lastname and that matches the name of the
argument expected by the CFC function
| | 04:29 | on the server and we will set its value
to the filter value. Finally, we will
| | 04:34 | make a call to the Remote CFC function using
the syntax MyService.getPersonData
| | 04:42 | and then we will pass in the params object.
| | 04:46 | Now go back down to the CharacterSelector
button and replace the action script
| | 04:50 | code in the select event listener, so
that now it's calling the method
| | 04:55 | getDataByLastName and once again passing
the event objects text property to
| | 05:00 | indicate what we were filtering on. When
you pass in a object with named
| | 05:05 | properties into a ColdFusion function
as its only argument, the object is
| | 05:09 | broken apart into its individual named
values and the arguments and their
| | 05:13 | values are now matched by name rather
than by order. Save and run the
| | 05:17 | application and you should still be able
now to filter by clicking on the
| | 05:22 | buttons of the custom component.
| | 05:25 | Let's make one more change to the application
and then we will consider it
| | 05:28 | complete. Go back to the Button labeled
Get Data and change its label to Get
| | 05:32 | All Data, then go to the call to getPersonData
and remove the argument.
| | 05:37 | So now you have two different ways of getting
data from the server. If you call
| | 05:41 | the getPersonData directly without any arguments,
you will retrieving all the
| | 05:45 | data because of the logic within the CFC
function, but if you passed the
| | 05:48 | function and object containing named properties,
where the property names match
| | 05:53 | the names of the arguments in the CFC,
you are not passing the arguments by name.
| | 05:57 | I will run the application one final time
and show that if I clicking the Get
| | 06:01 | All Data button, you will retrieve all
the data from the server, but by
| | 06:05 | clicking on the buttons of the selector
component you are filtering on that
| | 06:09 | particular character.
| | Collapse this transcript |
| Working with multiple CFC functions| 00:00 | In this video, I am going to describe how
to handle result events when you
| | 00:04 | called multiple functions from the ColdFusion
Component. For the exercises in
| | 00:08 | this video, I will go back to the application
UseResultEvent.mxml. Let's take
| | 00:13 | another look at the ColdFusion component
we have been calling, named
| | 00:16 | PersonService.cfc. It has two functions named
getPersonData and getPersonCount.
| | 00:23 | The getPersonData function returns data
from the database table. You can call
| | 00:28 | the function without any arguments to
get back all the data or pass in an
| | 00:31 | argument to filter it.
| | 00:32 | There is a also a function called getPersonCount,
which returns a numeric value
| | 00:38 | which is the total number of records in the
database. When you want to be to it
| | 00:42 | call more than one function from a single
CFC, you have to distinguish in your
| | 00:46 | result event handlers, which event of which
function you are listening for. If
| | 00:51 | you declare everything in MXML,
here is how it's handled.
| | 00:55 | First of all, change your Remote Object
Component so that it's declare with a
| | 00:59 | set of tags rather than a single tag. Then
within the remote object component
| | 01:04 | you declare as many mx method tags as there
are functions you are calling from
| | 01:09 | the CFC. Mx method is something called a
compiler tag. It doesn't represent a
| | 01:13 | true property or even an instance of a
class, instead it's simply a way of
| | 01:17 | instructing the compiler how to despatch
and handle different events.
| | 01:21 | So for example, when you call the method
called getPersonData and you want to
| | 01:25 | handle the result event for that particular
method with a specific function,
| | 01:29 | you add an mx method tag and you set the
name property to the name of the
| | 01:34 | method you are calling, getPersonData. As
always this is highly case sensitive.
| | 01:39 | You must match the value of the name property
here to the name of the method as
| | 01:43 | it's being called.
| | 01:45 | Now add a result event handler which looks
exactly the same as the version in
| | 01:49 | the remote object tag and pass the event
object to the appropriate event
| | 01:53 | handler function. So I am going to call
resultHandler and pass the event
| | 01:57 | object. Now I am specifically handling this
particular functions result event.
| | 02:03 | So I will go back to the remote object
tag and remove the result event from there.
| | 02:09 | Now going back to the ColdFusion component,
I would also like to make a method
| | 02:13 | call to getPersonCount. So I will go back
to the application and add another
| | 02:18 | method tag, set its name property to
the name of that remote method,
| | 02:23 | getPersonCount and set a different result
event handler called countHandler.
| | 02:34 | Then I will go up to the Script section
and create that function. As with all
| | 02:39 | event handler functions for RPC result events,
I will receive an event object
| | 02:44 | data typed as resultEvent and as with all
event handler functions are returned void.
| | 02:51 | Now I am going to display the total number
of records that was recorded by the
| | 02:55 | database using an Alert class and I will
call it show method and display the
| | 03:01 | message There are and then our output event.result
which will be total number
| | 03:08 | of records and then another little string
of, records in the database table.
| | 03:14 | Then I will pass in the title of Record Count.
| | 03:22 | Finally, I will go down to the applications
visual interface and add a new
| | 03:26 | button. I will set its label to Get Record
Count and add a click event listener
| | 03:34 | that calls the remote function getPersonCount.
Be sure to include the opening
| | 03:41 | and closing parenthesis at the
end of the function called.
| | 03:45 | So here are all the pieces of the puzzle.
We have a distinct event listener for
| | 03:49 | that particular remote function in the CFC.
We have an mx method tag within the
| | 03:54 | remote object that handles the event and
despatches the event object to the
| | 03:59 | correct function and a button control whose
click event calls the function. I
| | 04:03 | will save the changes and run the application
and as before I can still click
| | 04:11 | the Get Data button and I will get all the
data displayed in the Data Grid, but
| | 04:15 | now I can also click the Get Record Count
button and I get back the report that
| | 04:19 | there are 100 records in the database table.
| | 04:21 | So this is one way of handling multiple
functions that you call from a single
| | 04:26 | CFC. Now in the next video, I will show you
another approach that's pure action
| | 04:30 | script code based, where you both instantiate
the Remote Object Component and
| | 04:34 | set up its event listeners using
pure action script.
| | Collapse this transcript |
| Using RemoteObject with ActionScript| 00:00 | In this video, I am going to describe how
to use the Remote Object Component,
| | 00:04 | initializing the component and setting up
its event listeners using pure action
| | 00:08 | script code. For this demonstration,
I am going to create a brand new
| | 00:11 | application. If you are following along
with the exercises, go to the Flex
| | 00:15 | Builder Menu and select File, New, MXML
Application. Set the name of the
| | 00:21 | application as RemoteObjectWithAS.mxml and
set its layout property to vertical.
| | 00:30 | Now I will place the cursor between the
Application tags and add a Script
| | 00:33 | section. The Remote Object Component is
an Action Script Class which can be
| | 00:38 | instantiated in action script code just
as easily as in MXML. Between the
| | 00:42 | Script tags, declare a new variable data
typed as ro for Remote Object and then
| | 00:49 | for its data type select Remote Object.
| | 00:51 | When you select the Remote Object class from
the list of available classes, you
| | 00:55 | will see that there are two versions of
the class. They are distinguished by
| | 00:59 | their packages. Notice one of them ends with
the package of .MXML and the other
| | 01:03 | doesn't. Use the second one for action
script code. There are couple slight
| | 01:08 | differences in its properties, but its basic
behavior is the same. Click OK and
| | 01:13 | then ends the declaration with the semicolon.
| | 01:16 | Next, create a private function named init.
This function will be called upon
| | 01:20 | application start up and return void. Then
go back to the application start tag
| | 01:25 | and add an applicationComplete event listener
and call the init function. Now I
| | 01:30 | will go back down to the init function. As
the application starts up, here are
| | 01:34 | the tasks you will need to accomplish.
| | 01:36 | First instantiate the remote object and
initialize it with its destination,
| | 01:41 | that is the remote object on the server
that you are calling, that will be a
| | 01:44 | value of ColdFusion. So the code for that
is ro = new RemoteObject and here we
| | 01:51 | are calling the Constructor method of the
RemoteObject class and then pass in
| | 01:55 | the destination as the one and only argument.
The destination as with the MXML
| | 02:00 | version is simply ColdFusion.
| | 02:02 | Now set the source property which is the
address of the CFC on the server. Use
| | 02:07 | this code, ro.source = "flex3btb.cfc.PersonService"
and this is exactly the
| | 02:17 | same value that you would put into the
source property in the mxml version.
| | 02:21 | Next, we need to set up an event handler
function to handle the data that's
| | 02:24 | returned, when you call one of the CFCs
functions. Place the cursor after the
| | 02:29 | init function and create a new function
called resultHandler. The syntax for
| | 02:35 | this event handler function is exactly the
same as in the MXML version. It will
| | 02:39 | receive the single event argument, data
typed as ResultEvent and return void.
| | 02:45 | Now to hold the data, place the cursor above
the init function and declare a
| | 02:50 | new Bindable variable using the syntax private
var and name the variable myData
| | 02:56 | and data type it as an ArrayCollection.
Go back to the resultHandler function
| | 03:01 | and fill in the value of that variable when
the data comes back from the server
| | 03:05 | with the syntax myData = event.result
as ArrayCollection.
| | 03:12 | Now we have just a couple more steps to do.
Go to the init method again. As the
| | 03:17 | application starts up, you have already
instantiated and set the Remote
| | 03:20 | Object's source property, now you will need
to add an event listener using this
| | 03:24 | syntax, ro.addEventListener and for
the event name, use the constant
| | 03:30 | ResultEvent.RESULT and then in the second
argument, pass in a reference to the
| | 03:35 | function you want to call, resultHandler.
| | 03:38 | Finally and the last step in using the Remote
Object, call the remote object's
| | 03:43 | CFC function name using the same sort of
syntax as you did in the MXML version,
| | 03:48 | ro.getPersonData. So as the application
starts up, we are handling everything
| | 03:54 | within the init method. Constructing the
remote object, setting its source, its
| | 03:59 | destination and its event listener and
then calling the remote method.
| | 04:03 | Finally, create a visual control to display
the returned data. Place the cursor
| | 04:08 | after the script section and create a DataGrid
and set its dataProvider using a
| | 04:13 | binding expression to the ArrayCollection
variable, myData. Save your changes
| | 04:20 | and now as the application starts up, it
will make the request to the Remote
| | 04:23 | Server and the data should be
displayed successfully.
| | 04:27 | So you now have a working example of how
to use the Remote Object Component in
| | 04:31 | pure action script. Many developers prefer
this approach to the mixture of MXML
| | 04:36 | and action script code, but it's a question
of style rather than function and
| | 04:41 | you can make your own choice about how
to architect the code for your application.
| | Collapse this transcript |
|
|
8. Using the ColdFusion Extensions for Flex BuilderInstalling the ColdFusion Extensions plug-in| 00:00 | In this chapter of the video series, I
am going to describe the use of the
| | 00:03 | ColdFusion Extensions for Flex Builder,
an Eclipse plug-in that provides many
| | 00:08 | features that are valuable to ColdFusion
developers including RDS connectivity.
| | 00:13 | RDS stands for Remote Development Service
and it's a protocol that's been used
| | 00:18 | by various products including HomeSite and
Dreamweaver in the past to connect
| | 00:22 | to ColdFusion servers during development
and provide information about database
| | 00:26 | structure, services and other valuable features.
| | 00:30 | The RDS connectivity is also used by the
ColdFusion Extensions to create code
| | 00:35 | generation wizards. These code generation
wizards can inspect the structure of
| | 00:39 | the database table and then generate both
server and client-side code to create
| | 00:44 | easy data connectivity functionality from
a Flex application to ColdFusion at runtime.
| | 00:50 | In order to use the ColdFusion Extensions
you have to first install them,
| | 00:54 | during the initial installation of Flex Builder
you may have already installed
| | 00:58 | the extensions because they are offered
as an option during that installation
| | 01:01 | process. If you would like to check whether
you have the ColdFusion Extensions
| | 01:05 | installed, go to the Flex Builder menu and
select Window, Other Views and look
| | 01:12 | for a set of views that are categorized
under ColdFusion.
| | 01:15 | You will see such views as RDS Dataview,
RDS Fileview and others. If you don't
| | 01:21 | see that group of views that means that
the ColdFusion Extensions aren't
| | 01:25 | installed on your system and you need to
install them if you want to use them.
| | 01:29 | So here are the steps for the installation.
From the Flex Builder menu select
| | 01:34 | Help Software Updates, Find and Install.
| | 01:39 | Select Search for new features to install
on the Feature Updates screen and
| | 01:43 | then click next. The ColdFusion Extensions
are provided as a zip formatted
| | 01:49 | installer file in the Flex Builder installation.
They are also provided as the
| | 01:54 | same file in the ColdFusion 8 installation.
Click the New Archived Site button,
| | 01:59 | in the Update sites to visit dialog,
and navigate to the Flex Builder 3
| | 02:03 | installation folder.
| | 02:06 | On Windows, this will be by default under
C:\ProgramFiles\Adobe\FlexBuilder3
| | 02:15 | and on Mac OS X, this folder will be
\Applications\Adobe\FlexBuilder3. From
| | 02:22 | that folder, navigate down to the Installers
folder, from there to the
| | 02:27 | ColdFusion Extensions for Flex Builder
and then locate and select the file
| | 02:32 | ColdFusion_Extensions_for_Eclipse.zip.
This will bring you back to a dialog
| | 02:37 | labeled Edit Local Site, the name that you
supply for this site can be anything
| | 02:42 | and you can accept the default value and
the URL is set based on what you
| | 02:46 | selected during the browsing process. Click
OK to save the site definition.
| | 02:51 | When you come back to the Update sites to
visit screen, the new site will be
| | 02:56 | selected, click the Finish button to continue.
Now, I am not going to continue
| | 03:01 | this process because I already have the
extensions installed, but on your
| | 03:05 | system if you need to complete the installation
follow all of the rest of the
| | 03:09 | prompts through the installation process.
At the end you will be prompted to
| | 03:13 | restart Flex Builder and you will want
to confirm and do that and that will
| | 03:17 | ensure that all of the new features
would be available upon restart.
| | 03:21 | Then if you are following along with the
exercises and you have the exercise
| | 03:24 | files available, before you continue with
the rest of this chapter, you will
| | 03:29 | want to make sure you have installed and
started ColdFusion and that you have
| | 03:33 | installed the sample database that's a
part of the assets\ColdFusion folder
| | 03:37 | within the exercises area, and from that
point all of the rest of the exercises
| | 03:42 | in this chapter will be available to you,
because I am primarily going to be
| | 03:46 | looking at how to use this ColdFusion
Extensions plug-in to inspect data
| | 03:50 | structure create queries and then generate
both client and server code and
| | 03:56 | integrate that into your Flex applications.
| | Collapse this transcript |
| Using RDS Dataview and the Visual Query Builder| 00:00 | In this video I am going to describe how
to configure and use some of the
| | 00:04 | features of the ColdFusion Extensions
for Flex Builder. I am going to be
| | 00:08 | focusing in this video, on features that
are enabled by RDS or the Remote
| | 00:13 | Development Service Protocol. As I described
previously, RDS has been
| | 00:17 | previously implemented by other code development
tools such as HomeSite and
| | 00:22 | Dreamweaver, and allows you to connect
to a ColdFusion server during
| | 00:25 | development, to get information about database
tables and their structures.
| | 00:30 | Before you try to visit a ColdFusion Server
through RDS, you first need to
| | 00:34 | check and perhaps setup your configuration.
| | 00:38 | Go to the Flex Builder Menu and select Window
Preferences. In the Preferences
| | 00:43 | dialog, open the Adobe category and select
RDS Configuration. You'll see a
| | 00:50 | single item listed here labeled local
host. The default RDS Configuration
| | 00:55 | labeled local host, is setup to look for
a ColdFusion server installation on
| | 00:59 | the local system, using the IP address
127.0.0.1 and port 8500, which means
| | 01:08 | that it assumes that you are using the development
or stand-alone web server.
| | 01:12 | Now if your version of ColdFusion is installed
differently, for example if you
| | 01:16 | install ColdFusion using IIS and you are
listening on port 80 instead of 8500,
| | 01:21 | you'll need to make a change here.
| | 01:23 | Similarly, if you are using a version of
ColdFusion that works in the J2EE
| | 01:28 | installation, under a different port number
and with what's called a context
| | 01:32 | root, you should fill that context route
in here. The security information
| | 01:37 | refers to the name and password under which
your RDS system is protected on the
| | 01:43 | ColdFusion Server. During the installation
of ColdFusion, I describe the setup
| | 01:48 | of an RDS password. You can add the password
here and then deselect the prompt
| | 01:54 | check box and then you'll be able to connect
your ColdFusion Server through
| | 01:57 | RDS, without having to reenter the password
later on. I'll go ahead and enter
| | 02:02 | my password here and deselect the
check box and then click OK.
| | 02:08 | Now to view the ColdFusion server's data
information through RDS, go to the RDS
| | 02:13 | Data view window. Select Window, Other Views
and go to the ColdFusion section
| | 02:20 | of the Views List. Locate the RDS Dataview,
select it and click OK. The RDS
| | 02:29 | Dataview appears at the bottom of the interface
by default. I typically click
| | 02:33 | and drag the tab up to the top right, because
the tree lays out vertically and
| | 02:39 | that gives me a little bit more space to
look in the information. If you have a
| | 02:42 | dual Screen Setup where you spanning two
monitors alternatively, you might
| | 02:47 | right click or Control+Click on the Mac
on the tab and select Detached. That
| | 02:52 | will allow you to undock the view,
and drag it to the other screen.
| | 02:57 | Now open the local host heading and because
I already entered my RDS password.
| | 03:02 | I can now see all the data sources of the
ColdFusion server, without entering
| | 03:06 | the password again. Here is the data source
that I setup in the previous
| | 03:10 | chapter, Flex 3 BTB contacts. Click the
Tree Icon to open up the data source
| | 03:17 | and you'll see a listing of four categories
of items. Tables, Views, Synonyms
| | 03:22 | and System Tables. Open the table list and
you will see a single table there
| | 03:27 | named ape.person, the Ape prefix is something
that comes from the particular
| | 03:33 | database driver that's used for this database.
| | 03:36 | The Apache Derby database driver always adds
the Ape prefix to every table name
| | 03:41 | automatically, even if you haven't done
it yourself. You can also replace the
| | 03:46 | prefix with some other value, but you can't
get rid of entirely. If you use
| | 03:50 | another database such as SQL Server or MySQL,
you probably won't see that sort
| | 03:55 | of prefix there, but with Apache Derby it's
a part of the database name. Now
| | 04:00 | click the Tree Icon next to ape.person,
the table name and you'll see the
| | 04:05 | structure of the database appear and you'll
see that this table has unique
| | 04:09 | identifier column, person ID and variable
character fields of first name, last
| | 04:14 | name and so on. Now the next step is to
take a look at the data in the table.
| | 04:19 | Right click on the name of the table or
Control+Click on the Mac and select
| | 04:23 | Show Table Contents. A query is executed
and another view named the RDS Query
| | 04:30 | Viewer appears in the Editor region. I
am going to double click the Tab for
| | 04:34 | that view and you'll be able to see all
of the data is returned from the
| | 04:38 | ColdFusion Server. Now from this screen,
you can go into another feature called
| | 04:42 | the Visual Query Builder. Click the Visual
Query Builder button and that will
| | 04:47 | take you into a Visual Query Builder interface,
that's very similar to the one
| | 04:50 | that used to be used in a HomeSite. You
can build your query in a variety of
| | 04:53 | ways, here I am going to drag a table into
the interface and then I am going
| | 04:59 | double click on a couple of columns. I am
going to set a sort order on one of the columns.
| | 05:05 | Now if you are working on the Widows platform,
you will see a button on the
| | 05:09 | interface for Visual Query Builder.
If you are working on Mac OS X,
| | 05:13 | unfortunately this particular feature is
not available. But for Windows users,
| | 05:18 | you can click the Visual Query Builder button
and you'll go into an interface
| | 05:22 | that's very similar to the old Visual Query
Builder that was available with the
| | 05:26 | product named HomeSite or ColdFusion Studio.
Then I am going to test the query,
| | 05:32 | a window pops up displaying the data and
you can confirm the query is working
| | 05:36 | correctly. Then you can close the window
and return to the Visual Query Builder Interface.
| | 05:42 | Notice that the result of this visual interface
is a well formed SQL statement.
| | 05:47 | You can now use this SQL statement in
many ways, including copying it and
| | 05:52 | pasting it into your ColdFusion code. The
interface doesn't provide a way to
| | 05:56 | save the query, to disc in any fashion. Instead
it's just a way of building and
| | 06:00 | testing SQL code to get your database information.
So I am going to cancel out
| | 06:05 | of this screen and return to the RDS Query
Viewer and restore it to it's
| | 06:10 | original size. The RDS Query Viewer which
is the Editor window that I am in
| | 06:15 | right now, has a pull down list that lets
you switch between different RDS
| | 06:19 | connections if you have more than one
and also that lets you switch to
| | 06:22 | different projects if you need to.
| | 06:25 | So that's an overview of some of the major
tools of the ColdFusion extensions.
| | 06:29 | The RDS data view, the RDS Query Viewer
and on Windows, the Visual Query
| | 06:35 | Builder. Now in the next video, I am going
to show you how to use these tools
| | 06:39 | to start generating both server and client
side code for use in your Flex
| | 06:44 | Applications.
| | Collapse this transcript |
| Generating code with the CFC Value Object Wizard| 00:00 | In this video I am going to describe how
to use the ColdFusion Value Object
| | 00:04 | wizard. That's a part of the ColdFusion extensions
for Flex Builder to generate
| | 00:09 | both ColdFusion service side code and client
side Flex ActionScript code, so
| | 00:14 | that you can easily move data back and forth
between a Flex application and a
| | 00:18 | ColdFusion server at runtime.
| | 00:21 | Before you generate the code, you need
to create a Flex project that's
| | 00:24 | associated with your ColdFusion
Server. Follow these steps:
| | 00:29 | From the Flex Builder menu select File,
New, Flex Project. As in the previous
| | 00:36 | chapter, you are going to create a project
that's associated with ColdFusion.
| | 00:41 | Name this project Chapter08Begin. Check
your application and server type and
| | 00:46 | make sure that it's set to ColdFusion, and
that the Use remote object access
| | 00:51 | service option is selected along with
ColdFusion Flash Remoting.
| | 00:56 | Click Next and then check your server location
both the default disk location
| | 01:01 | and the web root. Then making sure that
your ColdFusion server is running,
| | 01:06 | click Validate Configuration and you should
see the verification message at the
| | 01:10 | top 'The web root folder and
root URL are valid.'
| | 01:14 | Also select your output folder which should
be a location under your ColdFusion
| | 01:18 | server web root. The default is the name
of the project followed by -debug, and
| | 01:24 | this is where you output folder with the
debug version of the application will
| | 01:28 | be created.
| | 01:30 | Click Next to go to the final screen and
set the name of the main application
| | 01:34 | file as UseCFWizardCode.mxml. Then click Finish.
| | 01:39 | When the application code has been generated,
check its layout property and if
| | 01:47 | it's been set to value of absolute, change
it to vertical. Then place label a
| | 01:53 | control inside the application text and set
its text property ColdFusion Wizard
| | 01:59 | Code. Set the font size style to a value
of 18 pixels, so it's nice and large.
| | 02:08 | Save your changes and then run the application,
and you will be able to varify
| | 02:12 | that your ColdFusion server is running and
that you are able to download and
| | 02:16 | run your Flex application from the ColdFusion
server. Then close the browser
| | 02:20 | and return Flex Builder.
| | 02:23 | The purpose of the ColdFusion Value Object
Wizard is to look at a database
| | 02:28 | table structure and create a set of ColdFusion
components on the server and one
| | 02:32 | ActionScript class on the client that will
then allow you to easily pass data
| | 02:37 | back and forth between the tiers
of the application.
| | 02:40 | To get to the wizard, go to RDS Dataview.
Go to the menu and select Window,
| | 02:46 | Other Views, and select RDS Dataview from
the ColdFusion section of the view
| | 02:51 | list, click OK. Now go to your RDS connection,
which on my system is labeled
| | 02:57 | localhost. Open the list of data sources;
open the data source for which you
| | 03:03 | want to generate code and open the table
list. Locate the name of the table for
| | 03:09 | which you want to generate code, right-click
on it or Ctrl-click on the Mac and
| | 03:15 | select ColdFusion Wizards, Create CFC.
| | 03:19 | The CFC Value Object Wizard needs a lot of
configuration before it will do what
| | 03:23 | you want it to do. The first bit of information
is the location of the folder
| | 03:28 | where you want to generate your ColdFusion
code. On my system I had previously
| | 03:33 | created a CFEclipse project pointing to
the location of my ColdFusion Server
| | 03:38 | code. I am going to browse and select that
project, which on my system is named
| | 03:43 | flex3btbcf, and then I will navigate down
to its CFC folder, which is where I
| | 03:49 | am going to place the generated ColdFusion
component code, and click OK.
| | 03:54 | Now set the CFC package name. This part
is not handled for you automatically,
| | 03:59 | instead you have to figure out what the
name of the package is based on the
| | 04:03 | names of the folders starting at the
web root. If you had followed the
| | 04:07 | instructions chapter for creating this CFEclipse
project, the package name will
| | 04:12 | be flec3btb.cf, and again that matches an
existing folder that starts from the
| | 04:19 | web root on down.
| | 04:21 | The next step is to select the primary key
column of the target database table.
| | 04:27 | By default, when you are working with a
database table that already has its
| | 04:30 | primary key defined, this will be selected
automatically for you. You also need
| | 04:36 | to indicate whether the primary key is going
to be provided by the user or is
| | 04:40 | going to be generated by the database table.
| | 04:42 | In this example, the database table is designed
to autoincrement or fill in the
| | 04:47 | next value for any new record. So I'll leave
this option deselected. The next
| | 04:53 | option simply indicates whether you want
to overwrite any existing files. I
| | 04:57 | haven't created these files yet, so it
doesn't matter what I select here.
| | 05:01 | The next option has to do with what type
of CFC you want to use. You can select
| | 05:06 | either Active Record CFC with result in generating
two ColdFusion components or
| | 05:11 | Bean CFC & DAO CFC which generates three.
I prefer Bean & DAO because it
| | 05:18 | creates a better separation of code on
the server, and there are also some
| | 05:21 | incompatibilities in the code for the active
record approach that you avoid.
| | 05:27 | The Property scope indicates how data will
be stored in what are called Value
| | 05:32 | Objects on the server. If you use the default
private, that means properties
| | 05:37 | are stored within a Bean or a Value Object
component on the server, and they
| | 05:41 | are stored privately within that component,
and can only be accessed through
| | 05:46 | private setter and getter accessory methods,
which will be generated for you.
| | 05:50 | If you select the option public, those variables
are then set in what's called
| | 05:55 | THIS scope in the ColdFusion component and
they can be referenced from other
| | 06:00 | ColdFusion code using simpler dot syntax.
I'll the Property scope to public.
| | 06:06 | When you use the Bean & DAO architecture,
there are three components generated
| | 06:10 | on the server. They are the Bean, also knows
as a Value Object that represents
| | 06:15 | a single instance of a data entity mapping
to the database table structure, a
| | 06:20 | DAO component that actually handles communication
with the database, and a
| | 06:25 | gateway component which contains remote
functions that you can call from your
| | 06:29 | Flex Remote Object component.
| | 06:31 | I will accept all of the file names, and
then I'll select another option down
| | 06:36 | here indicating that I want to create an
ActionScript Value Object. This is a
| | 06:41 | Value Object class that maps its properties
to the same values as the Bean
| | 06:46 | component or the Value Object component on
the server. You always want to place
| | 06:51 | this component in your Flex project and
not in you ColdFusion project.
| | 06:56 | So I'll click the Browse button, navigate
to my Flex project, 08Begin, and
| | 07:02 | select the source folder as the location
of the Value Object class. Now you
| | 07:06 | don't have the ability to create new folders
during this operation. So if you
| | 07:11 | want to move this to another folder later
on, you'll need to handle that move
| | 07:15 | manually after the code generation is done.
| | 07:18 | I'll click OK, and then the ColdFusion Wizard
gets a little thing wrong here
| | 07:24 | that you have to adjust for it. Get things
that the src folder in which I am
| | 07:28 | creating the class is actually a subfolder
of the source code root and it
| | 07:32 | isn't. It actually maps directly to the
source code root. So I am going to
| | 07:36 | leave the package blank. That's a lot of
information; let me review the steps.
| | 07:41 | The CFC folder is a location on your ColdFusion
server under your ColdFusion
| | 07:46 | project. The CFC package name is how you
address the folder on the ColdFusion
| | 07:52 | server and it's the folder structure containing
the CFCs starting from the web
| | 07:57 | root using dot syntax.
| | 08:00 | The Primary Key is detected automatically
by the wizard. You select one of
| | 08:04 | these two options for the CFC type, and I
have a preference for Bean & DAO CFC,
| | 08:09 | because it does a better job of separating
code on the server and the functions
| | 08:13 | it generates are completely
compatible with Flex.
| | 08:16 | I typically set the Property scope to
public. That gives me a little more
| | 08:19 | flexibility in the ColdFusion generated
code. I always create an ActionScript
| | 08:24 | Value Objects that maps to the ColdFusion
Bean Object, and the package name has
| | 08:28 | to be modified to account for the fact that
in Flex Builder 3 the source folder
| | 08:33 | maps to the source root and is not really
a subfolder of the source root as the
| | 08:38 | wizard expects.
| | 08:40 | Those are all the settings. Now I'll click
Finish, and after just a few moments
| | 08:45 | all of the code is generated. I'll have
four files that have been generated.
| | 08:50 | The Bean component, PERSON.cfc; the DAO
or Data Access Object component,
| | 08:56 | PERSONDAO; the Gateway component that I'll
call from Flex, PERSONGateway, and
| | 09:02 | the ActionScript class, PERSON.as.
| | 09:05 | Now and the next video, I am going to do
a code review of all of this generated
| | 09:08 | code and describe the purpose and use of
each of the components and classes.
| | Collapse this transcript |
| Understanding the generated code| 00:00 | In this video, I am going to review the
code that was generated by the
| | 00:03 | ColdFusion Value Object Wizard. As I described
in the video, when you use the
| | 00:09 | Bean and DAO architecture, there are three
components for each database table.
| | 00:14 | The value object or a Bean component, which
in this case is called person, the
| | 00:18 | same as the table name. The data access
object which has DAO after the table
| | 00:23 | name and the gateway component. Let's start
with the value object, the Bean or
| | 00:29 | Value Object Component, declares properties
for each of the columns of the
| | 00:33 | database table. The data type of the properties
are declared in the CF property
| | 00:38 | tags. The name and type attributes of the
CF property tags dictate to the Flex
| | 00:43 | environment, how that data will be translated
in the Flex application.
| | 00:47 | For example if you declare the column
name in all upper case, as happens
| | 00:52 | automatically with databases that are
being managed by the Apache Derby
| | 00:56 | Database Driver. That's the name of the property
that will be seen in the Flex
| | 01:00 | application and the same thing is true of
the data type. Columns that have a
| | 01:05 | type of numeric will show up as ActionScript
numbers and strings will show up
| | 01:09 | as ActionScript strings. The default attribute
of the CF property tag, doesn't
| | 01:14 | actually do anything in terms of functionality.
Instead the defaults are
| | 01:18 | explicitly set in a CF script section below
the CF property tags and this is
| | 01:24 | code that's outside of any of the functions
and therefore executes
| | 01:28 | automatically upon instantiation
of this component.
| | 01:31 | Because I selected an option to make these
properties public, they are all
| | 01:35 | prefixed with this, which in a ColdFusion
component means that each of these
| | 01:40 | properties is public and can be addressed
directly using simple dot syntax from
| | 01:45 | any other ColdFusion code on the server.
There is a function named init which
| | 01:50 | returns an instance of the current component
and then there are set and get
| | 01:55 | accessor methods for each of the properties.
For example the getPERSONID
| | 02:00 | function, has an access property of public
and return type of any, but it's
| | 02:05 | designed to return the current person ID
value of the current instance of the
| | 02:10 | component. Similarly the set method for
this particular function receives the
| | 02:16 | value which it names a Val as an argument
name, examines the value to make sure
| | 02:20 | it's of the correct type and isn't blank
and then passes the value to the
| | 02:25 | public property.
| | 02:27 | Using setter and getter accessor methods,
lets you be much more specific and
| | 02:32 | capture any runtime errors on the server
side a lot more easily. So you'll find
| | 02:37 | one set and one get function for each of
the properties that's declared at the
| | 02:41 | top of the component. There is one other
critical part of this component, that
| | 02:45 | should be described, the CF Component
tag has an alias property, which
| | 02:50 | indicates not only the name of the component,
but also the package in which
| | 02:54 | it's stored. In this case Flex3btb.cfc.
| | 02:59 | If you were to move this component to somewhere
else on your ColdFusion server,
| | 03:04 | you would want to make sure that you reset
the alias in this location and
| | 03:08 | everywhere, where it's referenced in the
rest of the ColdFusion code and also
| | 03:12 | in the Flex Code as I'll show you in
a little bit. So that's the Bean
| | 03:16 | Component. Now let's look at the DAO Component.
DAO stands for Data Access
| | 03:22 | Object, a Bean Component when it's
generated using the Bean and DAO
| | 03:27 | architecture has four functions named Read,
Create, Update and Delete. Taking
| | 03:33 | together they stand for CRUD, a conventional
type of component, that's used to
| | 03:37 | address database tables.
| | 03:40 | The purpose of the Read function is to receive
a single ID property and then
| | 03:45 | query and return a single object to the
requesting code because we are using
| | 03:50 | strongly typed value object components, after
it executes the query which is in
| | 03:55 | this CF query tag, it then transform the
returned data, into an instance of the
| | 04:00 | Bean Component. Notice that the entire Bean
Component is addressed in this call
| | 04:05 | to the Create Object function in ColdFusion.
This is an example of where if you
| | 04:09 | were going to move this code on the ColdFusion
Server, you would have to change
| | 04:13 | quite a few references to where
the components are stored.
| | 04:16 | The next function is named Create. It receives
a single instance of the Bean
| | 04:20 | Object, saves its values to local variables
after calling the get methods of
| | 04:26 | the Bean Object and then executes an Insert
statement to add the data to the
| | 04:30 | database. There is a bit of odd code here,
which is worth talking about. There
| | 04:36 | is a following query that retrieves the
record that was just inserted using a
| | 04:41 | where clause that filters on all of the
tables columns. Now that seems like a
| | 04:45 | bit of overkill, but the reason the code
is generated in this manner is
| | 04:49 | because every database has it's own unique
way of retrieving the most recently
| | 04:54 | assigned auto incremented primary key value.
You should select the approach for
| | 04:58 | your particular database and modify this
code accordingly. For example on SQL
| | 05:03 | server you might change it to select the
Add at Identity Value and assign it to a value.
| | 05:09 | Again look at the documentation for your
particular database to see how to
| | 05:13 | retrieve a recently assigned auto increment
value. The last two functions are
| | 05:18 | named update and delete, the update function
receives a Bean Object and
| | 05:23 | executes a conventional update statement
and the Delete function also receives
| | 05:28 | a Bean Object and it executes a delete SQL
Statement, to remove a record from
| | 05:32 | the database. So that's the DAO component.
| | 05:36 | Finally let's look at the Gateway. The Gateway
component contains the methods
| | 05:41 | that are designed to be called directly
by the Flex Application. There is a
| | 05:45 | method called Get ID that allows you
to pass in a primary key value and
| | 05:49 | retrieve a single object. There is a Safe
Method that allows you to pass in a
| | 05:54 | Bean Object and detects whether it's a new
or existing data object based on its
| | 05:59 | PERSONID value. If the value of the primary
key is zero, it assumes as it's a
| | 06:04 | new object and calls the DAO class' create
method. Otherwise it assumes, it's
| | 06:09 | an existing object and calls the DAO object's
update method. Again notice that
| | 06:14 | these functions have an access property of
remote, which means that we can call
| | 06:18 | them directly from the Flex Application.
| | 06:21 | There is a function named deleteById, which
receives a primary key value and
| | 06:26 | calls the DAO Object's delete method and
two methods for retrieving all the
| | 06:31 | data from the table. One named getAll that
executes a query against the entire
| | 06:35 | database and then creates an array of instances
of the value object or the Bean
| | 06:41 | Object and returns that. Then another one
called get all as query, that returns
| | 06:46 | the query object directly. These are the
two functions I am going to describe
| | 06:51 | using from a Flex Application, now in the
next video I am going to describe how
| | 06:55 | to use these two functions getAll and
getAllAsQuery and show you the
| | 06:59 | differences between the functions and how
they are actually handled, when the
| | 07:03 | data is returned to Flex.
| | Collapse this transcript |
| Retrieving data with the generated code| 00:00 | In this video, I am going to describe
how to call public functions of the
| | 00:04 | ColdFusion component generated by the
ColdFusion value object wizard. I am
| | 00:09 | going to use the application from the
Chapter08Begin project that I created
| | 00:13 | earlier named UseCFWizardCode.mxml. This
application currently has only a label
| | 00:20 | that displays the text ColdFusion Wizard Code.
| | 00:24 | Start off in the application by creating
RemoteObject component and set it's id
| | 00:29 | to personGateway. This will be a RemoteObject
component that refers to the
| | 00:34 | Gateway component on the server. Set it's
destination as I described in the
| | 00:39 | previous chapter on using ColdFusion components
from Flex. Set the destination
| | 00:44 | to ColdFusion. Pay attention to the case
and spelling. It should be spelled
| | 00:49 | with an upper case C and F and no spaces.
| | 00:53 | Now add the source attribute. The source
is determined by the location and name
| | 00:58 | of the ColdFusion component on the server.
Go to your CFEclipse project which
| | 01:03 | on my system is named Flex3btbCF. Open the
CFC folder and then select the file
| | 01:10 | PERSONGateway.cfc and double click to open.
| | 01:14 | This again is the Gateway component that
you will be calling directly from
| | 01:17 | Flex. Now browse the component so that
you can look at the component's
| | 01:21 | documentation. Go to the CFEclipse toolbar
and click the number 1 to open in an
| | 01:28 | external browser. You will need to type in
your RDS or Administrative Password
| | 01:33 | for ColdFusion and then Login and then
you should immediately see the
| | 01:38 | documentation for the new component.
| | 01:41 | Notice again that the component has five
functions, each marked as remote and
| | 01:46 | each describing what you pass in and what
you get back. For example, the
| | 01:48 | getAll function returns an array of Person
components which you will see right here.
| | 01:55 | The getAllAsQuery function returns a query
object. The getById function returns
| | 02:02 | a single instance of the being or value object
component and the Save function
| | 02:08 | receives a single object and either updates
or creates that object in the database.
| | 02:14 | Go back to the top of the documentation and
locate the fully qualified name and
| | 02:19 | location of the Gateway component as it's
known to ColdFusion. Select and then
| | 02:25 | Copy that to the Clipboard then close the
browser and return to Flex Builder,
| | 02:31 | go back to the Application and then Paste
that information into the Source
| | 02:36 | Property of the remote object component declaration.
This is now a RemoteObject
| | 02:41 | that points to the Gateway object.
| | 02:44 | Next, create a Script section above the RemoteObject
tag set. Within the Script
| | 02:50 | section declare a new variable named
acPerson data typed as an Array
| | 02:55 | Collection. When you select the Array
Collection class from the list of
| | 02:59 | available classes, Flex Builder should automatically
add an import statement
| | 03:03 | for the class for you. Next, add a resultHandler
function. Declare the function
| | 03:10 | with the Syntax private function resultHandler.
Set up the resultHandler
| | 03:16 | function to receive an event argument typed
as ResultEvent and return void.
| | 03:23 | Now go down to the RemoteObject component
and add a resultevent listener using
| | 03:28 | an attribute and call the resultHandler
function passing in the event object.
| | 03:34 | The final step in this part of the process
is to go to the Application tag and
| | 03:38 | add an applicationComplete event listener
and here, I am going to call one of
| | 03:43 | the two functions that returns all
of the data from the server.
| | 03:47 | The first is going to be the getAllAsQuery
function which returns an actual
| | 03:51 | query object. Use this syntax personGateway.getAllAsQuery().
Remember to add
| | 04:00 | the opening and closing parenthesis after
the function name. I am going to
| | 04:05 | reformat the code here, so we can see all
of it on the screen at the same time.
| | 04:09 | So as the application starts up, it's going
to make a call to the ColdFusion
| | 04:14 | server and when the data is returned this
function named resultHandler will be
| | 04:18 | triggered.
| | 04:20 | Add a breakpoint at the line that contains
the finally brace of the function on
| | 04:25 | my system it's at line 16. Save and Run the
application in Debug mode. So that
| | 04:31 | you can inspect the data that returns
from the server. When the data is
| | 04:36 | returned from the server, you should be
triggered to open the Flex Debugging
| | 04:39 | perspective in Flex Builder.
| | 04:42 | Now go to the Variables View and expand
it to Full Screen by double clicking
| | 04:45 | its tab. Go to the event object which is
data typed as the ResultEvent class,
| | 04:52 | Open it to see its properties and go to
the Result. Notice that because the
| | 04:57 | ColdFusion Code returned a query object,
the result is data typed as an Array
| | 05:02 | collection. The ArrayCollection contains
multiple objects each of which
| | 05:07 | contains the various properties
from the database table.
| | 05:11 | Now restore the variables view and terminate
your Debugging session. On some
| | 05:15 | systems that will also the browser and then
expand the code to full screen and
| | 05:20 | let's make a change. Go back to the application
complete function and this
| | 05:25 | time, instead of using the getAllAsQuery
function call the Gateway components
| | 05:29 | getAll function which returns an Array rather
than a query. Save your changes,
| | 05:36 | once again, run the application in Debug
mode. As the application starts up it
| | 05:42 | makes the call to the server and then
because I am already in the Debug
| | 05:45 | Perspective it brings me immediately to Flex
Builder when I hit the breakpoint.
| | 05:51 | The next step is to restore the size of
the editors if they come up in this
| | 05:55 | fashion. You can click this Restore right
next to the tabs and then go to the
| | 06:00 | Variables View and double click to expand
and this time, you should see that
| | 06:05 | the returned data comes back as an array
rather than an ArrayCollection.
| | 06:10 | Notice however, that the individual objects
that are returned as the part of
| | 06:14 | the array are typecast as object, rather
than as that strongly typed Person
| | 06:20 | class that we had seen created before
and here is why. Once again, I will
| | 06:25 | return to the code and terminate the debugging
session. We have an action
| | 06:30 | Script class named PERSON.as which was
generated by the ColdFusion wizard.
| | 06:35 | This value object component automatically
has been populated with the
| | 06:39 | declaration named RemoteClass which has
an alias pointing to the component on
| | 06:44 | the server including at both its CFC name
and its package. This is a two-way
| | 06:50 | mapping that tells Flex and ColdFusion,
when you pass an instance of this
| | 06:54 | ActionScript class ColdFusion, it should
be transformed into the ColdFusion
| | 06:58 | component of the same name and when an instance
of that component comes back
| | 07:02 | from ColdFusion, it should be transformed
into the ActionScript class. So all
| | 07:07 | the code in place, why isn't it working?
| | 07:11 | The answer is because unless you have actually
declared at least one instance
| | 07:15 | of this ActionScript class in your Flex
application, this mapping that I have
| | 07:20 | selected isn't a part of the application.
In order for the mapping and the
| | 07:24 | action script code to be a part of the application,
you must declare at least
| | 07:28 | one instance of it.
| | 07:29 | So I am going to come back to the main application
code. I am going to return
| | 07:33 | to the application and to clear one instance
of the component using this code,
| | 07:39 | private var currentPerson and then I will
data type to PERSON which is the name
| | 07:46 | of the ActionScript class that was generated
by the ColdFusion wizard.
| | 07:50 | Notice that I am not actually instantiating
the class, I am just declearing an
| | 07:54 | instance of it and that's enough to add
the class definition to the compiled
| | 07:58 | application including it's two-way mapping.
I will Save the changes and run the
| | 08:03 | application in the Debug mode one more
time. Once again is the application
| | 08:08 | start should makes the call to the ColdFusion
server and upon the data is
| | 08:12 | returned, we hit the breakpoint.
| | 08:14 | I restore the size of the various editors
and then go the Variables view and
| | 08:19 | now notice that the Array contains multiple
instances of the person class.
| | 08:24 | That's exactly how you want to store the
data in your Flex application. So one
| | 08:30 | final step, I will terminate the debugging
session and go back to the
| | 08:33 | application code. Within the resultHandler
function, I am going to fill in the
| | 08:38 | value of array collection using this syntax
acperson = new ArrayCollection and
| | 08:46 | I am going to pass in the event.result property
as an Array. I know that I am
| | 08:54 | getting back in array because I debugged
and inspected the data and because the
| | 08:58 | compiler expects event.result to be an object,
I have to exquisitely typecast
| | 09:04 | it as an Array here and then I pass it into
the ArrayCollections constructor
| | 09:08 | method and now the data is an ArrayCollection
that can manage the data at runtime.
| | 09:13 | I place the cursor after the label and add
a DataGrid component to display the
| | 09:17 | return to data and I will set its data provider
using a binding expression to
| | 09:21 | the ArrayCollection, acPerson. I'll Save
the changes and this time I am going
| | 09:27 | to run the application in normal mode and
as the application starts up, it
| | 09:32 | retrieves the data from the server
and displays it in the DataGrid.
| | 09:37 | What you now have in memory is an ArrayCollection
containing multiple instances
| | 09:41 | of the strongly typed value object class
person. In the next video, I will show
| | 09:46 | you how to use that data that you now have
in Flex application memory to allow
| | 09:50 | the user to view and modify the data that's
managed by the ColdFusion server.
| | Collapse this transcript |
| Modifying data with the generated code| 00:00 | In this video, I am going to describe
how to incorporate code that was
| | 00:04 | generated on the server by the ColdFusion
Value Object wizard, that allows you
| | 00:08 | both to retrieve and display data, but also
allows you to send commands to the
| | 00:12 | server to modify the data in databases
that are managed by the ColdFusion
| | 00:16 | server. For the demonstrations in this video
I will use some prepared code that
| | 00:21 | you will find in the Exercises folder.
| | 00:23 | If you have access to the Exercises folder
and you are following along with the
| | 00:26 | Exercises, go to the Exercises folder which
I have installed on my desktop and
| | 00:31 | from there to the Chapter08 folder and from
there to Chapter08Begin. You will
| | 00:37 | find three folder in one file named ModifyData.mxml.
Select all three folders
| | 00:43 | and the Application File and copy them to
the Clipboard. Then go back to Flex
| | 00:48 | Builder go to the source folder within the
Chapter08Begin project and paste the
| | 00:54 | folders in file. Then navigate to the ModifyData.mxml
application file, right
| | 01:01 | click on it or Control+Click on the Mac and
select Set as Default Application.
| | 01:05 | That will cause the application to be compiled
and be ready to use. Then double
| | 01:11 | click the file to open the application code
in Flex Builder. This application
| | 01:16 | already has an instance of the RemoteObject
component that makes a call to the
| | 01:20 | CFC function on the server to retrieve data.
| | 01:23 | When the user runs the application, they
see the data filled in and displayed
| | 01:28 | immediately in a DataGrid control. They can
then select a row from the DataGrid
| | 01:32 | by double clicking on it and that results
in presenting the data in a data
| | 01:37 | entry form. The data entry form control itself
is a custom component and it is
| | 01:43 | stored in the Forms folder within the Project
Source. When the user clicks the
| | 01:48 | Save button any changes that are dispatched
to the rest of the application in a
| | 01:52 | custom event named the Person event and you
can handle that event and send the
| | 01:57 | data to the server.
| | 01:59 | Let's take a look at the code. I'll close
the browser and returned to Flex
| | 02:03 | Builder. At the top of the application, there
is a declaration of a State. This
| | 02:10 | is how the data entry form is being presented.
When the user double clicks on a
| | 02:14 | row of the DataGrid that results in calling
a method named editRecord and this
| | 02:19 | method passes the selected item from the
DataGrid into the form using its
| | 02:23 | current person public property and changes
the current state to detail.
| | 02:28 | Let's take a look at the Form. In the Form
component, there is a Metadata tag
| | 02:34 | set that defines two events, one named save
and other named cancel. When the
| | 02:38 | user clicks the Save button, it calls the
saveRecord functions, which saves all
| | 02:43 | of the data from the input controls into
a new instance of the person object
| | 02:47 | and then wraps it inside a custom
event object and dispatches it.
| | 02:51 | This is the data that we want to send to
the server. Go back to the application
| | 02:57 | and locate the component named PersonForm,
notice again that we are calling a
| | 03:01 | method called saveRecord which is an empty
method within the application. Place
| | 03:07 | the cursor within that method. The event
object that's dispatched to this
| | 03:12 | function will be an instance of the person
event class which in turn has an
| | 03:16 | instance of the person object.
| | 03:18 | So first declare a variable named person
and data type it as PersonVO which is
| | 03:25 | the version of the Value Object for this
application and get its value from the
| | 03:31 | expression event.person. Now place a
breakpoint on the last line of the
| | 03:35 | function that is the line with the closing
brace and run the application in Debug mode.
| | 03:40 | When the data appears, double click on one
of the items, make a change such as
| | 03:50 | changing the name Miriam to Mary and then
click Save. That should take you to
| | 03:56 | the breakpoint that you placed in the saveRecord
function. Go to the debugging
| | 04:02 | perspective and then to the Variables view
and take a look at the value of the
| | 04:07 | person variable.
| | 04:08 | You will see that it's an instance of the
personVO and whatever data values you
| | 04:12 | changed in the form should be reflected.
Now restore the variables view and
| | 04:17 | then click the Resume button in the debug
view, switch back to the application
| | 04:22 | and click the Cancel button that will
take you back to the list.
| | 04:26 | This time, click the New button, you will
see the form opens with blank values,
| | 04:32 | click the Save button, that will take back
to the breakpoint and once again,
| | 04:36 | view the value of the person variable and
this time, you will see it's starting
| | 04:40 | off with blank values. Again, these are
the values they are coming from the
| | 04:44 | data entry form, but they are the Default
Values of the value object.
| | 04:48 | So here is how you are going to save the
data to the server. Once again,
| | 04:52 | restore the variables view and terminate
debugging and then go back to the
| | 04:57 | Code. The ColdFusion component that's designed
as the Gateway on the server has
| | 05:03 | a function called Save. It's designed to
receive the single instance of this
| | 05:07 | Value Object. So I am going to call that
CFC function with this syntax,
| | 05:13 | personGateway.save and then I will
pass in the person object.
| | 05:18 | Now let's go to the RemoteObject declaration.
Notice that there is already a
| | 05:23 | function saveHandler, it's an empty function
that's already been declared and
| | 05:27 | it receives an event object typed as ResultEvent.
Break up the RemoteObject
| | 05:32 | declaration into a begin tag and an end tag
and then add an mx:method complier
| | 05:37 | tag with the name of save and a ResultEvent
handler that calls the method
| | 05:43 | saveHandler and passes the event object.
| | 05:47 | Now go to the saveHandler function and
when the data has been saved to the
| | 05:51 | server, you can react by refreshing the
view of the data and making a call to
| | 05:56 | get all records again, using this code,
personGateway.getAll. Now here is the
| | 06:02 | logic that we are using, the mx method tag
declares a ResultEvent listener for
| | 06:08 | that particular method, the Save method,
but the getAll method doesn't have its
| | 06:13 | own mx method tag at least at this point
and so it's going to use the Default
| | 06:17 | Result listener for the RemoteObject component.
| | 06:21 | Let's watch the results. Save and Run the
application this time in standard
| | 06:26 | mode, select any item from the person list
and just double click on it to open
| | 06:33 | it in the Form and make a change. For instance,
I am going to have this guy
| | 06:37 | move from Syracuse to New York city and I
click the Save button and then take a
| | 06:44 | look up here in the Form and you will see
that his city has changed to New
| | 06:48 | York, but also notice that I haven't cleared
the form or restored the ability
| | 06:52 | to get to that List Control.
| | 06:54 | So I have one more little bit of code to
add in this saveHandler function. I am
| | 06:59 | also going to Reset the current state back
to the default or Base State using
| | 07:04 | this code currentstate = null. You can
set the current state either a blank
| | 07:10 | string of "" (quote quote) or to null, that
will have the same effect. I will
| | 07:15 | run the code again and test again. I once
again double click on Brad Lang, this
| | 07:22 | time I will set his city back to Syracuse.
I will save and after just a moment
| | 07:29 | you will see that the data is
refreshed from the server.
| | 07:32 | Now let's try adding a new record. I will
click New and I will add some data. I
| | 07:37 | will set the Name as Adam and the Last Name
as Aardvark and I will give him an
| | 07:43 | address and you can type anything at this
point and then click the Save button
| | 07:50 | and then sort the data by Last name and
you should see that the new row has
| | 07:54 | been successfully added to the database.
| | 07:57 | Now let's take a look at deleting data.
If you go down to the bottom of the
| | 08:01 | application, you will notice that there
is a button with the label of Delete,
| | 08:05 | which is calling a method called deleteRecord.
Let's go to the deleteRecord
| | 08:09 | method and you are going to call a remote
CFC function called deleteById. It
| | 08:14 | will look like this, personGateway.deleteById
and then you are going to go get
| | 08:19 | the selected item from the DataGrid and it's
PERSONID property and pass it in.
| | 08:24 | The code will look like this.
PersonGrid.selectedItem.PERSONID.
| | 08:32 | I am uppercasing the name of the property
because that's how it's returned from the
| | 08:35 | server and that's how it's stored
within the component.
| | 08:39 | I make those changes then notice that there
is already a function here called
| | 08:45 | deleteHandler. I'll add a new mx method complier
tag for that method and I will
| | 08:51 | set the name as deleteById and set the result
to deleteHandler and once again,
| | 08:59 | pass the event object. Going back to the
deleteHandler, I will copy the code
| | 09:03 | from the safeHandler function that refreshes
the data from the server and paste
| | 09:09 | it into the deleteHandler and now once again,
after the data has been deleted
| | 09:12 | from the server, I am going to recall the
data from the server and display it all.
| | 09:16 | I will run the application again. After
the data has been loaded and has been
| | 09:21 | displayed in the application, I once again
sort on the Last Name column, select
| | 09:26 | Adam Aardvark and Delete and you will see
that the data is now gone and if I
| | 09:32 | re-sort you will see that Adam Aardvark
is no longer in the database. So this
| | 09:37 | is how we use the code on the server. To
retrieve all of the data, you use the
| | 09:41 | getAll method, to save either new or existing
data you call the Save method and
| | 09:47 | to remove data from the server side database
you call deleteById and passing
| | 09:51 | the primary key value of the row
that you want to delete.
| | Collapse this transcript |
| Defining RemoteObject channels at runtime| 00:00 | In this video, I am going to describe
how to define a channel at runtime
| | 00:05 | through which you communicate with the
ColdFusion Server. A Channel is a
| | 00:08 | definition of how to communicate and where
to communicate when you send a
| | 00:12 | remote object request, using the remote object
component in a Flex application
| | 00:17 | and a CFC on the ColdFusion Server.
| | 00:20 | By default, the Channel is defined in a
file in the ColdFusion server called
| | 00:24 | services-config.xml. Let's take a look at
that file. I am going to select File
| | 00:30 | Open and then I am going to navigate
to the WWW root folder under the
| | 00:34 | ColdFusion8 installation. Under that folder
go to WEB-INF, from there to Flex
| | 00:42 | and from there to a file named
services-config.xml.
| | 00:48 | This is the file that configures all of
your ColdFusion functionality and in
| | 00:52 | fact, this file is bound into your project
in Flex Builder and it's how the
| | 00:56 | ColdFusion destination is known to the
remote object component in your Flex
| | 01:01 | application. Within the services-config file
there is a setup what are known as
| | 01:07 | channel-definitions and the default channel-definition
that you use with
| | 01:11 | ColdFusion is down here under cf based endpoints.
It's a definition with an id my-cfamf.
| | 01:21 | The endpoint within the channel-definition
defines the location of the server
| | 01:25 | to which communications are sent at runtime
as the same server from which the
| | 01:29 | Flex application is downloaded. That's what
these dynamic expressions are doing
| | 01:33 | in the URI property, and then the URI ends
with the URL pattern that is then
| | 01:39 | used by ColdFusion to detect when a Flex
communication is coming in as opposed
| | 01:44 | to a conventional browser request.
| | 01:47 | So it's possible to create your own channels
within an application and not use
| | 01:52 | the channels that are defined say, in the
services configuration file. This can
| | 01:56 | be especially important if you are working
with an application that's delivered
| | 02:00 | over AIR, the Adobe Integrated Runtime,
as a desktop application, where you
| | 02:04 | don't download an application from a server
at runtime and don't have access to
| | 02:08 | this dynamic information.
| | 02:11 | So in this video I want to show you how to
define one of these runtime channels
| | 02:15 | in your Flex application using mxml code.
I am going to return to the Flex
| | 02:21 | Development perspective and then reopen
the file ModifyData.mxml. This is the
| | 02:27 | application that I worked on in the previous
video, then I will navigate down
| | 02:31 | to the remote object component which is about
at line 74 in my version of file
| | 02:36 | right now. In order to define a channel,
you first create something called a
| | 02:42 | channel set. It's actually possible to create
a set of channels and then the
| | 02:47 | RemoteObject component will try each channel
in turn until it finds when it can
| | 02:51 | communicate with.
| | 02:54 | Place the cursor after the Remote Object
start tag and make a little bit of
| | 02:58 | space before the method declarations, then
declare an mx channelSet property
| | 03:04 | using child element syntax. That means we
are using a paired tag. Now within
| | 03:09 | the channelSet tag, declare another channelSet,
but this is with an upper case
| | 03:14 | C meaning that it's an instance of an actual
class. Once again, declare this
| | 03:19 | with a pair of tags and now you are ready
to declare the actual channel that
| | 03:25 | you will use to communicate with
the ColdFusion server.
| | 03:27 | We are communicating over AMF, Action Message
Format, the binary messaging
| | 03:33 | format that allows communication between
a Flex application and ColdFusion to
| | 03:37 | be very fast and very small. So we are going
to use a class called AMFChannel.
| | 03:44 | Declare the AMFChannel tag and
then set its URI property.
| | 03:49 | The URI property should start with the
absolute address of the ColdFusion
| | 03:53 | server with which you want to
communicate like this,
| | 03:56 | http://localhost:8500/flex2gateway/ and
then end it with Flex 2gateway just
| | 04:05 | like you saw in the services configuration
file. Close the AMF channel tag,
| | 04:13 | Save your changes and run the application
again. As the application starts up,
| | 04:19 | it should once again display the data,
but this time we are configuring the
| | 04:23 | location of the ColdFusion server as
the application starts rather than
| | 04:27 | depending on the version that's in
the services configuration file.
| | 04:32 | Now as I mentioned, there is a section in
the Project Properties that indicates
| | 04:36 | which configuration file is going to be
used. Go to the Menu and select the
| | 04:40 | Project, Properties and from there go to
the Flex Compiler section. Notice in
| | 04:47 | the Flex Compiler section there is a Services
property that's pointing to the
| | 04:52 | Service-config.xml file, that's in the
WEB-INF folder under your ColdFusion
| | 04:56 | document root.
| | 04:58 | So that's how all the configurations
are being bound together. This
| | 05:02 | configuration file is actually compiled
into your application. So the
| | 05:06 | definition where of your ColdFusion server
is a part of the application. By
| | 05:11 | using runtime channel declarations, you
can overwrite those settings and to
| | 05:16 | clear at runtime which ColdFusion server
you want to communicate with.
| | Collapse this transcript |
| Managing an asynchronous state with AsyncToken| 00:00 | In this video, I am going to describe how
to use a class called AsyncToken
| | 00:04 | which allows you to track the state of
objects between the time you send a
| | 00:08 | request to a server, using a RPC components
such as the RemoteObject Component
| | 00:13 | and the time the response comes back. For
this demonstration, I'll continue to
| | 00:17 | work on the application file ModifyData.mxml.
| | 00:21 | Right now in this application, whenever
we save or update data and a response
| | 00:25 | comes back from the server, we are reacting
by refreshing all of the data from
| | 00:29 | the database in the server by calling the
Gateway components getAll method
| | 00:32 | again. This is a bit of overkill.
| | 00:35 | We have only modified one row of the database
table and yet we are retrieving
| | 00:39 | all of the data from the server. By using
the AsyncToken class to track the
| | 00:43 | State between the time you send the request
and the time you get back the
| | 00:46 | response, you can fine-tune in the way you
react to these events and only deal
| | 00:51 | with those single data objects that was
modified or deleted. Here is how you
| | 00:54 | use the AsyncToken class.
| | 00:57 | Start off at the ActionScript code that's
making the call to the remote CFC
| | 01:01 | function. I am going to the saveRecord
method which has a call to
| | 01:05 | personGateway.save. Every time you make
a call to a remote function using our
| | 01:09 | RPC component you get back reference to an
AsyncToken object. The nature of an
| | 01:14 | AsyncToken is that it's a dynamic object
to which you can add as many arbitrary
| | 01:19 | named properties as you want.
| | 01:21 | The first step is to get a reference to the
token, like this. Place the cursor
| | 01:25 | before the code personGateway.save, make
an extra line and add this code var
| | 01:31 | token data typed as AsyncToken = and then
indent the next line of code because
| | 01:39 | you are getting the reference from the call
to the remote CFC function. Now you
| | 01:43 | have a reference to the token and you can
add as many named properties as you
| | 01:47 | want. I only need to add one. I am going
to add a reference to the actual value
| | 01:52 | object that I send to the server. The code
will look like this, token.person =
| | 01:59 | person. Now I have saved a reference to that
in memory data object and I'll be
| | 02:04 | able to get it back when I get a result
event back from the server.
| | 02:07 | Go down to the saveHandler method. Right
now we are recalling the getAll CFC
| | 02:13 | function and refreshing all of the data.
We don't need to do that, so I am
| | 02:16 | going to comment out that line of code
and then make a little bit of extra
| | 02:20 | space between that and the change to the
current state. Now, I am going to get
| | 02:24 | a reference to the person object that I sent
off to the server using this code,
| | 02:29 | var person data typed as the value object
class I am using for this application
| | 02:35 | PersonVO = event.token.person.
| | 02:41 | The token property is a member of the ResultEvent
class. Every time an RPC
| | 02:46 | comment dispatches a result event. You
have a reference to the AsyncToken
| | 02:50 | object that's associated with that event
and because I had added the person
| | 02:54 | property to the token earlier, when I sent
the request to the server it's still
| | 02:58 | there when the result event is dispatched.
| | 03:01 | Now I am going to inspect the person object
and find out whether I would send
| | 03:05 | in a new object or an existing object
using this conditional code. If
| | 03:10 | person.PERSONID == 0. So if the PERSONID
property is 0 that means it was a new
| | 03:18 | object and then I'll add an else clause
to handle existing objects.
| | 03:23 | Now if I sent an object off to the server,
it started off with a primary key of
| | 03:28 | 0, but when it comes back from the server,
it is actually going to have the new
| | 03:32 | automatically assigned primary key that
was assigned and created by the
| | 03:35 | database. If you go back to the Gateway
code, you will see that the Gateway
| | 03:39 | code always returns an instance of the
person object and if you called the
| | 03:44 | Create method, you will get back to Person
Object with the new primary key.
| | 03:48 | So here is how I am going to handle new
data, instead of using the existing
| | 03:52 | person variable, I am going to use the version
that comes back from the server.
| | 03:56 | So I'll say person = events.result as PersonVO.
Then I am going to manage the
| | 04:04 | Datagrid's appearance. First, I am going
to set at selected item to this data
| | 04:09 | object because it's now in the Array
collection which the DataGrid is
| | 04:12 | presenting and then I am going to make
the DataGrid scroll to the correct location.
| | 04:16 | I'll use this code, personGrid.slectedItem=
person and then in a separate
| | 04:24 | statement personGrid.scrollToIndex and
I will pass in the current selected
| | 04:31 | index of the grid which is now already set
because I already set the selected
| | 04:35 | item. Now in the other condition where I
passed the Value Object to the server
| | 04:44 | to make a change, once again, I am going
to get back that object from the
| | 04:47 | server, but this time I am going to replace
in the correct position in the
| | 04:51 | Array collection using this code. acPerson.setItemAt,
then I am going to pass
| | 04:57 | an event.result as PersonVO and then I'll
pass in the currently index of the
| | 05:04 | grid to indicate where I want to put
it, PersonGrid.selectedIndex.
| | 05:13 | So I am replacing the old data in the local
dataset with the version they came
| | 05:17 | back from the server. I will save my changes
and run the application and let's
| | 05:21 | take a look at the result. I will select
and double click on the first row of
| | 05:26 | the DataGrid to edit it's details then
I will change some of the data. This
| | 05:30 | time I will change his name from Lang to
Smith and I will Save and once again
| | 05:37 | you see that the data has changed in the
DataGrid, but this time, it didn't
| | 05:40 | require another round trip to the server
and it didn't require retrieving all
| | 05:44 | the data from the database table.
| | 05:47 | Now I will add a new item to the database.
I will put in once again Adam
| | 05:52 | Aardvark. I will click Save and this
time notice that I scrolled to and
| | 05:58 | displayed the row that I want the user to
see. So I no longer have to sort or
| | 06:03 | otherwise, navigate to the right row. Now
handling Delete is very similar, I
| | 06:07 | will go back to the code to the method deleteRecord
and I am going to repeat
| | 06:11 | the same pattern.
| | 06:12 | When I call the remote CFC function I will
get back a token. So I am going to
| | 06:16 | once again declare a variable data typed
as AsyncToken var token datatyped as
| | 06:23 | AsyncToken = and then I am going to get
that reference from the call to
| | 06:30 | deleteById. Now I am going to add a property
to the token object. In order to
| | 06:35 | remove an item from the Array collection
in the Handler, I am going to have to
| | 06:39 | know the index of the currently selected
row in the DataGrid. So here is the
| | 06:43 | code for that, token.index =
PersonGrid.selectedIndex.
| | 06:50 | Now go down to the deleteHandler function.
Once again, comment out the call to
| | 06:54 | the getALL method, we won't need to do that
anymore and instead put on a call
| | 06:58 | to the acPerson, Array collection object
and call it removeItemAt property and
| | 07:04 | pass in event.token.Index and that's going
to be the Index that was passed into
| | 07:10 | the token object, when I made the call to
delete the record from the database
| | 07:13 | at the server level. Save your changes,
run the application. When the
| | 07:19 | application starts up, go to any row of
the database. I am going to sort by
| | 07:23 | Last Name and get to the row that I had
created earlier. I will click the
| | 07:27 | Delete button and you will see that the
data is removed both from the server
| | 07:31 | and from the client. But once again, without
requiring that additional round
| | 07:35 | trip to the server and without requiring
loading all of the data from the
| | 07:38 | server back in to the client.
| | 07:40 | So that's a look at how you can use the AsyncToken
class to manage information
| | 07:45 | and state between the time you send a request
to the server and the time you
| | 07:48 | get back a response. You can add as many
named properties that reference
| | 07:52 | whatever kind of objects you need to track
and use that information to manage
| | 07:56 | the visual presentation of your application
and reduce the number of calls you
| | 08:00 | need to make to your server.
| | Collapse this transcript |
|
|
9. Integrating with PHPInstalling WAMP on Windows| 00:00 | In this chapter of the video series, I
am going to describe strategies for
| | 00:04 | integrating Flex Client application with
PHP. In Flex Builder 3, Adobe systems
| | 00:09 | has now provided tools that allow you
to inspect MySQL databases that are
| | 00:13 | exposed through PHP and then generate Server-Side
PHP code, that you can easily
| | 00:18 | integrate into a Flex Client application
that in turn, allows you to view data
| | 00:22 | and modify data on the server quite easily.
| | 00:25 | For the exercises in this chapter, i'll
be using PHP 5 in MySQL and I'll be
| | 00:30 | using a bundle of server options known as
WAMP on Windows or MAMP on the Mac.
| | 00:36 | In this video I'll describe how to install
up the Windows version knows as WAMP
| | 00:40 | for Windows Apache MySQL and PHP and in this
next video I'll describe how to do
| | 00:45 | the same thing on the Mac with MAMP.
| | 00:47 | The first step is to download the WAMP
installer. You can find the WAMP
| | 00:51 | installer and download it for free from this
URL, www.en.wampserver.com. I have
| | 00:58 | already downloaded the software to my
desktop. The version I found was
| | 01:02 | WampServer2.0C.exe. Before you install WAMP
you should first make sure that you
| | 01:08 | don't have any other web servers that
are listening on Port AD that's the
| | 01:12 | default port that's used for example by internet
information services. When you
| | 01:17 | install the WampServer bundle, the Apache
Server that's a part of that
| | 01:20 | installation will listen on Port AD and if
you have a web server that's already
| | 01:24 | listening on that port, it
can generate a conflict.
| | 01:26 | I am working on a system that does not have
any other web services installed
| | 01:30 | right now. So I am going to go ahead with
the installation by opening the EXE,
| | 01:35 | stepping through a set of information on
warning screens and then coming to the
| | 01:40 | welcome screen. After the welcome screen
there is a License Agreement, which is
| | 01:45 | based on the GNU, General Public License.
Essentially, it means that you are
| | 01:49 | free to use this server without
having to pay any fees.
| | 01:53 | After the license screen you are asked
where to install WAMP. The default
| | 01:57 | location is in a folder named WAMP under
the C drive root. I am going to accept
| | 02:02 | that default setting and throughout all of
the demonstrations in this chapter,
| | 02:05 | I'll be assuming that my code for the server
is in this physical location. I'll
| | 02:10 | go to the next screen and check a couple
of options. I am not going to put in a
| | 02:14 | Quick Launch Icon or Desktop Icon and I don't
need them and I'll click through
| | 02:18 | and complete the Installation.
| | 02:20 | The installation of WAMP takes about two
minutes. Once the installation is
| | 02:24 | complete you will be ready to fire up the
server which you will be able to do
| | 02:28 | from System Tray Menu that you can click
on in the lower right hand corner of
| | 02:32 | the Windows interface.
| | 02:35 | Once the primary installation is complete,
the WAMP Installer looks for a web
| | 02:39 | browser. If it finds Firefox, it asks if
you want to use it as is shown here on
| | 02:44 | the screen. I'll click Yes and now whenever
I navigate to the Home or
| | 02:48 | Configuration pages of the WampServer
bundle, I'll be using the Firefox browser.
| | 02:55 | The next step in the installation process
is to enter an SMTP server and
| | 03:00 | address an e-mail. If you want to be able
to use the mail function on PHP. Now
| | 03:04 | I don't have an SMTP server on this system
and I don't really care what the
| | 03:08 | primary e-mail address is because I won't
be using that feature during these
| | 03:12 | demonstrations. So I'll just accept the Default
Settings and click Next. That's
| | 03:16 | the end of the installation process. You
have the option of launching the
| | 03:19 | servers immediately. I am not going to do
that because I want to show you how
| | 03:23 | to launch the WampServer later on once you
have installed it and need to get
| | 03:26 | back to it again. I'll click Finish and
now I'll go to the Windows Menu and I
| | 03:32 | will click on All Programs and locate the
folder WampServer. From there, I'll
| | 03:38 | locate the Menu item start WampServer
and select it.
| | 03:41 | When you start the WampServer bundle, you
will see a System Tray icon in the
| | 03:45 | lower right hand corner of your screen.
It looks like a gauge and when the
| | 03:49 | pointer on the gauge is all the way over
to the right, that means your server
| | 03:52 | is ready to use. You can click the gauge
and you will see this Administrative
| | 03:56 | Menu that allows you to control the
services and get into the various
| | 04:00 | administrative tools. For example, I am going
to first select Put Online, which
| | 04:05 | means I am going to make the server available,
then I'll go down to the System
| | 04:09 | Tray icon again and this time
I'll select Local Host.
| | 04:14 | Local Host takes me to the Homepage of the
WampServer Bundle, where I can see
| | 04:18 | the status of all the various services an
also I can find links to the some of
| | 04:21 | the most important programs. I am also going
to go back to the Menu and show
| | 04:26 | you that you can easily get into a web
application named phpMyAdmin which
| | 04:30 | allows you to manage your MySQL server.
I will be using this interface in a
| | 04:35 | later video when I show you how to import
a database from an SQL file that's
| | 04:39 | the part of the exercises for this video
series. Now in the next video, I'll
| | 04:43 | show you how to do exactly the
same steps using Mac OS X.
| | Collapse this transcript |
| Installing MAMP on Mac OS X| 00:00 | In this video, I am going to describe how
to install MAMP, the Server bundle
| | 00:04 | that includes Apache, MySQL and PHP for Mac
OS X. There are two versions of the
| | 00:09 | MAMP server bundle, MAMP Pro and the simpler
MAMP. MAMP itself is completely
| | 00:14 | free and can be used without registration
or paying any license fees. You can
| | 00:19 | download the MAMP bundle from the website
I am displaying on the screen.
| | 00:22 | www.mamp.info From the home page, click
on the Download now button and then
| | 00:29 | download the DMG installer. This installer
includes the installations for both
| | 00:34 | the PRO and the Standard version. Then, after
you have completed the download,
| | 00:39 | open the DMG file, review the license agreement
and then if you agree, you can
| | 00:43 | click the Agree button to continue. That
results in mounting the disk image in
| | 00:48 | the DMG file. Now to install MAMP simply
drag the MAMP folder into the
| | 00:53 | Applications folder. It takes just a moment
to complete the installation.
| | 01:00 | Then navigate to the Applications folder
on your Mac hard disk. Then from there
| | 01:05 | locate the new MAMP folder. Open the folder
and you'll find an application file
| | 01:11 | named MAMP. To run the MAMP Server at any
time just open the MAMP application.
| | 01:16 | As long as you have the MAMP server running
you will have access to MySQL,
| | 01:20 | Apache and PHP. When you first install
MAMP, it is configured with custom
| | 01:26 | ports, typically you'll want to go back
to the standard ports that are
| | 01:29 | conventionally used with Apache and MySQL
and here is how you do that. I am
| | 01:34 | going to close the browser and all other
windows and show you that there is
| | 01:37 | actually a MAMP application window that's
opened in the background. From this
| | 01:41 | MAMP application window, I'll click the
Preferences button. Then I will click
| | 01:45 | the ports item at the top of the screen.
Notice the custom ports that are
| | 01:49 | assigned to both Apache and MySQL.
| | 01:52 | In order to work seamlessly with Flex Builder,
you'll want to switch to the
| | 01:55 | standard ports that are normally associated
with these applications. Click this
| | 02:00 | button, set the default Apache and MySQL
ports and then click OK, that will
| | 02:06 | cause both Apache and MySQL to restart.
You may at this point need to type in
| | 02:11 | your administrator password to continue along.
| | 02:15 | In order to check the progress of starting
the Servers, watch the indicator
| | 02:18 | lights on the screen. You can also make
changes to the configurations in a
| | 02:22 | number of different ways. Other options
available in Preferences includes
| | 02:27 | certain PHP options and also certain options
for Apache. Notice for example,
| | 02:32 | that by default the root documents folder
for the Apache server is located
| | 02:36 | under- /Applications/mamp/htdocs. This will
be a critical bit of information
| | 02:42 | that you will need later on, when you set
up a Flex Builder project for use
| | 02:46 | with PHP. I'll be mentioning in a later
video that the document route which
| | 02:51 | points here to /Applications/mamp/htdocs
is the folder in which you create your
| | 02:55 | PHP output folder, when building a Flex
project. You can also start and stop
| | 03:01 | the Servers from the screen. You can click
the Stop Servers button and that
| | 03:05 | will stop both Servers and then you can click
the Start Servers button again to
| | 03:09 | restart. It's also important to know
how to get into a utility named
| | 03:13 | phpMyAdmin. phpMyAdmin is a web interface
that allows you to manage your MySQL
| | 03:19 | server. To get into phpMyAdmin or any of
the other web page utilities, click
| | 03:24 | the Open start page button and then from
there look at the links at the top.
| | 03:29 | Here is the link to phpMyAdmin. I will
click it and it will show the
| | 03:33 | administrative interface for MySQL.
| | 03:34 | You will be using this interface later on
to import a database. When you are
| | 03:40 | done with MAMP just quit the Application,
that shuts down the Servers and
| | 03:45 | allows you to continue with your other work.
Here is one other important tip
| | 03:50 | about working with MAMP. If you go to your
System Preferences and from there to
| | 03:54 | Sharing. Check the Web sharing option. Mac
OS X, includes a copy of the Apache
| | 04:00 | web server. If you have web sharing turned
ON on your Mac, it might conflict
| | 04:05 | with the MAMP server depending
on how it's configured.
| | 04:08 | So if you are having trouble getting the
MAMP Server started, check this
| | 04:11 | option, again it's under System Preferences,
Sharing and make sure that you
| | 04:15 | have this Web Server turned off and then
your MAMP installation should work fine.
| | Collapse this transcript |
| Importing a sample database| 00:00 | In this video, I am going to describe how
to import a sample database into the
| | 00:04 | MySQL Server that's a part of the WAMP or
the MAMP Server bundles. If you have
| | 00:09 | access to the exercise files and you have
already installed the WAMP or MAMP
| | 00:13 | servers, you will be ready
to follow these steps.
| | 00:15 | The exercises files contain a sub folder
named Assets/PHP and within this
| | 00:22 | folder you will find a file called contacts.sql.
The contacts.sql file contains
| | 00:27 | a set of SQL statements that first looks
for a table named person and drops the
| | 00:32 | table if it exists and then recreates it.
The database structure is listed here
| | 00:37 | in this SQL statement. There is a primary
key named personid, that's an integer
| | 00:41 | value and auto increments and then a set
of variable character or string
| | 00:45 | columns that allow you to enter various values.
At the end of the file there is
| | 00:50 | an insert statement that adds one 1000
rows of data. So we have a good
| | 00:53 | significant amount of data to work with.
Here is how you use this SQL file.
| | 00:58 | First go to phpMyAdmin, this is a web based
application that's included with
| | 01:03 | both the WAMP and MAMP installations.
That allows you to manage the MySQL
| | 01:07 | Server, that's a part of the server bundle.
To create a new database, click
| | 01:11 | into the text field with the label Create
new database and then type the name
| | 01:15 | of the database you want to create. I am
creating a database named contacts.
| | 01:20 | Click the Create button and then once you
reach the screen indicating that the
| | 01:24 | contacts database has been created. Click
the Import link at the top of the screen.
| | 01:29 | Now create the database table using the
SQL file, click the Browse button and
| | 01:35 | navigate to the Assets/PHP folder within
the exercises area. Select the file
| | 01:40 | contacts.sql and click Open and then within
the web based interface click Go.
| | 01:47 | It takes just a few seconds to complete the
import of the database table. Once
| | 01:51 | the database table has been created and its
data has been added, you will then
| | 01:55 | be able to browse the database table
using phpMyAdmin once again.
| | 02:00 | To view the data go back up to the top
of the screen and click the database
| | 02:03 | link for the contacts database. You should
now see the person table listed and
| | 02:08 | you can click the first link next to the
name of the table which is the Browse
| | 02:11 | link and you will be able to see that the
data that was listed in the SQL file,
| | 02:15 | is now in the database and ready to use.
So those are the steps for creating
| | 02:19 | the database table and populating it with
data. If you don't have access to the
| | 02:23 | exercise files, you can create the same database
structure using the phpMyAdmin
| | 02:28 | interface and add some sample data. Now
in the next video I will show you how
| | 02:32 | to link up to this database from within
Flex Builder and start to create PHP
| | 02:36 | code that allows you to integrate these
Servers with Flex Applications.
| | Collapse this transcript |
| Creating a Flex/PHP project in Flex Builder| 00:00 | In this video, I am going to describe how
to create a Flex Project in Flex
| | 00:04 | Builder 3, that's integrated with the
Application Server PHP. If you are
| | 00:08 | following along with the exercises, first
make sure that you have installed
| | 00:11 | either WAMP on Windows or MAMP on Mac
and then, that you have the Server running.
| | 00:16 | Before you can create a project correctly,
you must know where the root
| | 00:20 | document folder is for your Application
Server. This will differ depending on
| | 00:24 | operating system and how you have PHP installed.
On Windows, if you are using
| | 00:29 | the integrated Server bundle WAMP, you'll
find that the WAMP folder, where the
| | 00:33 | product is installed, has a sub folder
named www. This is the Root document
| | 00:38 | folder for the WAMP installation.
| | 00:41 | When you create a new Flex project, you'll
want to create the output folder for
| | 00:44 | that project, that is, the folder where you
are outputting the Debug version of
| | 00:48 | the Application into a folder underneath
this www directory. If you are working
| | 00:53 | on Mac OS X, with the Mac Server bundle,
using the default directory, the
| | 00:57 | location of the same document root is under
/Applications/MAMP/htdocs. With
| | 01:04 | both Server bundles you can reconfigure
and point to a different root folder,
| | 01:08 | but these are the default locations. So
once you have that information, the
| | 01:12 | document root of your Application Server
and its hosting Web Server, then you
| | 01:16 | are ready to create a new Flex project
that's integrated with PHP.
| | 01:20 | Here are the steps, from Flex Builder's Menu
select File, New,Flex Project. Set
| | 01:27 | the project name as anything you like. I
am going to set the project name here
| | 01:30 | as Chapter09Begin. The location of the project
itself can be anywhere on disk
| | 01:35 | and I am going to use the default location,
which is a folder with the same
| | 01:39 | name as the project, underneath the current
workspace. Set the application type
| | 01:43 | to Web Application. Now pull down the list
of available Server Types and select
| | 01:48 | PHP. Click the Next button.
| | 01:51 | Now you have to provide the Web root folder
and the Root URL. The Web root, as
| | 01:55 | I mentioned is the location of your document
root folder as configured under
| | 01:59 | Apache and PHP. My root folder is c:\wamp\www.
Now set the Root URL. Under
| | 02:08 | WAMP, the listener port is port AD. So
you can put in a Root URL of simply
| | 02:12 | http://localhost. If you are working in
the MAMP Server bundle, you'll either
| | 02:18 | be using its custom port or more likely
you'll have reconfigured MAMP to use
| | 02:23 | port AD as well. Click the Validate Configuration
button and you should see the
| | 02:28 | message, the Web root folder and root
URL are valid. If you see an error
| | 02:32 | message of any type, check to make sure
that your Server is running and also
| | 02:35 | that you don't have another Web Server running
on the same system, listening on
| | 02:39 | the same port.
| | 02:40 | Now check the recommended output folder.
The output folder is placed by default
| | 02:44 | as a sub folder of your Web Server document
root. As usual the name of the
| | 02:49 | output folder defaults to the same as the
name of the project, in this case
| | 02:52 | Chapter09Begin and ends with dash debug
to indicate that this folder will
| | 02:56 | contain the output version of the finished
application. Click Next, and in the
| | 03:02 | following screen,which looks the
same as for all web based Flex
| | 03:05 | applications,set the Main Application
File. I am going to set the main
| | 03:10 | application file to FlexAndPHP.mxml
and click Finish.
| | 03:16 | After the application of project have been
created, I'll double click on the
| | 03:20 | Editor tab to take it to full screen and
then I'll add a Label control. I'll
| | 03:24 | set its text property to "Hello from PHP!"
its fontSize to 18, so we can see it
| | 03:31 | very clearly and its fontWeight to bold.
| | 03:34 | I will also change the layout property
for the application from its default
| | 03:40 | value of absolute to vertical. I will save
the changes and run the application
| | 03:47 | and you should see if everything is working
correctly, that the application
| | 03:50 | loads in the browser and you can say the
label "Hello from PHP!" and most
| | 03:55 | importantly, the application is being downloaded
from PHP and Apache at run
| | 03:59 | time, rather than load it from the local
disk. This will become critical as I
| | 04:03 | start to send messages from the Flex application
at run time to PHP to retrieve
| | 04:08 | data and modify data in the MySQL database.
| | Collapse this transcript |
| Using Flex Builder's PHP Data Wizard| 00:00 | When you want to integrate a Flex Application
with PHP, there are a variety of
| | 00:04 | methods available. You can make simple calls
using the Http service component,
| | 00:08 | for Example, to a PHP page. Have the PHP
page returned well formed XML and then
| | 00:14 | deal with that XML content either as
a set of objects or with E4X.
| | 00:19 | Alternatively, you can install an AMF library,
which enables Flash remoting in
| | 00:24 | PHP. PHP doesn't have AMF capability natively.
But there are a couple of great
| | 00:29 | libraries out there that you can select
from. To use PHP and Flex together in
| | 00:33 | the simplest fashion, you can use the Data
wizard that's a part of Flex Builder
| | 00:37 | 3. The Data wizard has the ability to introspect
and get information about the
| | 00:41 | structure of a MySQL Database table that's
hosted by PHP and then it will
| | 00:46 | generate a complete application, including
both client and server side code.
| | 00:51 | The client side Flex application that the
data wizard creates, is a fairly
| | 00:55 | trivial application.
| | 00:56 | It provides very simple data entry without
any real visual design or other good
| | 01:01 | user interactions. But the server side PHP
code that it generates consist of a
| | 01:06 | complete, create, read, update, delete
interface for a particular Database
| | 01:10 | table. You can use the Data wizard, to generate
one set of code for each of the
| | 01:14 | Database tables in a Flex application.
You would then write your own custom
| | 01:18 | Flex code on the client and use the generated
Server code. So in this video, I
| | 01:23 | am going to show you how to run the Data
wizard, show you how to connect to a
| | 01:26 | MySQL Database from within Flex Builder
3 and then how to generate all that
| | 01:30 | code for a particular database table.
| | 01:33 | Here are the steps: before you use the
Data wizard, you must have already
| | 01:36 | created a Flex Builder Project that integrates
with the PHP Server and I showed
| | 01:40 | how to do that in the previous video. Then
with that project open, go to the
| | 01:45 | Flex Builder Menu and select Data, Create
application from database. In this
| | 01:50 | screen you select a data source. When you
are using PHP. You can only select
| | 01:55 | the Data Source that uses MySQL. I am going
to click the New button to create a
| | 02:00 | new Data source and I will name
it contacts and click Next.
| | 02:04 | Now I provide a database name. I named the
database contacts in MySQL, when I
| | 02:10 | imported the database table into the MySQL
server. So I will put that value in
| | 02:14 | here and then I will set the user name and
the password. If you are working on
| | 02:19 | Windows, using WAMP in its default installation,
the password will be blank, if
| | 02:24 | you are working on the Mac OS X and
you are using MAMP in its default
| | 02:27 | installation, the password will be the word
root. After you enter the password
| | 02:31 | will be the word root. After you enter
the information,click the Test
| | 02:32 | connection button. You should get the message,
the connection was successful.
| | 02:36 | If so, click OK and continue. If you weren't
able to connect successfully, go
| | 02:41 | back to the MySQL admin, Web based application
and make sure that the MySQL
| | 02:45 | Database is in fact running.
| | 02:48 | Now click Next and review the information
for your Database connection and
| | 02:52 | click Finish. You are now ready to select
a Database table and generate the
| | 02:57 | code. Pull down the list of available tables.
My Database currently has only
| | 03:02 | one table named person and that person
table has a primary key column of
| | 03:07 | personid. That information has been detected
automatically by the Data wizard.
| | 03:12 | Click the Next button and now indicate where
you want to place your code. The
| | 03:17 | PHP source folder should be set to the
same folder as the one in which your
| | 03:21 | Flex Application is being output, that
is, the Debug folder. So the Default
| | 03:26 | location for the PHP source folder is bin
- debug and I am going to leave it at
| | 03:31 | that default selection. The PHP file name
defaults to the same name as the
| | 03:36 | table itself with an upper case initial character.
You can rename this file if
| | 03:40 | you like. For Example, I think this as a
service page. So I am going to name
| | 03:44 | the PHP file that I am going to be making
calls to PersonService.php.
| | 03:50 | Then click Next and then in the Final screen,
first indicate which columns you
| | 03:54 | want to display in a Data Grid in the Flex
Application and then at the bottom
| | 03:59 | of the screen, you can select a single column
under which you want to be able
| | 04:02 | to filter. For example, I am going to set
filtering to the city column. Now you
| | 04:07 | may think, I would like to be able to filter
on more than one column. Once the
| | 04:11 | Flex application has been generated, you
will have the opportunity to customize
| | 04:14 | the code to whatever extent you like.
| | 04:16 | But this is the limitation of the Data wizard,
it only creates a filter for a
| | 04:20 | single column initially. Those are all the
steps. Click Finish to generate the
| | 04:25 | application. The application is generated
with the name set as the name of the
| | 04:30 | Database table. For example we reworking
with the Database table named Person.
| | 04:34 | So name of the Flex application is person.mxml.
In addition to the Flex
| | 04:39 | application code, there are also a couple
of ActionScript files that are
| | 04:42 | generated. I will describe those in more
detail in the following video. In the
| | 04:47 | bin-debug folder, a number of PHP and supporting
files have been created. For
| | 04:51 | example, here is the PersonService.php file,
that's been placed in the folder
| | 04:56 | underneath the PHP directory and then
there are other files such as
| | 05:00 | contactsconn.php, a sub folder named
PEAR and another one called
| | 05:06 | functions.ink.php. These new files are
now a part of the file set that you
| | 05:11 | would upload to your PHP server in
order to deploy the application.
| | 05:16 | Place the focus into the application, person.mxml
and then click the button to
| | 05:21 | run the application. As the application
loads, it makes a call to the PHP
| | 05:26 | Server, retrieves data and displays it in
a Data Grid. The Data Grid is set as
| | 05:32 | being editable, which means that you can
click into any row and any column and
| | 05:35 | make a change. I will click into the last
name column of the first row and
| | 05:40 | change the name from Brad Lang to Brad
Smith. Click out of the row and that
| | 05:45 | actually causes a Server-side communication
that saves the data in the Database
| | 05:49 | Server. I will also do a search-by-city.
I will click into the search by city
| | 05:54 | field at the bottom of the screen and type
in Houston, Click the Search button
| | 05:59 | with the magnifying glass and you will
see that its filtered based on that
| | 06:03 | city. You can also create a brand new record
by clicking the plus icon. You can
| | 06:09 | add new data into this data entry form
and save it and once again the
| | 06:13 | information will be sent to the Server
and the data will be saved in the
| | 06:15 | Database. So in the next video, I am going
to describe a little bit more about
| | 06:19 | how this application works, show you where
all the code is and describe the
| | 06:23 | particular approach that is being used
in sending and receiving messages
| | 06:27 | between Flex and PHP.
| | Collapse this transcript |
| Understanding the generated PHP code| 00:00 | In the previous video, I described how
to use the PHP data wizard, that's a
| | 00:04 | part of Flex Builder 3, to generate a complete
Flex application including both
| | 00:08 | client and PHP Server side code. In this
video, I am going to review some of
| | 00:13 | the generated code so you can understand
how you might be able to use this code
| | 00:16 | in your own applications. The generated client
side application as I mentioned,
| | 00:21 | is simple, even trivial. It presents a basic
Data Grid that shows all of the
| | 00:26 | data from particular Database table. Allows
filtering on a single column and
| | 00:30 | allows you to add new rows as needed.
| | 00:32 | Most of the work of the application is being
done in this file personScript.as
| | 00:38 | which is included in the main application
through a script tag. Lets take a
| | 00:42 | look at that ActionScript file.
| | 00:47 | The ActionScript file has a set of imports
at the top and then an include
| | 00:51 | statement that includes another ActionScript
file called personconfig.as. This
| | 00:55 | is the simplest of the files. It has a single
declaration of a public constant
| | 01:00 | named ENDPOINT_URL, which points to the location
of the Service PHP page, which
| | 01:05 | I named PersonService.php. Because the application
is being downloaded from the
| | 01:10 | PHP Server at run time, the ENDPOINT_URL
doesn't have to include the entire
| | 01:15 | URL, that is it doesn't have to start with
HTTP and so on. All you need to use
| | 01:20 | is the name of the actual PHP page because
the PHP page is stored in the same
| | 01:25 | folder from which the application downloads
at runtime, that will be the
| | 01:29 | location to which HTTPService
requests will be send.
| | 01:33 | Going back to the ActionScript file, the
next critical bit of code declares
| | 01:37 | variable named gateway data typed as in
HTTPService Object. Now in previous
| | 01:42 | videos of the Video series, I have shown
how to use RPC components such as
| | 01:46 | HTTPService or remote object and declare
them most of the time using MXML code.
| | 01:52 | This ActionScript file gives you a great
model for how you can use the
| | 01:55 | HTTPService class and declare it and manage
it completely in ActionScript. The
| | 02:00 | ArrayCollection, dataArr will contain all
of the data that's retrieved from the
| | 02:05 | Server and then in the initApp method,
all of the configuration of the
| | 02:09 | HTTPService Object, that is, the
Gateway variable is handled.
| | 02:13 | The URL is set to the ENDPOINT_URL,
that's the constant set in the
| | 02:17 | configuration file. The method is set to
post. Use proxy is set defaults and
| | 02:23 | here is the most critical part of the information.
The gateway objects result
| | 02:27 | format is set to E4X. The PHP Service page
will return well formed XML and you
| | 02:33 | will be able to look at that XML content
and retrieve it when you integrate the
| | 02:37 | PHP Service page into your own applications.
There is a set of event listeners
| | 02:41 | that are set up and then there is a call
to a function called fill, which I
| | 02:45 | will move to now. The fill function retrieves
data from the database using the
| | 02:50 | PHP page. It starts off by setting some
properties including filtering and
| | 02:54 | sorting and then set some parameters
based on the filter that is been
| | 02:58 | requested, and then finally calls a method
called doRequest, where it passes in
| | 03:04 | a string of FindAll. You will see when
we look at the PHP service page that
| | 03:08 | this is a fixed string that the PHP service
page is expecting and it's a
| | 03:13 | command that executes the server's
select statement in SQL.
| | 03:18 | From here we get into a more advanced architecture
than we had seen before,
| | 03:21 | when using RPC components. The name of the
method that was passed in which was
| | 03:25 | called FindAll in this example, is set
to a property of a parameters object
| | 03:29 | named method. That's then passed to the
request property of the HTTPService
| | 03:34 | Object known as gateway and then the request
is sent. When the result event
| | 03:39 | happens, that is, when the data is returned
from the Server, its handled in
| | 03:43 | something called a call back Object and
the call back Object contains result
| | 03:48 | and fault handlers to deal with those two
particular events and save the data
| | 03:52 | as needed to whichever predeclared variable
such as the ArrayCollection is
| | 03:56 | designed to hold it.
| | 03:57 | Here is the more important code that I
am interested in though. Go to the
| | 04:02 | bin-debug folder and locate the service
class, PersonService.php. Right click
| | 04:08 | on the service class or Ctrl click on the
Mac and select Open with text editor.
| | 04:13 | Now if you simply double click on that file,
within the Flex navigator view, it
| | 04:17 | will result in opening whatever application
on your system is associated with
| | 04:21 | PHP files. On my system, Dreamweaver is associated
with PHP, so double clicking
| | 04:26 | would have resulted in opening Dream weaver.
| | 04:30 | Here is the PHP file, it has a bunch of code
at the top that I am not going to
| | 04:34 | go through in a lot of detail. But I am going
to point out that there is a call
| | 04:37 | to a PHP class named XmlSerializer. This
is a pre-built PHP class, that knows
| | 04:43 | how to take any PHP object and serialize
it into XML. The actual XML structure
| | 04:49 | that's returned from this page, is documented
in the comments at the top of the
| | 04:53 | page. Whenever you get data back from the
remote service, it will come back
| | 04:57 | with the root element of response, a sub
element named data and then repeating
| | 05:03 | elements named Row. The child elements of
the row element will be based on the
| | 05:07 | names of the database columns of the table.
Notice down here that when you
| | 05:12 | retrieve data you also get a metadata section,
which contains an element named
| | 05:16 | totalRows which indicates the total number
of items within the dataset that's
| | 05:20 | being returned.
| | 05:22 | There is some additional code that manages
the filtering model. I am not going
| | 05:26 | to go through that in detail. Although I
do encourage you to review that code
| | 05:29 | yourself. But I am more interested in what
happens at the bottom of the page.
| | 05:33 | Go down towards the bottom and locate a switch
statement. Which on my screen is
| | 05:37 | at line 384. The switch statement looks
for a request parameter named method
| | 05:43 | and then it goes through five possible values
they can handle, FindAll, Insert,
| | 05:48 | Update, Delete and Count. For each of those
possible methods, it calls in an
| | 05:53 | internal function and returns the appropriate
data. You can make request to
| | 05:57 | this PHP service page yourself by using an
HTTPService component. Passing in a
| | 06:02 | parameter named method, which has one of
these values and that will result in
| | 06:06 | calling that method on the Server and returning
the appropriate data. So now in
| | 06:11 | the next video, I am going to create a brand
new application from scratch, that
| | 06:15 | sends request to the PHP service, gets back
the data and displays the data in
| | 06:20 | the Flex application.
| | Collapse this transcript |
| Retrieving data with the generated code| 00:00 | In this video I am going to describe how
to make calls to the PHP Service page
| | 00:04 | that's generated by the data wizard. In
the previous videos I have generated
| | 00:08 | the PHP code and now I am going to use
an HTTPService component. I will be
| | 00:13 | creating this application pretty much from
scratch, so if you are following
| | 00:16 | along with the exercises you can work
in the same file I have open
| | 00:19 | FlexAndPHP.mxml which was the default main
application for this new project or
| | 00:24 | you can create a brand new file.
| | 00:26 | Start by creating an instance of the HTTPService
component. Set its id to
| | 00:32 | myService and the set its URL property
to the name of the PHP file that you
| | 00:37 | want to make the request to which
I named PersonService.php.
| | 00:44 | Next create a new script section above the
PHP object and create a new private
| | 00:49 | function named getData. In order to retrieve
data from the PHPService page you
| | 00:57 | pass in a property named method with a
value of FindAll. The value of this
| | 01:02 | parameter method is case sensitive and
must match exactly the string that's
| | 01:06 | expected in the PHP page.
| | 01:08 | So here are the steps. First declare a new
variable named params data typed as
| | 01:13 | an object. And then fill in the value of
this object using a pair of braces
| | 01:20 | which in ActionScript creates a new object
on the fly. Give the object a named
| | 01:25 | property of method and set its value to
FindAll. Next send the request to the
| | 01:32 | HTTPService object using the syntax myService.send
and pass in the parameters
| | 01:38 | object, params.
| | 01:40 | Now the next step is to create an array
collection to hold the data when it's
| | 01:43 | returned. Place the cursor above the function
and declare a new Bindable
| | 01:48 | variable named myData data typed as an
ArrayCollection. Notice that the
| | 01:55 | ArrayCollection class is automatically imported
by Flex Builder as I select it
| | 01:59 | from the list of available classes.
| | 02:01 | Next create an invent handler function to
deal with the data when it's returned
| | 02:05 | from the PHPService page. Create a new
function named resultHandler which
| | 02:12 | receives an invent argument data typed as
ResultEvent. Place a break point on
| | 02:18 | the last line of the new function that is
the line that has the closing brace.
| | 02:23 | Now go down to the HTTPService component
and add an attribute-based result
| | 02:27 | event listener called resultHandler and
pass the event object. Finally place
| | 02:34 | the cursor after the existing label control
and add a new button. Set its label
| | 02:40 | to Get Data and its click event listener
to called the method getData.
| | 02:48 | So those where all the steps to retrieve
the data so far. Before we actually
| | 02:52 | display the data I am going to debug the
application so we can see what's
| | 02:56 | returned from the server. Save the changes
and run the application in Debug mode.
| | 03:11 | When the application appears in the browser
click to Get Data button and when
| | 03:16 | the data is returned from the server, you
will hit the break point, come back
| | 03:20 | to Flex Builder and switch to the Flex
Debugging Perspective. Go to the
| | 03:24 | Variables view and double click its
tab to expand it to full screen.
| | 03:28 | And then inspect the invent object which
is data typed as ResultEvent. Open the
| | 03:33 | event object and go down to its result
property which you will see as data
| | 03:37 | typed as the class ObjectProxy. Within
the result object you will see that
| | 03:41 | there is a sub-element named response. That
represent the root element of the
| | 03:46 | XML structure that returned from the server.
Open the response property and you
| | 03:51 | will see within the response property that
there are two child objects named
| | 03:54 | data and metadata and once again these represent
XML elements that are returned
| | 03:59 | by the PHPService page.
| | 04:01 | Open the data element and you will see
a row element which is data type as
| | 04:05 | ArrayCollection. That's the actual data being
returned from the server. And you
| | 04:11 | open that and you will see that there are
a 1000 rows of data being returned.
| | 04:16 | Also take a look at the metadata element,
this contains a value of pageNum and
| | 04:21 | totalRows, where the totalRows represents
the total number of data items
| | 04:26 | returned in the ArrayCollection.
| | 04:26 | So, now we know we are getting the data back
correctly. Restore the size of the
| | 04:32 | Variables view and then terminate the debugging
session and go back to the
| | 04:37 | code. I have already declared a bindable
variable named myData as an
| | 04:42 | ArrayCollection. So now to save the data
persistently so that I can use it in
| | 04:46 | my application, I will use this syntax,
myData=event.result.response.data.row
| | 04:56 | as ArrayCollection.
| | 04:59 | Now again the reason I am using this particular
data structure is because
| | 05:03 | that's the structure of the XML that's returned
from PHP and going back to the
| | 05:08 | PHPService page that's been called, the documentation
in the service page shows
| | 05:12 | you a sample of that XML structure.
| | 05:14 | I will go back to the application and
now I am going to add a DataGrid
| | 05:19 | component to display the returned data.
I will place the cursor after the
| | 05:23 | button and add a DataGrid and set its dataProvider
property using a binding
| | 05:28 | expression to myData. I will save the changes
and run the application this time
| | 05:35 | in Normal mode and when the application appears
in the browser I will click the
| | 05:41 | Get Data button and the data will be returned
and displayed in the DataGrid.
| | 05:46 | So, that's the first step in integrating
your Flex application with the
| | 05:49 | generated PHP code. Now in the next video
I will show you a more complete
| | 05:53 | example where we not only retrieve data
but we also modify the data in the
| | 05:57 | MySql database.
| | Collapse this transcript |
| Managing an asynchronous state with AsyncToken| 00:00 | In this video I am going to describe the
use of the AsyncToken class, a class
| | 00:05 | from the Flex class library that allows you
to track state between the time you
| | 00:08 | send a request to a server function using
the HTTPService or other RPC
| | 00:13 | components and the time a
resultEvent comes back.
| | 00:16 | For the demonstrations in this and the
next video I will be using an
| | 00:19 | application from the exercises folder.
If you have access to the exercises
| | 00:23 | folder and you are following along, go there
now. Go into the Chapter09 folder
| | 00:28 | to Chapter09Begin, select all of the files
and folders you will find there and
| | 00:33 | copy them to the clip board. Then go back
to Flex Builder, go to the source
| | 00:39 | folder within Chapter09Begin and
paste those files into place.
| | 00:43 | Next open the application file, ModifyData.mxml
and run the application. This
| | 00:50 | application uses an HTTPService component
instance and makes requests to the
| | 00:56 | server side PHP code that I generated in
a previous video. It presents the data
| | 01:01 | in a Data Grid and when you double click
on an item in the Data Grid you see
| | 01:05 | the details of that data in the data entry
form. You can cancel out of the form
| | 01:09 | and click New and see the form with blank
values. And you also have buttons for
| | 01:15 | deleting and saving that right
now aren't doing anything.
| | 01:18 | Let's go back to the code. In the current
version of the application as it
| | 01:23 | starts up, it calls this function getData.
As in the previous video, I am
| | 01:28 | creating an object named params. Adding a
method property which will be used as
| | 01:32 | a parameter with the value of FindAll and
then sending the request. And then
| | 01:37 | with the resultHandler function I am receiving
the data and saving it to a
| | 01:40 | pre-declared ArrayCollection
variable named acPerson.
| | 01:44 | When this application is completed I will
be making calls to many functions not
| | 01:48 | just one, and I need a way to distinguish
when a ResultEvent occurs, which
| | 01:53 | operation was called and what data might
have been associated with it. So I am
| | 01:57 | going to use an AsyncToken class.
| | 01:59 | In order to create an instance of an AsyncToken
you get its reference when you
| | 02:03 | call the request to the server. The send
method of the HTTPService object
| | 02:08 | always returns an instance of AsyncToken.
The AsyncToken object then stays in
| | 02:13 | application memory. It's a dynamic object
which means that you can assign
| | 02:17 | arbitrary named properties to it, and then
when the ResultEvent occurs, the
| | 02:22 | event object which is data typed as ResultEvent
has a token property which will
| | 02:27 | refer to the same instance of the AsyncToken
class that you created when you
| | 02:31 | made the call. You can then inspect the properties
and you will know and their
| | 02:35 | names and their values because you created
them and determine when the
| | 02:38 | ResultEvent happens, what operation you executed
and what data might have been
| | 02:42 | associated with it.
| | 02:43 | So here's the first example, go to the
getData method and place your cursor
| | 02:48 | before the line that says myService.send.
Within the same line of code declare
| | 02:53 | a new variable named token data typed as
AsyncToken and get its value from the
| | 03:00 | call to the send method. Now in the next
line add a new action property, this
| | 03:05 | is not a property that's already known to
the AsyncToken class, it's one we are
| | 03:09 | creating arbitrarily. And then set the value
of the action property to the same
| | 03:14 | value as the method that you
just created, FindAll.
| | 03:19 | Now when the ResultEvent comes back from
the server, the event object will have
| | 03:23 | a token property and it will point to the
same object. Go to the resultHandler
| | 03:28 | function and add the following code,
var token data typed once again as
| | 03:35 | AsyncToken and then get its
value from event.token.
| | 03:40 | Now place a break point on the next line
of code, this is the line of code that
| | 03:44 | sets the value of the ArrayCollection, save
and run the application in Debug
| | 03:49 | mode. As the application starts up, it makes
the request to the server and when
| | 03:57 | the ResultEvent is dispatched we hit the
eventHandler function with the break
| | 04:01 | point. I will go to the debugging perspective
and then to the variables view
| | 04:06 | and you will see that the event object has
this token property which you will
| | 04:09 | find under the inherited section of the
event object. And the token has the
| | 04:14 | arbitrary named property action
with the value of FindAll.
| | 04:18 | So now we can look at that value and decide
intelligently that in fact this
| | 04:23 | resultEvent happened because we went and
got all the data and now we can do a
| | 04:27 | little bit of conditional processing. Terminate
your Debugging session and then
| | 04:33 | go back to the code. Place the cursor above
the line of code that collects the
| | 04:39 | data and saves it into the acPerson ArrayCollection
and add a switch statement.
| | 04:44 | Within the parenthesis following the switch
key word inspect the value of
| | 04:48 | token.action and then put in a pair of braces.
| | 04:53 | Now add a case statement and look for the
value FindAll, followed with a colon.
| | 05:00 | Take the existing code that's saving the
data and move it right after the case
| | 05:04 | statement and then following that line of
code, put it in a break command. This
| | 05:09 | will ensure as we add additional cases to
the switch statement that we don't
| | 05:13 | continue executing all of them. Save your
changes and run the application again
| | 05:18 | this time in Normal mode. And this is now
to test whether after making those
| | 05:22 | changes, in fact the data still shows up
in the application and it should.
| | 05:26 | So now you have seen the basic structure
of the AsyncToken object. You get a
| | 05:31 | reference to an AsyncToken object upon making
a call to a remote function. This
| | 05:35 | architecture works whether you are
using HTTPService, WebService or
| | 05:40 | RemoteObject, any of the RPC components.
You add whatever arbitrary named
| | 05:45 | properties you want and then when the resultEvent
is dispatched, you get the
| | 05:49 | token back and you can expect its properties
to find out what happened. In the
| | 05:54 | next video I will extend this architecture
and we will be able to edit, update
| | 05:58 | and delete rows and react accordingly
in the finished application.
| | Collapse this transcript |
| Modifying data with the generated code| 00:00 | In this video, I am going to continue work
on the application ModifyData.mxml.
| | 00:05 | In this application I am using an HTTPService
object to make a request to PHP
| | 00:10 | and get data back and then using an AsyncToken
object to track information
| | 00:14 | between the time I sent a request to the
server and the time the ResultEvent
| | 00:18 | comes back.
| | 00:19 | This architecture using the AsyncToken object
will allow me to make multiple
| | 00:23 | calls to the same service page on the server
and handle the results in a single
| | 00:27 | eventHandler. I am going to run the application
again and show that when the
| | 00:32 | user double clicks on a row, we see the
details for that row in a data entry
| | 00:36 | form or when the user clicks the new button
we see the same data entry form,
| | 00:41 | but this time with blank values.
| | 00:44 | In the first part of the video, I am going
to describe how to have set up all
| | 00:48 | of the functionality you need to both create
and update existing data. First
| | 00:52 | take a look at the newRecord function, notice
that it starts off by setting a
| | 00:56 | property of the form component named currentPerson
to an object with the
| | 01:00 | property named personid with the value
of zero. This is essentially saying,
| | 01:04 | Create a new data object, but without using
a strongly typed value object.
| | 01:08 | Now when the user types values into the
form and then sends the data back by
| | 01:12 | clicking the Save button, we will receive
that data and this method saveRecord,
| | 01:16 | will be called. The event object which is
data typed as this class PersonEvent
| | 01:22 | has a property named person data typed as
an object. The data entry form fills
| | 01:26 | in this object with all of the properties
from the form controls and we can now
| | 01:30 | receive it and handle it within the function.
| | 01:33 | Add this code to the saveRecord function,
first of all, declare a variable
| | 01:37 | named personObj typed as Object and get
its value from the event object's
| | 01:43 | person property. Now inspect the primary
key property personid, if the value is
| | 01:49 | zero that means the data came from this
newRecord function and it's a new
| | 01:53 | object, it should be added to the database.
Otherwise it's an existing record
| | 01:58 | that came from the actual database
and it should be updated.
| | 02:01 | So here's the conditional code. If personObj.personid,
has a value of zero, add
| | 02:09 | a method property to the object with the
value of Insert. And this is the
| | 02:14 | string that the PHP service page will be
looking for, to determine what action
| | 02:18 | it's supposed to take. Next add an else clause
and within the else clause, set
| | 02:24 | that same method property to a value of
Update. Make sure you spell the words
| | 02:30 | Insert and Update exactly as I have them
here, with upper case initial
| | 02:34 | characters because that's what the
PHP service page is expecting.
| | 02:38 | Now I am going to make the request to the
server by calling the send method and
| | 02:41 | passing in the object and I will get back
a reference to the AsyncToken, just
| | 02:45 | like I did with the FindAll method. I
will declare token object typed as
| | 02:50 | AsyncToken, I will get a reference for the
token, by calling the send method of
| | 02:56 | HTTPService component and I will pass in
personObj, which now contains the
| | 03:01 | actual data I am sending to the database
plus the method property indicating
| | 03:05 | what supposed to be done with it.
| | 03:07 | Now I will add the action property as follows
token.action = personObj.method.
| | 03:14 | And now the action property is a part
of the token and I will be able to
| | 03:17 | determine what happened, when the data comes
back from the server. Now let's go
| | 03:22 | to the resultHandler. Within the resultHandler,
we already have a switch
| | 03:26 | statement that's examining the action property
of the AsyncToken. Add two more
| | 03:31 | case statements, the first for the Update
action, and always add the break
| | 03:35 | statement whenever you add a case statement,
and the second will be for the
| | 03:39 | Insert action. Then place the cursor after
the case statement for the Update
| | 03:45 | action but before the break. Whenever you
call the Insert or the Update actions
| | 03:50 | from the PHPservice page, you get back
a response which is the actual data object.
| | 03:56 | In the case of the Update statement, it's
typically the same object that you
| | 03:59 | passed into the action, but just in case
anything happened on the server that
| | 04:03 | modified the data, you always want to take
that data and put it back into your
| | 04:07 | local data set. So place the cursor above
the switch statement and declare
| | 04:12 | another variable named personObj
data typed as an Object.
| | 04:17 | Now move back down into the case statement,
after case Update and fill in the
| | 04:22 | value of that object as follows personObj
= event.result.response.data.row, for
| | 04:33 | as with the FindAll action we got back all
of the data, this time we'll only
| | 04:37 | get back one. Then replace the object within
the local data set as follows
| | 04:43 | acPerson.setItemAt and pass in two values,
the first is the person object,
| | 04:49 | personObj and the second is the index position
where you want to put the item
| | 04:54 | in. And we can get that value from the current
position in theData Grid using
| | 04:58 | the expression persongrid.selectedIndex.
| | 05:04 | Finally set the currentstate property to
a blank string and that results in
| | 05:09 | removing the data entry form from the interface
and re-enabling the Data Grid.
| | 05:14 | The Insert statement code is very similar,
place the cursor after case Insert
| | 05:19 | and before the break and add the following
code. Once again get the value of
| | 05:25 | personObj using the same expression as before,
event.result.response.data.row.
| | 05:34 | Now because we added the item in the database
on the server, we also want to
| | 05:38 | add the item in the local ArrayCollection
using this syntax, acPerson.addItem
| | 05:45 | and add personObj. Now the next couple
of lines are going to manipulate the
| | 05:51 | interface and cause theData Grid to scroll
to and select the newly added item
| | 05:57 | as follows. personGrid.selectedItem = personObj,
by getting a reference to the
| | 06:05 | object and then passing it to the selected
item of the Data Grid will now
| | 06:09 | select the row of the newly added item.
But because that item may not be
| | 06:13 | visible on the screen currently, we also
have to tell the Data Grid to scroll
| | 06:17 | to that position, using this code, personGrid.scrollToIndex
and pass in the
| | 06:24 | value of personGrid.selectedIndex.
| | 06:30 | Finally as before, set the currentstate
property to a blank string and that
| | 06:36 | will remove the data entry form and re-enable
the Data Grid, save your changes
| | 06:41 | and run the application and let's test
the results. First we'll update an
| | 06:47 | existing row, when the data appears double
click on the first row which
| | 06:51 | currently has the value of Brad Lang change
Brad's last name to some other
| | 06:56 | values such as Brad Smith, click save and
after a moment, after the message
| | 07:03 | goes back to the server and comes back to
the application you will see that the
| | 07:07 | data is updated in the application.
| | 07:09 | Next create a new record, click the button
labeled New, type in values in all
| | 07:15 | of the columns on the PHPserver each of
these columns are required. So I am
| | 07:19 | going to type in a value of Adam Aardvark
and put in just any kind of values in
| | 07:26 | the rest of the fields. I will click the
save button and after the request goes
| | 07:42 | off to the server and comes back to the
client application, the data is
| | 07:45 | selected in the Data Grid as result of that
scrolling code that I had put in.
| | 07:50 | Finally let's add code for deleting data.
Go back to Flex Builder and locate
| | 07:54 | the deleteRecord function. Within the deleteRecord
function use the following
| | 07:59 | code, declare a variable named personObj
data typed as an object and get its
| | 08:04 | value from personGrid.selectedItem, so
we are getting a reference to the
| | 08:09 | currently selected object within the Data
Grid. Then add the method property as
| | 08:15 | we have before, this time the syntax will
be, personObj.method = Delete, and be
| | 08:22 | sure to use an upper case D because that's
what the PHPservice page is expecting.
| | 08:27 | Next make the call to the server and get
an AsyncToken object and get the value
| | 08:35 | of the token object by calling the service
components send method passing in
| | 08:40 | personObj and finally set the action property
of the token to Delete. Now go
| | 08:48 | back to the resultEventHandler, within
the resultEventHandler, locate the
| | 08:52 | switch and case statements and add a new
case for the Delete action. And after
| | 08:58 | the case statement for the Delete action,
add this code acPerson.removeItemAt
| | 09:05 | and then once again use the Data Grid's
selectedIndex property to indicate
| | 09:09 | which item you want to remove
from the local collection
| | 09:12 | personGrid.selectedIndex and even though
it's not literally necessary here I
| | 09:24 | always had a break statement at
the end of every case clause.
| | 09:27 | Save the changes and run the application
one more time and as the application
| | 09:32 | opens, it will once again show all of the
data. Click the last name column to
| | 09:36 | sort and you should see that new row Adam
Aardvark appear at the top, select it
| | 09:42 | and click Delete and after a moment you
should see the data has been removed.
| | 09:47 | And if you refresh the application, so
that you are pulling all of the data
| | 09:50 | from the server again and then once again
sort it, you will see that in fact
| | 09:54 | the data has also been deleted from the server
side database. So that's a look
| | 09:58 | at how to build your custom application
code on the Flex client and to
| | 10:02 | integrate it with the generated PHP code
that's created by Flex Builder's PHP
| | 10:07 | Data Wizard.
| | 10:09 | As I mentioned at the beginning of this
Chapter there are many other possible
| | 10:12 | approaches to integrating Flex applications
with PHP, for example, if you
| | 10:16 | prefer the better performance of AMF and
the Flash Remoting architecture, you
| | 10:20 | might want to look at the component library
named AMFPHP or another one called
| | 10:25 | SabreAMF, both of these are completely free
libraries that you can download and
| | 10:30 | install into your PHP server installation
and then you can use the RemoteObject
| | 10:34 | component in the Flex framework to make
calls that are similar to these, but
| | 10:38 | get the benefits of the smaller size and
faster communication of AMF or Action
| | 10:43 | Message Format.
| | Collapse this transcript |
|
|
10. Integrating with ASP.NETInstalling ASP.NET and SQL Server 2005 Express| 00:00 | In this chapter of the video series, I am
going to describe how to integrate
| | 00:04 | Flex applications with ASP.NET. This chapter
will be only useful on Windows,
| | 00:09 | because the ASP.NET software only works
on that operating system and is not
| | 00:14 | available for Mac. Flex Builder 3 includes
a new feature called the Data
| | 00:17 | Wizard, which I have already demonstrated
in a previous chapter in the context
| | 00:21 | of PHP, but which also can be used to generate
server side code in ASP.NET,
| | 00:27 | that allows you then to link your Flex applications
to SQL Server databases.
| | 00:31 | Before you can use this Flex Builder
feature, you must have the ASP.NET
| | 00:35 | Framework installed and also the Data Wizard
for ASP.NET only works with SQL
| | 00:39 | Server databases. So if you don't already
have the SQL Server, you'll need to
| | 00:43 | download it and install some version of
that. Finally, when you create a Flex
| | 00:47 | Builder project for use with ASP.NET, you
have the option of using something
| | 00:51 | called the Development Web Server. This
is a product that's included with
| | 00:55 | another product called Visual Web Developer
2008 Express Edition and also with
| | 00:59 | the full product Visual Studio.
| | 01:01 | You can download Visual Web Developer 2008
and an incorporated installer for
| | 01:06 | SQL Server from the web page that
I am displaying now at
| | 01:10 | www.microsoft.com/express/download/#webinstall.
Go to the Visual Web Developer
| | 01:19 | 2008 Express Edition section and click
the Download link. Download the file
| | 01:24 | which is relatively small only 2.6 megabytes.
Then once you have downloaded it,
| | 01:29 | it's started up. Here is what the installer
looks like, it walks you through
| | 01:32 | some informational steps including information
about the license agreement.
| | 01:36 | Visual Web Developer 2008 Express Edition
is free for download and use. You
| | 01:41 | will have to register to use it beyond
30 days, but it doesn't require any
| | 01:45 | license fees.
| | 01:46 | After you've read through the license agreement,
if you accept it, click the
| | 01:49 | appropriate radio button and then click Next.
On this screen, you indicate what
| | 01:54 | options you want to include in your Visual
Web Developer 2008 installation. You
| | 01:58 | will always be including the .Net Framework
and Visual Web Developer and
| | 02:04 | optionally you can also install SQL Server
2005 Express Edition, which is a
| | 02:09 | free version of SQL Server and the Microsoft
Server like Runtime. I don't need
| | 02:14 | the server like Runtime, so I am going
to deselect that option but I will
| | 02:18 | select SQL Server 2005 Express. Then I'll
click Next again, I'll review all of
| | 02:24 | my options and then click the Install button.
| | 02:26 | The downloaded installation of these products
takes a little bit of time. After
| | 02:30 | you are done, you'll probably need to reboot
your system. But then once that's
| | 02:33 | finished, you'll be ready to start using
SQL Server ASP.NET and Flex Builder
| | 02:38 | all together to go to Flex applications that
integrate these products together.
| | Collapse this transcript |
| Installing SQL Server Management Studio Express| 00:00 | After you have installed SQL Server 2005
Express, you might also want to
| | 00:05 | install the Management User Interface,
that's available from Microsoft for
| | 00:09 | free. You can download this software
from this web address,
| | 00:12 | www.microsoft.com/express/sql/download/default.aspx.
Notice the http prefix
| | 00:22 | before this URL. If you have already installed
SQL Server itself, then the only
| | 00:27 | thing you need from this screen is the
SQL Server Management Studio Express
| | 00:31 | product. This is an application that will
allow you to manage and create
| | 00:34 | databases and import and query the data.
Click the Download link to download
| | 00:39 | the software and then save
it to your local disc.
| | 00:42 | Once the installer has been downloaded, you
can launch it and walk through the
| | 00:46 | prompts. The installation is fairly straightforward.
Once the file has been
| | 00:51 | downloaded, click Run and then continue
through the security warning. Now
| | 00:56 | follow the prompts to complete the installation,
review the license agreement.
| | 01:00 | As with SQL Server Express itself, the Management
Studio Software is free to
| | 01:05 | use without any license fees. Provide any
other required information and then
| | 01:10 | complete the installation.
| | 01:12 | In the next video, I'll show you how to import
a database using the SQL Server Management Studio Express.
| | Collapse this transcript |
| Importing a database into SQL Server| 00:01 | In this video I am going to describe how
to import a database into SQL Server
| | 00:05 | that you can then use to experiment with
the Flex Builder 3 Data Wizard for
| | 00:09 | ASP.NET. Before you can do this exercise,
you must have first installed ASP.NET
| | 00:15 | and SQL Server 2005 Express and SQL Server
Management Studio Express, which I
| | 00:20 | am showing on the screen now. The first
step is to create a database.
| | 00:24 | Go to the Object Explorer panel on the left
and locate the tree item labeled
| | 00:29 | Databases. Right-click on it and select
New Database. Name your new database
| | 00:34 | contacts and click OK. The next step is to
run an SQL Script, that's a part of
| | 00:41 | the exercise files that come with this video
series. If you are following along
| | 00:45 | with the exercises that you have accessed
to these files. Go to the Menu and
| | 00:49 | select File, Open, File, navigate to
the Exercises folder, which I have
| | 00:54 | installed on my Desktop and from there go
down to Assets, ASP.NET and you'll
| | 01:00 | find the file there named, contacts.sql.
| | 01:04 | Open the file, this file creates a table
named person with the particular data
| | 01:09 | structure, that's listed right here. Notice
that there is a primary key named
| | 01:13 | personid which is an IDENTITY field, which
means that the value for this column
| | 01:17 | will be assigned automatically for each
new row. The rest of the columns are
| | 01:21 | string or variable character values of different
lengths. At the bottom, there
| | 01:26 | is a set of INSERT statements, then inserted
a total of 100 records into the
| | 01:30 | database table. Once the file has been
opened, you can check its syntax by
| | 01:34 | clicking the checkmark icon on the toolbar
and you should get this message,
| | 01:37 | Command (s) completed successfully.
| | 01:40 | Then to execute the file, click the Execute
button on the toolbar. You'll see a
| | 01:45 | series of messages indicating, how many
rows were effected on each INSERT
| | 01:49 | statement. Now to view the data, go back
to the Object Explorer and open the
| | 01:53 | contacts database and from there, open the
Tables list. You should find the new
| | 01:59 | table dbo.Person is listed there. Right-click
on the table name and select Open
| | 02:05 | Table. After just a few seconds, you should
see that there are 100 rows of data
| | 02:10 | to work with in this database table.
| | 02:13 | Now if you don't have access to the exercise
files, you can instead create the
| | 02:17 | database table structure based on the script
that I showed and then add your
| | 02:21 | own data manually. Then you should once again
have that data available to work
| | 02:26 | with, in Flex Builder 3, using
the ASP.NET Data Wizard.
| | Collapse this transcript |
| Creating a Flex/ASP.NET project in Flex Builder| 00:00 | In this video, I am going to describe how
to create a Flex Project in Flex
| | 00:04 | Builder 3 that integrates with ASP.NET.
You have a couple of choices for how
| | 00:09 | you build this project. The most important
is which WebServ you are going to
| | 00:13 | use. If you use Internet Information Services
that's the industrial strength
| | 00:17 | web server that comes with Windows XP Professional
and up and also with Windows
| | 00:22 | Vista Business and up, then you can integrate
your Flex Project with that web
| | 00:26 | server. If you don't have Internet Information
Services but you have installed
| | 00:30 | either Visual Web Developer Express or Visual
Studio then you will have access
| | 00:35 | to a Development or a stand-alone web
server, that's included with those
| | 00:39 | products and Flex Builder will know how to
use and launch that web server when
| | 00:43 | you want to test your application.
| | 00:45 | For this demonstration, I will
be using that Development
| | 00:48 | web server that's a part of Visual
Web Developer Express
| | 00:51 | because I have already installed that product
on my system. Within Flex Builder
| | 00:55 | to create the project, select File, New,
Flex Project. As with all Flex Project
| | 01:02 | you can name it anything you want as long
as you don't include spaces or
| | 01:06 | special characters. I am going to
name my project Chapter10Begin.
| | 01:11 | You can place the project anywhere you like
and I will set the application type
| | 01:14 | as Web Application. Now, I will select
ASP.NET from the list of available
| | 01:20 | application servers and click Next. On this
screen, you indicate whether you
| | 01:25 | are going to use the Development Server or
Internet Information Services (IIS)
| | 01:30 | as I indicated before. I installed Visual
Web Developer, so I have the
| | 01:34 | Development Server installed and I am going
to use it in this demonstration.
| | 01:39 | Next, you indicate the Output folder, if
you use Internet Information Services,
| | 01:44 | you will need to output your files to a folder
that's available within the IIS
| | 01:47 | document route. But if you are using the
Development Server then the flex_bin
| | 01:52 | folder which is the default Output folder
is set up automatically as the
| | 01:56 | document route for that special web server
and that web server will start up
| | 02:00 | automatically and will listen at Port 3000.
Then when you test your application
| | 02:05 | from within Flex Builder, Flex Builder will
automatically know to pull the file
| | 02:10 | from that web server using the same port.
| | 02:12 | So I will leave the Output folder named at
the default setting of flex_bin and
| | 02:17 | click Next. Now, I will indicate the name
of my main application file which I
| | 02:22 | will call FlexAndDotNet.mxml. Again notice
that the Output folder URL is set
| | 02:30 | automatically to include Port 3000. Now
I will click Finish and that creates
| | 02:38 | the Application in the project. I will
create a Label control within the
| | 02:42 | Application text and I will say it's text
property to Hello from ASP.NET! and
| | 02:50 | then so we can see it clearly, I will
set the fontSize="18 "and the
| | 02:54 | fontWeight="bold"
| | 02:56 | I will also set the layout property to vertical
and then I will try running the
| | 03:05 | application from within Flex Builder. When
you run the application, it should
| | 03:10 | be downloaded from the Development web
server, notice the URL starting with
| | 03:15 | localhost3000. And now you can see that the
application is loading and running correctly.
| | 03:21 | In the Windows System Tray in the lower right-hand
corner you should now see an
| | 03:25 | icon that represents the ASP.NET Development
Server running on Port 3000. When
| | 03:31 | you close down Flex Builder, the web server
will shut down automatically but if
| | 03:35 | you need to stop it for any reason just go
to the System Tray icon, right-click
| | 03:40 | and select to Stop. You can also select
item such as Open In Web Browser and
| | 03:44 | Show Details.
| | 03:46 | The Open In Web Browser takes you to a directory
listing which is your project
| | 03:50 | route folder which is now also treated as
the web servers document route. And
| | 03:55 | you can also select the item Show Details
and that brings up a dialog box
| | 04:00 | indicating which port and which is the virtual
and physical path for this web server.
| | 04:06 | So now I will close the web browser and
return back to Flex Builder and let's
| | 04:10 | take a look at the couple of Project
properties that have been set up
| | 04:13 | automatically. In the Properties dialogue
you will notice that there aren't any
| | 04:18 | special settings in the Compiler arguments
whereas when you are using the
| | 04:22 | RemoteObject architecture with ColdFusion,
when you work with ASP.NET in Flex
| | 04:27 | by default Flex Builder expects you to work
with that system using web services
| | 04:32 | and so you don't need a services configuration
file or any other special
| | 04:36 | configurations. Essentially to this is
just like any other client site
| | 04:41 | application that's going to get and send
data using standard web services and
| | 04:46 | since this is ASP.NET we will be using
SOAP-based web services which is
| | 04:51 | something .NET does particularly well.
| | 04:54 | So now that you have a project set up that
integrates with .NET, the next step
| | 04:58 | is to generate some code based on the
SQL Server Database table that was
| | 05:02 | previously imported.
| | Collapse this transcript |
| Configuring SQL Server for use with Flex Builder| 00:01 | In this video, I am going to describe the
steps to configure SQL Server that
| | 00:05 | will allow you to connect to SQL Server
from Flex Builder 3 and use the Data
| | 00:09 | Wizard to generate client and server-side
code. Starting off in SQL Server
| | 00:14 | Management Studio Express, the first step
is to create a special login. It is
| | 00:19 | possible to use the built-in or default logins
that SQL Server comes with, but
| | 00:24 | good security practices dictate that you
should create a special login whenever
| | 00:27 | you are doing something special
such as generating code.
| | 00:31 | So the first step is to create a login.
Go to the Object Explorer panel and
| | 00:36 | open the Security section. From there double-click
on Logins and you will see
| | 00:41 | the list of built-in or default logins,
right-click anywhere in that area and
| | 00:46 | select New Login. Assign the login name flexUser.
Set the authentication to use
| | 00:54 | a password, enter a password of any type
and enter it twice. Make sure you
| | 00:59 | spell it the same both times. Next turn
off password expiration and that will
| | 01:06 | disable the other option, user must change
password at next login. The next
| | 01:10 | step in SQL Server is to map this
login as a database user.
| | 01:15 | Go to the list of pages and choose User
Mapping and then check the checkbox
| | 01:20 | next to contacts, the database you want
this user to be able to use. Finally
| | 01:26 | come down here and click OK and that will
create the user and map the user to
| | 01:30 | that database. There is one last step in
mapping the user to the database and
| | 01:36 | that's to provide them with the user role.
Go to the Object Explorer to the
| | 01:41 | Databases section and locate and open the
Contacts database. Go to the Security
| | 01:46 | section to Users and you should find your
new login, flexUser listed as a
| | 01:51 | database user for this database. Double-click
on the User and then in the
| | 01:56 | Database User property screen, go down to
the Database role membership section.
| | 02:01 | Scroll down to the bottom and select
db_owner. This will allow you to
| | 02:06 | interrogate the database and get for instance
a list of database tables and all
| | 02:10 | of the data structure that Flex Builder
will need in order to generate both
| | 02:14 | client and server-side code. Click OK to
save your changes. The next step is to
| | 02:19 | enable TCP/IP Connections from Flex Builder
to SQL Server. SQL Server is
| | 02:26 | initially installed without any TCP/IP
connectivity. This is a security
| | 02:30 | measure, but when you are doing development
work and you are working with Flex
| | 02:34 | Builder, you need to be able to connect over
TCPIP, here is how you set it up.
| | 02:40 | Go to the Windows menu and start up the
application SQL Server Configuration
| | 02:44 | Manager. This is an application that's
installed at the same time as SQL
| | 02:48 | Server. Go to SQL Server 2005 Network Configuration
and from there to Protocols
| | 02:55 | for SQLEXPRESS. Notice that the TCP/IP
protocol is currently Disabled,
| | 03:01 | double-click on it and on the Protocol tab,
set the Enabled property to Yes.
| | 03:07 | Then click the IP addresses tab and scroll
all the way down to the bottom and
| | 03:12 | locate the section labeled IPALL. Set
the TCP Port to 1433 which is the
| | 03:18 | standard default port on which SQL Server
is typically configured and the one
| | 03:23 | that Flex Builder will expect to use to connect.
| | 03:26 | Click OK and you will see a warning that
you must stop and restart SQL Server
| | 03:31 | before you will be able to connect. Click
OK, then come back up to the SQL
| | 03:35 | Server 2005 Services label, select SQL Server,
SQL Express. Then go up to the
| | 03:43 | toolbar and click the Stop Service button.
It takes a few seconds to stop the
| | 03:48 | service, and then once that operation is
complete, you should then be able to
| | 03:52 | select the service again and click
the Start Service button.
| | 03:56 | Now SQL server will be able to listen for
and respond to TCP/IP messages and
| | 04:01 | you will be able to login to the SQL
Server from within Flex Builder.
| | Collapse this transcript |
| Using Flex Builder 3's ASP.NET Data Wizard| 00:01 | In this video, I am going to describe how
to use the ASP.NET Data Wizard within
| | 00:05 | Flex Builder 3 to generate client and server-side
code based on the structure
| | 00:10 | of the database table hosted by SQL Server.
In previous videos, I installed SQL
| | 00:14 | Server and configured it so it could be connected
to from within Flex Builder.
| | 00:19 | I set up ASP.NET along with the development
server. I am now ready to start
| | 00:23 | putting all of the tools together. Within
Flex Builder I already created a
| | 00:27 | project that's associated with ASP.NET,
now I'll go to the Menu and select
| | 00:32 | Data, Create Application from Database.
| | 00:35 | The first step within this screen is to
create a connection. This is very
| | 00:39 | similar to the steps I followed in the previous
chapter, when working with PHP
| | 00:42 | and MySQL. I'll click the New button and
give the Connection profile a name. I
| | 00:47 | call the version in MySQL in a previous chapter
contacts, so I am going to call
| | 00:51 | this one contactsSQL. I'll click Next
and then provide the connectivity
| | 00:56 | information that Flex Builder needs.
The Server Name should be set to
| | 01:00 | localhost, assuming your SQL Server installation
is on your own local machine.
| | 01:05 | The Database Name matches the database
name that you've assigned in the
| | 01:08 | management console. The User Name and Password
are the values that you add it
| | 01:13 | when you created a login in SQL Server.
I created a user name called flexUser
| | 01:18 | and I assigned a password of simply password.
So you enter those four values
| | 01:23 | and then click Test Connection and you should
see this message, The connection
| | 01:26 | was successful.
| | 01:27 | Now if you see a message indicating that
there was a problem with connecting or
| | 01:31 | there was a problem with security. You
will need to go back to the SQL
| | 01:34 | administrator and configuration applications
and make sure that you follow the
| | 01:38 | steps both for creating the user, giving
them the access to the database and
| | 01:42 | also make sure that SQL Server is listening
and is ready to respond on the TCP
| | 01:48 | iport number 1433.
| | 01:50 | If you do see this message, The connection
was successful, you can click OK and
| | 01:53 | go on to the next step. Click Next and
click Finish to save your connection
| | 01:58 | information. If everything is healthy,
you should immediately see a list of
| | 02:02 | available tables in the database. We only
have one table named person and it's
| | 02:07 | indicated here. Also the Data Wizard automatically
detects the primary key of
| | 02:12 | the Table, which we created as personid,
but it does allow you to select any
| | 02:17 | other Primary Key if you will so desire.
I'll leave it to the real Primary Key
| | 02:21 | column, personid and click Next.
| | 02:24 | Now the next step is to configure the server-side
code that will be generated.
| | 02:28 | On the server, we're going to be creating
a class that's written in one of two
| | 02:32 | languages. Either C-sharp or Visual Basic
and either way this class will
| | 02:36 | provide a service that you can call to exchange
data between the server and the
| | 02:41 | Flex client. I am going to name the Class,
PersonService following a pattern
| | 02:46 | that's very similar to what I used with
PHP and MySQL, in a previous chapter.
| | 02:51 | For the Server language, I'll use the default
setting of C# with web services.
| | 02:55 | But if you prefer Visual Basic, you can
select that option. The resulting
| | 02:59 | application will behave exactly the same,
the only difference will be the
| | 03:03 | actual language in which the server-side
code written. Click Next after making
| | 03:07 | those selections and in this screen you
select which columns of the database
| | 03:11 | table will be displayed on the
applications primary screen.
| | 03:15 | By default, all columns except for the primary
key will be displayed. You also
| | 03:20 | have the ability to filter the data on one
column only. I am going to select a
| | 03:24 | filter on the city column, then I'll click
Finish and all of the code on both
| | 03:29 | the client and the server will be created.
It takes just a few moments for the
| | 03:33 | code generation to be completed.
| | 03:35 | In your project Source route, you will now
have a file where the name of the
| | 03:39 | application matches the name of the database
table. This application is named
| | 03:43 | person.mxml. If you then go to the New Folder
that's created within the project
| | 03:48 | named App_Code, you'll find the class
that you configured which I called
| | 03:52 | PersonService and it will have a file extension
of either .cs for C-sharp or
| | 03:58 | .vb for Visual Basic.
| | 03:59 | I am going to open the CS file briefly by
right-clicking on it and selecting
| | 04:04 | Open With Text Editor. Don't double-click
on it because if you have any other
| | 04:09 | application on your system that's configured
to work with CS files. The file
| | 04:13 | will open in that application, instead of
in Flex Builder. Here is the C-sharp
| | 04:19 | class that's going to be doing all the
server-side work, connecting to the
| | 04:22 | database and getting information
to the Flex client.
| | 04:26 | The last step in this video is to test the
application. Go back to person.mxml
| | 04:31 | and run the application. As previously,
the application is downloaded from
| | 04:36 | ASP.NET at Runtime. As it starts up, it makes
a request back to the server for
| | 04:41 | data and when the data is returned over
a SOAP-based Web Service, it's
| | 04:46 | displayed in the data grid as shown here.
You can apply a filter by clicking
| | 04:51 | into the text field at the bottom right
of the screen. I'll type a value of
| | 04:55 | Houston and click the magnifying glass to
perform the filter and I'll see only
| | 05:00 | the data for people who live in Houston.
| | 05:04 | I'll remove the filter and once again click
the Filter button and that restores
| | 05:08 | the view of all of the data coming from the
server. There is also a data entry
| | 05:12 | form that you can use to add rows, I'll Cancel
out of that and there is also a
| | 05:17 | trashcan icon, that you can use to delete
rows from the database table.
| | 05:21 | Now in the next video, I'll do a more
thorough code review of all this
| | 05:24 | generated code, so we can understand the
nature of the web services that have
| | 05:27 | been created in the ASP.NET environment.
| | Collapse this transcript |
| Reviewing the generated code| 00:01 | In this video, I am going to review the generated
code that was created by the
| | 00:04 | Data Wizard, using ASP.NET and SQL
Server. I'll start with the Flex
| | 00:09 | application. The application name is the
same as the table name, in this case,
| | 00:13 | person.mxml. The application presents a
DataGrid when it first appears. There
| | 00:18 | is an included file called personScript.as,
which contains all of the logic for
| | 00:24 | the application and one of the first commands
in that file is an include
| | 00:28 | statement, that includes a configuration
file, which in turn contains the
| | 00:33 | location of the web service endpoint. The
content that you download from that
| | 00:38 | web service endpoint, is in a format known
as WSDL or a Web Service Description Language.
| | 00:44 | ASP.NET is capable of generating WSDL content
based on requests, that end with
| | 00:50 | a question mark, WSDL query string. The file
that you make the request to, both
| | 00:54 | for the WSDL and to make calls to the web
service operations ends with a file
| | 00:59 | extension of .ASMX. This file, PersonService.asmx
is generated in the root
| | 01:07 | folder of the project. Notice, it's not
in the source code root, it's in the
| | 01:11 | actual root. I'll open that file and you
will see that this file contains a
| | 01:16 | single statement, indicating that this a
web service file written in C Sharp,
| | 01:21 | where all of the logic in a form known
as Code Behind, is in a file name
| | 01:26 | PersonService.cs in the App_Code folder.
Also note that there is a class
| | 01:31 | declaration of PersonService indicating
that, that's the class name as it's
| | 01:35 | known to the .NET environment.
| | 01:37 | Next, I'll take a look at the .CS file.
This is the file where the actual
| | 01:42 | activity of the web service happens, there
are a number of operations that are
| | 01:47 | defined. The FindAll operation receives
three required arguments, the first
| | 01:52 | argument is a filter string that allows
you to filter the data, the second is
| | 01:57 | also a string and indicates which field you
want to sort on if any and finally,
| | 02:02 | there is a boolean value, which indicates
when returning data in a sorted
| | 02:06 | order, which order you want to sort in,
ascending or descending. The code
| | 02:10 | within the FindAll operation, puts together
a dynamic SQL Statement and then it
| | 02:14 | creates an object known in ASP.NET as a
DataTable. The remainder of the code
| | 02:19 | fills the DataTable from the SQL Statement
and returns the result directly to
| | 02:23 | the caller, in this case, a Flex application.
| | 02:26 | There are also functions for updating, inserting
and deleting data. Notice that
| | 02:31 | the name of the function for deleting is
Remove and it receives only the id of
| | 02:36 | the record that you want to remove from
the database table. ASP.NET Web
| | 02:40 | Services have a unique capability. In that,
they can generate their own testing
| | 02:44 | pages. Here is how you can try this
out. First of all, go to the Flex
| | 02:49 | application and start it up. This will make
sure that you have your development
| | 02:53 | web server running, take a look down at the
system tray, in Windows it's in the
| | 02:57 | lower right hand corner and you should
see the web server icon up here.
| | 03:01 | Now, go back up to the web address and trim
the URL to end with Chapter10Begin.
| | 03:08 | this should take you to Directory Listing
of all the files in the project. Now,
| | 03:13 | click on to PersonService.asmx. When you
browse to the ASMX file directly from
| | 03:18 | a web browser, a page is generated that
lists all of the operations or
| | 03:23 | functions of the service.
| | 03:25 | Again, notice that the function names are
FindAll, Insert, Remove and Update.
| | 03:31 | Also, notice that there is a link for the
Service Description and if you click
| | 03:34 | on that link, that will take you to the WSDL
address for this service, you will
| | 03:39 | need this information, if you're going to
call this web service directly later
| | 03:43 | on. Taking a step back, from this screen
you can click into any of the links
| | 03:48 | and you can try out each of the operations.
For example, I'll click into
| | 03:52 | FindAll and I am asked for three values,
the city that I want to filter on,
| | 03:57 | which I'll put in as Houston, the orderField
which I'll leave blank and the
| | 04:02 | orderDescription, which I'll set to a value
of true, I'll click Invoke and the
| | 04:07 | result is that the data is
returned in XML format.
| | 04:10 | So, this is an easy way to test out and try
the ASP.NET Web Service operations
| | 04:15 | without having to write any Flex code
yet. I'll go back to the list of
| | 04:19 | operations and I'll click into the Insert
operation. Both the Insert and the
| | 04:24 | Update operations require individual values
for each property that you need to
| | 04:29 | set. With web services, all arguments or
parameters are required and so if I
| | 04:34 | wanted to execute this Insert operation from
within a Flex application, I would
| | 04:39 | have to send all of these properties
to the web service. Unlike the
| | 04:43 | RemoteObject environment, where you can
use optional arguments, in the web
| | 04:47 | service architecture, all arguments
or parameters are required.
| | 04:51 | Let's go back one more time to the Flex code
and run the application again. As
| | 04:57 | I mentioned previously, the Flex Client Application,
that's generated is fairly
| | 05:00 | simple, even trivial. What's truly valuable
about this generated code is the
| | 05:05 | server-side functionality.
| | 05:07 | So, in the remaining videos in this chapter,
I am going to describe ways to use
| | 05:11 | those generated web services in
your own Flex applications.
| | Collapse this transcript |
| Using the WebService component| 00:00 | In this video I am going to describe how
to use the generated WebService code
| | 00:05 | and call it from a Flex application using
the Flex class library's WebService component.
| | 00:11 | Before you can use the WebService component
you must know the WSDL address of
| | 00:15 | the web service you want to call, which
I am displaying on the screen now.
| | 00:19 | Typically I will navigate to the WSDL address
from the Browser to verify that I
| | 00:24 | have the right address and that I am able
to reach the WSDL address from the
| | 00:27 | local machine.
| | 00:29 | The Flex application requires this WSDL
address and uses it to determine the
| | 00:34 | names of the operations, what sort of data
needs to be passed in, and what sort
| | 00:38 | of data will be returned.
| | 00:40 | After you navigate to the WSDL address just
copy it to the Clipboard and then
| | 00:44 | you will be able to paste it into your
Flex code when the time comes.
| | 00:48 | Now I will close the Browser and go
back to Flex Builder. For this
| | 00:51 | demonstration I am going to use the application
file FlexAndDotNet.mxml. This
| | 00:56 | was the beginning application that I created
when I first created this project.
| | 01:01 | Place the cursor after the application
start tag and above the label in the
| | 01:05 | application, and then declare an instance
of the WebService component using MXML.
| | 01:11 | As with all RPC components you always assign
an ID so that you can refer to the
| | 01:16 | object in your ActionScript code
and binding expressions.
| | 01:19 | I am going to assign an ID of myService.
Now at a WSDL property. The WSDL
| | 01:27 | property is the location of the WSDL address
for this service, and then if you
| | 01:33 | copy the WSDL address from the Browser
you can paste it in here.
| | 01:39 | As the application starts up the WebService
component makes an initial request
| | 01:43 | to this WSDL address, it downloads the WSDL
content, parses it and then once
| | 01:49 | it's understood the names of the operations
and all of the other information in
| | 01:53 | the WSDL, it dispatches an event named Load.
| | 01:57 | The Load event tells you that the WebService
component is ready for use and you
| | 02:00 | can start making operation calls.
| | 02:03 | You can also make start-up calls from the
application complete or creation
| | 02:07 | complete events of the application. Sometimes
those events will be dispatched
| | 02:11 | before the load event of the web service,
but if that happens your calls will
| | 02:16 | be queued, and the call to the remote operation
will only happen once the load
| | 02:20 | event has been dispatched.
| | 02:21 | I am going to listen for the load event,
and when it happens I will make an
| | 02:26 | initial call to retrieve data from the
web service. So put in a load event
| | 02:31 | handler and within the load event handler
call a custom function that will need
| | 02:36 | to create named getData.
| | 02:39 | Now place the cursor above the WebService
component declaration, create a
| | 02:43 | script section and create the new getData
function. This function will return
| | 02:49 | void and it will contain a single call to
one of the remote operations of the
| | 02:55 | web service. I am going to call remote
operation name FindAll like this,
| | 03:00 | myService.FindAll. And then I am going
to pass in the operation's three
| | 03:05 | required arguments.
| | 03:07 | The first argument is the name of a city
on which you want to filter. I will
| | 03:11 | pass in a blank string meaning, I don't
want to filter at all. The second is
| | 03:15 | the name of a column on which you want to
sort and I will pass in the last name
| | 03:19 | column, and the third, is a boolean value
indicating whether you want to sort
| | 03:24 | in descending order. By passing in a value
of False I am indicating that I want
| | 03:29 | to use the default ascending order.
| | 03:31 | The next step is to handle the result, just
as with other RPC components you
| | 03:37 | can handle the results of calls to remote
functions using either binding
| | 03:41 | expressions or the result event handler.
| | 03:44 | In the case of an ASP.NET Web Service operation
that returns an ASP.NET data
| | 03:50 | table, the content that comes back is
not a simple array or an array
| | 03:54 | collection. So it's almost always better
to use result event handler to handle
| | 03:59 | the return data.
| | 04:01 | Go to the Web Service tag and add an attribute
paste result event listener and
| | 04:07 | call function named resultHandler which
we will need to create and pass the
| | 04:11 | event object.
| | 04:13 | Now create that function, place the cursor
in the Script section and declare a
| | 04:17 | new private function named resultHandler.
It will receive an event argument
| | 04:23 | data typed as ResultEvent and return void.
| | 04:28 | Now, place a break point on the last line
of the function that is the line with
| | 04:32 | the closing brace. Save your changes and
run the application in Debug mode. As
| | 04:39 | the application starts up it makes the call
to the remote operation and then
| | 04:42 | Flex Builder should prompt you to open
the FlexDebugging perspective.
| | 04:47 | Open the debugging perspective, expand the
Variables view and inspect the event
| | 04:51 | object result property. The result property
comes back as an ObjectProxy, it
| | 04:57 | contains a property named Tables with an
uppercase T which in turn contains an
| | 05:02 | item named Table0 and within that object
there is a property named Columns and
| | 05:07 | another one named Rows.
| | 05:09 | The full expression for the data
that you want to retrieve is
| | 05:13 | event.result.Tables.Table0.Rows and notice
that each property has an initial
| | 05:20 | uppercase character. Within the Rows
ArrayCollection you'll find the actual data.
| | 05:26 | So here's how we will now capture the data
and save it persistently. Restore
| | 05:30 | the size of the Variables view and terminate
your Debugging session. Declare a
| | 05:35 | new bindable ArrayCollection variable as
follows. Place the cursor above the
| | 05:39 | getData function. Put in the bindable metadata
tag and declare a new private
| | 05:44 | variable named myData data typed
as an ArrayCollection.
| | 05:48 | Now place the cursor inside the resultHandler
function and save the data using
| | 05:53 | the following code.
| | 05:54 | myData = event.result.Tables.Table0.Rows.
| | 06:03 | If you want you can add an explicit typecasting
of as ArrayCollection. This
| | 06:09 | isn't really necessary in this particular
syntax, but it will make it clear
| | 06:13 | later on exactly how you are saving the data.
| | 06:16 | Now, place the cursor towards the bottom
of the application after the existing
| | 06:20 | label. Create a data grid and set its data
provider using a binding expression
| | 06:25 | to myData.
| | 06:28 | So those are all the steps. As the application
starts up we will make the call
| | 06:32 | to the remote method. The result event
listener calls the resultHandler
| | 06:36 | function which saves the resulting data to
the myData object which has already
| | 06:41 | been declared as a Bindable ArrayCollection.
| | 06:44 | Run the application in Normal mode this
time, and you'll find that if the
| | 06:48 | application starts up it loads
and displays the data.
| | 06:51 | So that's to look how you can work with
the ASP.NET code that's generated by
| | 06:56 | the Data Wizard. It's a standard SOAP-based
Web Service. After you generate the
| | 07:01 | code it's typically a good idea to inspect
the results and then you can write
| | 07:05 | your own custom web service code to integrate
the web services into your own
| | 07:10 | Flex application.
| | Collapse this transcript |
|
|
11. Managing Data on the ClientFiltering data with the ArrayCollection class| 00:00 | In this chapter of the video series I am
going to demonstrate some advanced
| | 00:04 | capabilities of the ArrayCollection class.
We use the ArrayCollection class to
| | 00:08 | manage data in Flex Client applications
at runtime. The ArrayCollection is a
| | 00:13 | wrapper class that contains an array and
provides consistent dynamic binding
| | 00:18 | capabilities so that any changes to the
data it contains are broadcast to any
| | 00:22 | part of the application. But the ArrayCollection
class also implements a set of
| | 00:26 | interfaces that allow you to filter, sort,
search and bookmark data completely
| | 00:32 | within the client application.
| | 00:34 | These are features of your own applications
that in a classic web application
| | 00:38 | build purely say in ColdFusion or PHP or
ASP.NET would require multiple round
| | 00:44 | trips to the server and multiple requests
to the database. In a Flex
| | 00:49 | application you can handle a lot of these
tasks completely within the client,
| | 00:53 | eliminating a lot of round trips to the
server, eliminating a lot of database
| | 00:57 | usage and increasing the scalability in terms
of numbers of concurrent users of
| | 01:02 | your applications. For the exercises in this
chapter I will use a Flex Project
| | 01:07 | Archive that's available in the Exercise
Files. If you are following along with
| | 01:11 | the exercises, you can import this Project now.
| | 01:14 | Navigate to the Exercises folder which
on my system is on my Desktop. From
| | 01:19 | there go to the Chapter11 folder and select
the file Chapter11BeginProject.zip.
| | 01:26 | Complete the import process, go to the
Flex Navigator view and open the
| | 01:30 | project. Open the Source folder and
then open the application file
| | 01:35 | FilteringData.mxml. This application retrieves
and displays an XML dataset. The
| | 01:43 | same dataset I have been using in many other
parts of this video series, but
| | 01:47 | this time rendered as a pure XML file.
| | 01:49 | As the XML file was retrieved using the
HTTPService component, it's data is
| | 01:54 | then saved to persistent ArrayCollection
object and displayed in this DataGrid
| | 01:58 | control. In this application, there is a
user interface that's going to allow
| | 02:03 | us to apply a filter. As the user types in
the name of a city, we will be able
| | 02:08 | to filter the data completely within the
Flex client application and we won't
| | 02:12 | have to use a database on the server or any
other server-side functionality to
| | 02:16 | execute this filter.
| | 02:19 | Let's go back to the application. In order
to filter data on the client using
| | 02:23 | the ArrayCollection class, you use a property
of the class named the filter
| | 02:27 | function. The filterFunction property points
to a call back method that you
| | 02:30 | create. Whenever you set the filter
function and then call the
| | 02:34 | ArrayCollection's refresh method, that
causes the ArrayCollection to loop
| | 02:38 | through it's data and call the callback
function once for each of it's data
| | 02:42 | items. It passes the data item into the
function and receives back a Boolean
| | 02:47 | true or false value. If the filter function
returns a value of true that means
| | 02:52 | that that particular data item should be
exposed in a filtered view and if the
| | 02:56 | filter function returns false that means
that that particular data object
| | 03:00 | should be hidden in the filtered view.
| | 03:01 | Here are the steps. First of all let's
create the filter function. A filter
| | 03:07 | function always has the same signature.
It receives a single argument which
| | 03:11 | will be a data object and returns Boolean.
I am going to create a function
| | 03:16 | named filterByCity and I will set the name
of the argument as item and it's
| | 03:22 | data type as object and this function
will return a value that's Boolean.
| | 03:27 | Now when you execute the filter, again
the ArrayCollection is going to call
| | 03:32 | this function once for each data item. Your
job is to get the value that you
| | 03:36 | want to compare to, compare to something
and return a Boolean expression. I am
| | 03:41 | going to use the value from this TextInput
control with an id of filerInput and
| | 03:46 | compare it to the City property of the data
object like this. If (item.city ==
| | 03:54 | filterInput.text) and if the two values match,
I will return true and otherwise
| | 04:02 | I will return false.
| | 04:05 | You can make the logic of the filter function
as complex or as simple as you
| | 04:09 | like. This is a simple example. Notice that
the structure of the code though
| | 04:13 | guarantees that we are always returning
a Boolean value. Now to apply the
| | 04:17 | filter function. Create a new function named
doFilter. This is simple function
| | 04:25 | that receives no argument and returns void.
| | 04:28 | Now the next step is to examine the value
of the filterInput control. If the
| | 04:32 | user has typed a value into the filtered
TextInput that means they want to
| | 04:37 | filter. If they have left that TextInput
control blank however, that means they
| | 04:41 | don't need to do a filter at all. The most
efficient approach here is to set
| | 04:45 | the filterFunction property of the ArrayCollection
to either the name of the
| | 04:49 | filter function that you want to use or to
null if you don't to filter at all.
| | 04:54 | So, I will use this conditional logic. If
filterInput.text.length is 0 then I
| | 05:03 | am going to set the ArrayCollection's filterFunction
property to null, meaning
| | 05:07 | we don't to filter and we want to expose
all of the data. The name of the
| | 05:11 | ArrayCollection that we are filtering on
is contacts and it's declared at the
| | 05:15 | top of the Script section. So returning
back to the dofilter function. I will
| | 05:20 | use this code to eliminate any filters.
Contacts.filter function = null. Then
| | 05:28 | in the else clause, I will set the filter
function to the name of the function
| | 05:32 | that I want to execute for each
data object, filterByCity.
| | 05:36 | Now I am calling this the name of the function.
In reality, we are passing the
| | 05:40 | function as an object to the filterFunction
property. Finally after the
| | 05:46 | conditional clauses, call the refresh method
of the ArrayCollection as follows,
| | 05:50 | contacts.refresh(). Now to execute the filter,
go down to the declaration of
| | 05:58 | the Panel container that contains the
DataGrid and all of the other user
| | 06:02 | interface controls. Locate the button with
the label of Filter add a click
| | 06:06 | event listener and call the method doFilter.
Save the changes and run the application.
| | 06:14 | When the application appears, it displays
all of the data. Now I am going to
| | 06:18 | type in the name of a city, I will use Houston
and click the Filter button and
| | 06:24 | you will see that only the rows that have
that value in the City column are
| | 06:28 | displayed. Now I will remove the filter by
deleting that value click the Filter
| | 06:33 | button again and all of the data appears.
Notice that even though we are
| | 06:37 | filtering on a thousand records, the filtering
process executes in an instant.
| | 06:42 | This sort of filter is very, very fast and
you can filter enormous amounts of
| | 06:46 | data on the client without having to
do a round trip to the server.
| | 06:50 | To really thoroughly understand what's happening
here, I am going to go back to
| | 06:54 | the code, to the filterByCity and add a
call to trace. I am going to output a
| | 07:00 | literal string of Filtering on and then
I will concatenate that to the city
| | 07:05 | property of the current data object.
I will save the change and run the
| | 07:10 | application again. This time in Debug
mode and then I will resize the
| | 07:15 | application browser window, so that I can
see the console of Flex Builder in
| | 07:19 | the background.
| | 07:20 | Now I will click into the City Filter and
I will type a city name, this time I
| | 07:24 | will type Jackson and click Filter and
you will see in the console that the
| | 07:28 | filter function has been called 1000 times
in an instant. I will go back to the
| | 07:33 | application and remove the filter, click
the button again and this time you
| | 07:39 | should see in the console that the filtering
function isn't being called at
| | 07:42 | all, because the filterFunction property
of the ArrayCollection is set to null.
| | 07:47 | So that's one of the advanced features of
the ArrayCollection class. It allows
| | 07:51 | you to filter data on the client using a
very fast architecture without having
| | 07:56 | to resort to using the database on the
server. This can eliminate network
| | 08:00 | traffic, database usage and all sorts of
overuse of other shared resources and
| | 08:05 | push the processing of this data filtering
mechanism down to the client application.
| | Collapse this transcript |
| Sorting data with the ArrayCollection class| 00:00 | In this video, I am going to describe
another advanced feature of the
| | 00:04 | ArrayCollection class that allows you to
sort data on the client. Using this
| | 00:08 | feature you can sort data on one or more
columns of the data objects within an
| | 00:13 | ArrayCollection, you will use a set of
classes name Sort and SortField. The
| | 00:18 | sort object is attached to the ArrayCollection
through its sort property and
| | 00:22 | you create one or more SortField objects
to represent the fields on which you
| | 00:26 | want to sort.
| | 00:27 | For this demonstration, I will use the
application SortingData.mxml. This
| | 00:32 | application like the one in the previous
video retrieves a set of data that's
| | 00:36 | in an XML file in the project and then
displays the data in a data grid
| | 00:41 | component. This version of the application
has a set of radio buttons at the
| | 00:45 | bottom for sorting on the City column and
on two columns Last Name and First
| | 00:50 | Name and the action script class
is that I described.
| | 00:53 | I will close the browser and return to the
code. The application already has a
| | 00:57 | function called doSort. Here is how you
create a sort, let's say for example
| | 01:02 | that you want to sort on a single column
or property of the data objects and
| | 01:06 | the ArrayCollection, the first step is to
create an instance of the SortField
| | 01:11 | object like this, I will create a variable
named Field data typed as a Sort
| | 01:16 | Field class, and then instantiated using
the classes constructor method.
| | 01:23 | The SortField constructor method allows you
to pass in a number of values. The
| | 01:27 | first argument is the name of the property
on which you want to sort. So for
| | 01:31 | example, if I wanted to sort on the City
column, I would type in the name of
| | 01:35 | their property as its known
in the ArrayCollection.
| | 01:37 | I will type in the value of City, the next
argument indicates whether you want
| | 01:43 | to sort using a case insensitive or sensitive
architecture. By default, the
| | 01:48 | sort is case insensitive, if you want to
make it case sensitive you pass in a
| | 01:51 | value of true and the third value is the
descending argument. By default the
| | 01:57 | sort is ascending, if you want it to make
descending you pass in a value of true.
| | 02:01 | I am going to leave out that argument and
the result will be a sort on the city
| | 02:06 | property which is case insensitive. The
next step is to create an instance of
| | 02:10 | the sort class. I will call it mySort and
data type it as the sort class. You
| | 02:18 | instantiate the Sort class using the classes
no arguments constructor method.
| | 02:22 | Then you take your SortField objects and
you pass them into an array and pass
| | 02:28 | the array to the fields property
of the sort object like this.
| | 02:32 | I will use a bit of short hand mySort.fields
=. Then I will add a pair of
| | 02:38 | brackets to declare an ActionScript array
and pass in the SortField object. The
| | 02:43 | next step is to attach the sort object to
the ArrayCollection. I will use the
| | 02:48 | ArrayCollection and contacts and set is sort
property to mySort. The final step
| | 02:54 | in the process just as with filtering
on the client is to refresh the
| | 02:58 | ArrayCollection. I will call contacts.refresh().
Now, to trigger the sort
| | 03:04 | operation, I listen for an event of the Radio
Button Group named itemClick and
| | 03:09 | I will call my function doSort.
| | 03:12 | For the movement, I am always sorting on
the City field. I will fix that in the
| | 03:15 | later part of the exercise. I will run
the application when the Data first
| | 03:21 | appears it's returned in the same sort order
as its declared in the XML file,
| | 03:26 | but now when I click either of the radio
buttons the result is to sort by City.
| | 03:32 | Let's return to the Source code and I would
also like to demonstrate how to
| | 03:35 | apply a sort on more that one
field at the same time.
| | 03:39 | Notice that the radio buttons each have values
of city and name. So within the
| | 03:43 | doSort function I am going to add some conditional
code that detects what kind
| | 03:47 | of sort operation is being asked for. I
will put in the conditional clause
| | 03:51 | that's look like this if (sortGroup.selectedValue.toString()
== "city") and
| | 04:02 | now, I am going to move the code around
a little bit. I will take the line of
| | 04:06 | code that creates the sort object and I
am going to move that above the If declaration.
| | 04:11 | I moved the code up by the way by holding
down the Alt key and pressing the up
| | 04:15 | cursor key, once for each line I wanted
to move it. Now, I will take the two
| | 04:19 | lines of code that create the SortField object
for the City column and set the
| | 04:23 | array, and I will move those within the
If clause. Now, I will add in else
| | 04:30 | clause and I am going to copy the code from
the first part and paste it into
| | 04:37 | the else clause and then I am going to modify
the version in the else clause as follows.
| | 04:42 | The only other radio button in the radio
button group request a sort by
| | 04:47 | lastname and firstname. So I am going to
change the code as follows, I will
| | 04:51 | change the name of the variable to field1
and change the name of the property I
| | 04:56 | am sorting on to lastname. Now, I will clone
that line of code, change the name
| | 05:01 | of the second variable to field2 and change
the sort field to firstname.
| | 05:06 | I am going to move the code around a little
bit so we can see all of it on the
| | 05:11 | screen at the same time, and then I will
change the fields property of the sort
| | 05:16 | object as follows, it will still be an array
but this time it will contain two
| | 05:22 | SortField objects, field1 and field2. So
now the conditional code is working as
| | 05:27 | follows, regardless of which sort, sort
order is being used I am creating the
| | 05:32 | sort object first, then i am applying some
conditional logic and determining
| | 05:37 | whether the user has asked for the single
column sort on city and if so I am
| | 05:41 | setting up the architecture for that and
otherwise I am assuming that they are
| | 05:44 | asking for the two column sort on Last Name
and First Name and I am setting up
| | 05:48 | the objects for that.
| | 05:49 | At the end of the process, I am applying
the sort object to the ArrayCollection
| | 05:53 | and then refreshing the ArrayCollection.
I save and run the application again.
| | 05:58 | I will once again click the City radio button,
and you will see that the data
| | 06:04 | is sorted by city and then I will select
the other radio button and sort by
| | 06:08 | Last Name and then First Name and notice
that there are multiple rows with the
| | 06:13 | last name of Adams and within that data
set they are sorted by first name
| | 06:17 | alphabetically.
| | 06:18 | So you can see that you are effectively doing
a multi-property sort. So that's
| | 06:22 | how you apply sort operations using the ArrayCollection,
the Sort class and the
| | 06:28 | SortField class. To review the architecture
one more time, you create the sort
| | 06:33 | object, you create SortField objects for
each column or property on which you
| | 06:38 | want to sort, you wrap those into an array,
apply them to the field property of
| | 06:42 | the sort object, apply the sort object to
the ArrayCollection through its sort
| | 06:46 | property and refresh the ArrayCollection.
| | Collapse this transcript |
| Finding data with the IViewCursor interface| 00:02 | In this video, I am going to describe an
interface known as a view cursor. The
| | 00:06 | purpose of a view cursor is to allow you
to reverse data in an ArrayCollection
| | 00:11 | moving up, down bookmarking the data and
locating data. I am going to describe
| | 00:16 | one particular feature of the cursor interface
in this exercise. For this
| | 00:20 | demonstration, I will use the application
FindingData.mxml.
| | 00:24 | In this version of the application, once
again we are retrieving a displaying
| | 00:27 | data from an XML file. When the data first
appears, it's already sorted on Last
| | 00:32 | Name and First Name and there is a small
data entry form at the bottom of the
| | 00:36 | panel that allows you to type in a first
name and last name value. I am going
| | 00:41 | to show you how to use a cursor to search
by particular values and locate data
| | 00:46 | objects in ArrayCollection, unlike the
filtering functionality that I
| | 00:51 | demonstrated earlier in this chapter.
| | 00:53 | In this example, I won't be filtering or
reducing the number of rows that are
| | 00:56 | displayed, instead I am going to locate a
particular record and move data grid
| | 01:01 | selector row to that record. You get an
instance of a view cursor by calling
| | 01:08 | the ArrayCollection's create cursor method.
Go to the Source code and locate
| | 01:14 | the existing function in this application
named doFind. Notice two things about
| | 01:19 | the way this application presents the data.
| | 01:21 | First of all the doSort function is being
called when the data is first
| | 01:25 | retrieved from the XML file. So it's already
sorted and then the data grid
| | 01:30 | component in this application has its sortableColumns
property set to false.
| | 01:35 | This is because you can only use a cursor
to locate data on a sorted view of
| | 01:40 | the ArrayCollection and the columns on which
you search must be a part of the sort.
| | 01:46 | So the doSort function is already setup
to sort on lastname and firstname and
| | 01:51 | those are the columns on which we are going
to search. In fact if you try to
| | 01:55 | use the functions that I am going to demonstrate
here and you try to search on
| | 01:58 | a property that's not a part of the current
sort order, a run time error occurs
| | 02:02 | in Flex 3.
| | 02:03 | Here are the steps for using a cursor to
locate data. I am going to add all of
| | 02:08 | this code to the doFind function and that
function will be called when I click
| | 02:12 | the button in the interface. The first step
is to create a variable data typed
| | 02:16 | as an IviewCursor. I am going to name the
variable cursor and give it its data
| | 02:21 | type of IViewCursor and then I am going to
initialize the object by calling the
| | 02:26 | ArrayCollection's create cursor method.
| | 02:29 | Now, I am going to create a search object.
The purpose of the search object is
| | 02:34 | to indicate which properties you want to
search on and what values you want to
| | 02:38 | search for. You create it as a generic ActionScript
Object. I will create a new
| | 02:43 | variable name searchObj data typed as an
Object, and then I will initialize it
| | 02:49 | using the object classes no
arguments constructor.
| | 02:53 | Next, I am going to create named properties
of the search object where the name
| | 02:57 | of each property matches the property of
the data objects I want to search on.
| | 03:01 | I will get the values from the input controls
at the bottom of the application.
| | 03:06 | First, I will add a property named
lastname and set its value to
| | 03:10 | lnameInput.text and then I will do the
same thing again for the first name
| | 03:15 | field searchObj.firstname = fnameInput.text.
| | 03:23 | Again the names of the properties here must
match the names of the properties
| | 03:27 | in the data objects you are searching. Now,
I am going to use the search object
| | 03:32 | by calling a function of the cursor named
findAny. There are three functions
| | 03:36 | that you could call in this location findAny,
findFirst and findLast, they each
| | 03:41 | take a search object as their parameter and
they each return a boolean true or false.
| | 03:46 | If you get back a value of true that means
a data object was found and if you
| | 03:51 | get back a value of false that means
nothing was found. So here is the
| | 03:54 | conditional code. if (cursor.findAny, and
then now pass in the search object
| | 04:04 | and then I will put in a pair of braces
and an else clause and then I will go
| | 04:11 | back to the first part the if clause.
| | 04:14 | If the cursor finds an object and returns
true then the cursor objects current
| | 04:18 | property points to the data object that
was found. I am going to take that
| | 04:23 | reference to the data object and pass
it to the data grids selected item
| | 04:27 | property that will cause the data grid to
select the appropriate row. The data
| | 04:32 | grid's ID is myGrid. So I will its selected
row as follows, myGrid.selectedItem
| | 04:40 | = cursor.current.
| | 04:43 | Now, after I set the selected item property
I am also going to make the data
| | 04:47 | grid scroll to that row using this code.
myGrid.scrollToIndex and then pass in
| | 04:54 | the currently selected index of the data
grid using (myGrid.selectedIndex). In
| | 05:03 | the else clause, I will simply report to
the user that nothing was found. I
| | 05:08 | will use the Alert class's show method and
I will output a message of ("No data
| | 05:13 | was found for this search", and I will
add a title of "Not Found");
| | 05:24 | So that's the basic functionality of a
cursor when you use it to search for
| | 05:28 | data. Once again, you use the findAny, findFirst
or findLast functions. findAny
| | 05:33 | will search any where in the ArrayCollection.
findFirst goes to the top of the
| | 05:37 | ArrayCollection and searches forward and
findLast goes to the bottom of the
| | 05:41 | ArrayCollection and searches backward. Save
and run the application and when
| | 05:46 | the data is displayed in the application,
you can try searching as follows,
| | 05:51 | let's say for example that you want to search
for something that was way down
| | 05:54 | at the bottom.
| | 05:54 | I will search for Frank Young. So I will
start of selecting a row, I will type
| | 06:00 | in values of Frank and Young and click Search
and you will see that the data is
| | 06:06 | located correctly.
| | 06:07 | Now if you type in a value that's not found
and you click Search, you should
| | 06:12 | get the message, no data was found for
this search. So you can see that the
| | 06:16 | cursor component is able to search for data
and you determine which columns you
| | 06:21 | are searching on and which values by creating
a generic ActionScript Object
| | 06:26 | which we call the search object and applying
properties whose names match the
| | 06:30 | properties in the data objects
you are searching.
| | 06:33 | This allows you to do a finally tuned
search completely within the client
| | 06:38 | without having to go back to the database
and the application server and create
| | 06:42 | unnecessary round trips across the network.
The cursor component also has
| | 06:47 | methods that allow you to get bookmarks
to data and return to the data later
| | 06:51 | on. The one important limitation to understand
about the cursor interface when
| | 06:55 | you are using it the find data is that the
data that you are searching must be
| | 06:59 | sorted and the columns on which you are
searching must be a part of the sort order.
| | 07:03 | If your particular application's functionality
is able to work within those
| | 07:07 | limitations then this is a great interface
and tool that you can you use to
| | 07:12 | allow server-side location of data without
use of the server-side database.
| | Collapse this transcript |
|
|
12. Working with ModulesCreating a Module component| 00:00 | In this chapter of the video series I am
going to describe how to use run time
| | 00:04 | loadable modules. The module architecture
in Flex allows you to create large
| | 00:08 | scale Flex applications that have dozens
or even hundreds of views or
| | 00:12 | presentations and allows you to break down
the views and functionality in the
| | 00:16 | application in to a multiple SWF files.
| | 00:19 | The main application file can be kept very,
very small and then as the user
| | 00:23 | navigates around to different bits of functionality
in the application, you'll
| | 00:26 | be able to download that functionality
from the website as needed.
| | 00:30 | As result the initial download is kept
as small as possible. For the
| | 00:34 | demonstrations in this chapter, I will use
a Flex project archive that is in
| | 00:38 | the Exercises folder. If you have access
to the exercises files and you are
| | 00:42 | following along you can import the project now.
| | 00:45 | From the Menu select File, Import FlexProject.
Click the Browse button next to
| | 00:52 | archive file, navigate to the exercises
folder and to it's sub folder Chapter
| | 00:56 | 12, and then select and Import the file
Chapter12BeginProject.zip. In this
| | 01:03 | video I am going to describe how to create
a new module component. A module is
| | 01:08 | a visual container, in fact it's derived
from the Vbox container, but unlike
| | 01:12 | them Vbox it has a Layout property that
allows you to set a modules layout to
| | 01:16 | either horizontal, vertical or absolute.
| | 01:19 | Just like the panel container in the application.
You typically create each
| | 01:23 | module as an MXML component, but Flex Builder
has its own distinct wizard for
| | 01:28 | creating a module that has some other
options from the standard component
| | 01:32 | creation wizard. Go to the Flex Navigator
view open the project and open it's
| | 01:37 | source folder and you find that there is
sub folder there named modules. That
| | 01:41 | is where I am going to place all of
the modules for this application.
| | 01:45 | To create a new module right click on the
module's folder or control click on
| | 01:49 | the Mac and select New MXMLmodule. Notice
that this is a different menu choice
| | 01:55 | than MXML component. The new MXL module
wizard asked for the file name which
| | 02:01 | will be a .mxml file, just like any other
component. I am going to name my new
| | 02:06 | module ChartModule.MXML. Just like other
components you can set the width and
| | 02:11 | height in the wizard, I am going to set the
width and height of the ChartModule
| | 02:15 | to 100% each, so that the module component
will expand to fill it's container
| | 02:20 | and I'll set the layout value to vertical.
| | 02:24 | The next option has to do with optimization
of the SWF files size for the
| | 02:28 | compiled version of the module. The default
is to optimize the SWF file for use
| | 02:33 | with the particular application. This
allows you to eliminate redundant
| | 02:38 | compellations meaning, that if you have a
particular visual component or other
| | 02:42 | class that's used both in the application
and in a particular module by
| | 02:46 | optimizing, you can minimize the size of
the module and their by speed up the
| | 02:51 | download and availability of the module
when you need it. I am going to
| | 02:54 | optimize my SWF file size for a particular
application Use Moduleloaded.mxml.
| | 03:00 | Then I'll click finish and that creates
the module, just like any other MXML
| | 03:05 | component. A module consists of a MXML
file, but its root element is MXML: module.
| | 03:12 | Now, to fill in the functionality of
this module I am going to open an
| | 03:15 | application from this project named Simple
Chart.mxml. This is an application
| | 03:21 | that displays a pie chart with some fixed
data and then a legend at the bottom.
| | 03:27 | I'll go back to Flex builder to the code
for the application containing the
| | 03:30 | chart. Now I am going to canabalize this
application, I am going to take it's
| | 03:35 | script and also all it's visual controls
and copy them into the ChartModule.
| | 03:39 | I will click at the beginning of the script
section then scroll down to the
| | 03:44 | bottom, hold down the Shiftkey and select
everything inside the application
| | 03:49 | tags. Now I will copy that code to the clipboard
go back to the module and then
| | 03:54 | paste the code with in the module tags. I'll
save the changes and each time you
| | 04:00 | make a change and save the code for a module
it recompiles the module itself.
| | 04:06 | Let's take a look at the resulting SWF
file for this module. Go back to the
| | 04:11 | Flex Navigator view to the bin-debug output
folder. You notice within the
| | 04:16 | output folder there is the module folder
now and in that folder there is now
| | 04:20 | file named ChartModule.SWF. This is the
compiled version of your module.
| | 04:25 | Let us take a look at the file size, right
click on the SWF files or control
| | 04:29 | click on the Mac and select properties from
the Menu that pops up. Notice the
| | 04:35 | size of the module because I am using charting
components for the first time
| | 04:40 | this file is fairly large 173k because it
now has to compile in the definitions
| | 04:45 | of all the visual controls I am using
including the pie chart.
| | 04:49 | Now, I am going to demonstrate optimization.
I'll go down to the source folder
| | 04:54 | and locate the application for which I optimized
my module component. I will
| | 04:59 | open the application and in this script section
I am going to declare a single
| | 05:04 | instance of the pie chart component. I will
use this syntax private var chart:
| | 05:11 | data typed as pie chart. I will save the
changes now I am going to clean the
| | 05:17 | project which will cause everything to
recompile. From the Menu I'll select
| | 05:22 | Project, Clean and then click OK and that
will cause all of the applications
| | 05:28 | and components to look at each other
and we optimize as needed.
| | 05:33 | Now I will go to back to the Output folder
to the Module sub folder and once
| | 05:37 | again take a look at the properties for
the complied component and you'll see
| | 05:41 | that the component has shrunken dramatically.
On my system from about 170k down
| | 05:46 | to about 46k. So, that's how optimization
of modules works. By optimizing
| | 05:52 | against a particular Flex application
you eliminate redundancies in the
| | 05:56 | compiled SWF files and you minimize
the size of the modules.
| | 06:00 | Now in the next video I'll show you how
to use a component called the Module
| | 06:04 | Loader to load this module at run time.
| | Collapse this transcript |
| Loading a module with ModuleLoader| 00:00 | In this video, I am going to describe how
to use a component called the module
| | 00:04 | loader to load modules at runtime. Before
you can use the module loader, you
| | 00:08 | must have first created and compiled a set
of modules. I have created one so
| | 00:12 | far and I am going to add one more during
this video. For this demonstration, I
| | 00:16 | will use the application usemoduleloader.mxml.
If you are following along with
| | 00:21 | the exercises, you can open this file now.
| | 00:24 | The module loader is a visual container.
You place it in your application,
| | 00:28 | where you want the module to appear. For
example, if you want to place the
| | 00:32 | module loader in an application that uses
absolute layout, you can use the
| | 00:36 | module loader's X and Y properties or constraint
the properties to place it in
| | 00:40 | a specific location on the screen. I am going
to declare my module loader after
| | 00:45 | the application control bar and then I
am going to set its width and height
| | 00:48 | properties to a 100% so that it fills the
available space in the application.
| | 00:53 | Place the cursor after the Application Control
Bar declaration and declare a
| | 00:57 | module loader. Set its ID to loader. Set
its width and its height to 100% each.
| | 01:08 | Now because you are not adding anything to
the loader initially, you don't have
| | 01:12 | to put in a pair of tags, even though it
is a container. The next step is to
| | 01:16 | actually load a module at runtime. This
application already has a function
| | 01:21 | called Load Chart module and this function
is being called when you click the
| | 01:24 | button labeled Load Chart. Place the cursor
inside the function, there are two
| | 01:29 | steps to loading a module.
| | 01:30 | First you set the URL property of the
module loader component as follows
| | 01:36 | loader.url = and then you typically use
a relative address pointing to the
| | 01:41 | location and the file name of the compiled
module SWF file as follows
| | 01:47 | modules/chartmodules.swf. Be sure to use
a forward slash here and not a back
| | 01:54 | slash. On windows, the back slash might
work for now, but when you load this
| | 01:58 | application from the web, it wouldn't work.
The next step is to call a method
| | 02:03 | of the module loader component called load
module. This function doesn't take
| | 02:07 | any arguments, it simply uses the URL when
you have already indicated where
| | 02:11 | your module is and loads it from the web.
I will use this syntax loader.load
| | 02:16 | module, save the changes and run the application.
As the application starts up,
| | 02:24 | it doesn't display any modules initially.
Now click the button labeled Load
| | 02:28 | Chart and you should see the Chart Component
appear, by clicking the button,
| | 02:33 | you are downloading the SWF file from the
web and it's being displayed. Now as
| | 02:37 | with images, the SWF file will
be cached on the local disk.
| | 02:40 | So the next time that same module is loaded,
you will be loading from the
| | 02:44 | cached content rather than having to download
it again from the website. Now
| | 02:48 | modules are more impressive if you have
more than one, and there is already
| | 02:51 | another module component in this application.
Take a look in the modules folder
| | 02:56 | and you will see there's a file there named
formodule.mxml. Notice that the
| | 03:01 | icon on formodule.mxml doesn't look the
same as Chart Module which has the
| | 03:05 | little indicator indicating that this is
a compiled module. That's because this
| | 03:09 | module has not been made a
part of the project yet.
| | 03:13 | Here's how you add an existing module
component source code file to your
| | 03:17 | project and cause it to start compiling.
Go to the menu and select the project,
| | 03:22 | properties. Select Flex modules from the
list of categories and you will see
| | 03:28 | that Chartmodule.mxml is being built for
this project. Click Add and then click
| | 03:33 | the Browse button and navigate to the source
folder within the project to the
| | 03:38 | module's sub folder and select the file
For Module.mxml. Click Okay, just as
| | 03:45 | when creating a module from scratch, you
have the opportunity at this point to
| | 03:49 | optimize the module for this application.
Click Okay and then click Okay again,
| | 03:56 | now take a look at the Flex navigator view
and you'll see that formoduele.mxml
| | 04:00 | now has the icon indicating that the module
is being built. And if you then go
| | 04:05 | to the Bin Debug output folder, you'll see
that formodule.swf has been created.
| | 04:10 | Now go back to the application. Go to the
loadformodule method and add code to
| | 04:17 | load this module at runtime as follows, loader.url
= modules/formodule.swf and
| | 04:29 | then once again, make the call to loader.loadmodule.
Save your changes and run
| | 04:35 | the application.
| | 04:38 | Now, you are once again able to load the
chart component but you can also go
| | 04:42 | over and click the load form button and
that will load the form component and
| | 04:46 | you can move back and forth between
the modules as needed.
| | 04:49 | So this is how you can maintain multiple
modules in a Flex application and load
| | 04:54 | each one as the user requests that
particular functionality.
| | 04:57 | Now in the next set of videos, I will
talk about how to share information
| | 05:01 | between multiple modules using a variety
of approaches, including events,
| | 05:05 | centralized model management and passing
data directly to module instances.
| | Collapse this transcript |
| Handling Module Component events| 00:00 | In this video, I am going to describe how
to listen for and react to events
| | 00:04 | that are dispatched by module components
that are loaded by the module loader
| | 00:08 | container. Just as with other MXML components,
you can share custom information
| | 00:13 | from the module component by dispatching
a custom event.
| | 00:16 | Let's start in the modules folder of the
project. If you have access to the
| | 00:20 | exercises and you are following along, go
to the modules folder and open the
| | 00:24 | file FormModule.mxml. Notice that this component
defines a custom event named
| | 00:30 | submit and it dispatches an instance
of a custom event class named
| | 00:34 | ChartDataEvent. At runtime, when the user
clicks the button, a variable named
| | 00:38 | data, data typed as an ArrayCollection
is created and populated with
| | 00:42 | information from the data entry form. The
structure of this data is compatible
| | 00:46 | with the pie chart used in the other component.
That data object is then
| | 00:51 | wrapped in to an instance of the ChartDataEvent
custom event class. And then
| | 00:55 | the event object is dispatched from the
module, this is exactly how you would
| | 00:59 | dispatch the custom event from any sort of
MXML component to share information
| | 01:04 | with the rest of the application.
| | 01:06 | Listening for this event however is a
little bit different, the module
| | 01:09 | component instance is a child of the module
loader at runtime and in order to
| | 01:13 | listen for an event on this object, you have
to wait until the object has been
| | 01:17 | loaded into memory and only then can you
add an event listener. I am going to
| | 01:22 | work in an application named, ModuleEvents.mxml,
this application starts where
| | 01:27 | the last one left off. It loads two different
modules, a chart and a form. When
| | 01:32 | you load the FormModule, you are going to
want to listen for an event called
| | 01:36 | ready. The ready event which is dispatched
by the module loader tells you that
| | 01:41 | the module has been completely
loaded and is ready for use.
| | 01:44 | Start in the script section and create
a new private function named
| | 01:49 | readyHandler. The ready event dispatches
an event data typed as the standard
| | 01:56 | event class. Create the eventHandler function
to receive an event object typed
| | 02:03 | as event and return void, now go down to
the ModuleLoader declaration, add a
| | 02:09 | ready event listener and call this function,
passing the event object. Now
| | 02:16 | returning back to the readyHandler, once
you have loaded the component instance
| | 02:20 | into memory and you get the ready event,
you can now listen for the custom
| | 02:24 | events of the component instance.
| | 02:26 | The Form component instance is going to
dispatch an event named submit. So we
| | 02:30 | are going to listen for that event, only
if we have actually loaded a form. You
| | 02:34 | can reference the component instance using
the child property of the module
| | 02:38 | loader. So first add this conditional code,
if loader.child is FormModule, if
| | 02:46 | this condition is true then that means that
this ready event happened because
| | 02:50 | we loaded the form module component and
now you are ready to add an event
| | 02:54 | listener for the custom event of the module.
Place the cursor after this
| | 03:00 | function and create another new function,
this one called submitHandler. The
| | 03:05 | event argument for this submitHandler function
will be an instance of the Chart
| | 03:10 | event class, that's the custom class that's
constructed and dispatched by the
| | 03:14 | form module component. As with all other
eventHandler functions, it returns void.
| | 03:19 | Now we have the eventHandler function and
we can add an event listener for it.
| | 03:23 | I will go back to the readyHandler function,
place the cursor inside the
| | 03:27 | conditional block and I will add the event
listener using the following code
| | 03:31 | loader.child.addeventListener and because
we are listening for a custom event
| | 03:37 | name, I'll type it in as a literal string,
the name of the event will be Submit
| | 03:42 | and then I will pass in the submitHandler
function as an object to indicate
| | 03:46 | that that's the callback method for this
event. Next I'll place a break point
| | 03:51 | on the last line of the submitHandler
function, that's the line with the
| | 03:54 | closing brace, I'll save the application
and I will run it in Debug mode.
| | 04:00 | Now I will load the form and when I load
the form, the readyEvent is triggered
| | 04:04 | causing the event listener to be added.
I'll type some numeric values in of
| | 04:09 | 2000, 3000 and 4000 for my chartData. I'll
click the Submit button and that
| | 04:17 | will cause me to hit the break point. I
will click yes to open the Debugging
| | 04:21 | perspective, go to the variables view and
take a look at the event object which
| | 04:27 | contains the data that I submitted
into the form.
| | 04:30 | The data comes back as an ArrayCollection.
So now to save this data
| | 04:34 | persistently and make it available for all
components in the application, I am
| | 04:38 | going to follow the pattern that I followed
in the past, when working with
| | 04:42 | individual components. I will come back
to Flex Builder and terminate the
| | 04:46 | Debugging session and go back to the code.
At the top of the source code, I am
| | 04:52 | going to declare a new Bindable variable
named chartData, data typed as an
| | 04:58 | ArrayCollection. Then I'll go back down to
the submitHandler function and then
| | 05:03 | I'll get the data out of the event object
by referring to it's data property
| | 05:07 | which hold the ArrayCollection that was
shared by the FormModule component.
| | 05:14 | This data object is already data typed as
an ArrayCollection so I don't have to
| | 05:18 | explicitly cast it and now when the user
submits the form, the data will have
| | 05:22 | been shared with the rest of the application.
| | 05:25 | I'll once again run the application in Debug
mode, I will load the form, type
| | 05:33 | in some values, click the Submit button,
come on back to Flex Builder, go in to
| | 05:41 | the Debugging perspective and look at the
variables view. And I will see that
| | 05:46 | once again the data is available in the event
object. But now I will go over to
| | 05:50 | the expressions view and I will add a new
watch expression for chartData, click
| | 05:56 | OK and you should see that the chartData
variable contains the same data that
| | 06:01 | was just shared from the data entry form.
| | 06:04 | It's now stored in a persistent variable
at the application level, in a place
| | 06:08 | where it can then be passed to other components.
And in the next video, I'll
| | 06:12 | show you how to take that data that is stored
at the application level and pass
| | 06:16 | it to a component instance that's
loaded as a module.
| | Collapse this transcript |
| Passing data to a module| 00:00 | In this video, I am going to describe how
to pass data to a module component
| | 00:04 | after it's been loaded into a module loader.
For this demonstration, I will be
| | 00:08 | using two files, PassData.mxml and ChartModule.mxml.
ChartModule.mxml was
| | 00:15 | created in an earlier video in this chapter
and PassData.mxml is an application
| | 00:20 | that includes the same functionality as
the one I created in the previous videos.
| | 00:24 | As the application starts up, no modules
are displayed initially. When the user
| | 00:29 | clicks either of the modules, such as the
Load Chart module or the Load Form,
| | 00:33 | we see those modules. And in this version
of the application when the user
| | 00:37 | types values in to the data entry form and
then clicks submit, that causes that
| | 00:42 | data to be wrapped into a custom event object
and dispatch it to the rest of
| | 00:46 | the application. In this video, I am going
to show you how to take that data
| | 00:50 | after it's been saved to a persistent variable
at the application level and
| | 00:54 | explicitly pass it to the new component
that's just about to be loaded.
| | 00:58 | I will close the browser and go back
to the application. When the form
| | 01:03 | component dispatches its data through an
event object, that data is being saved
| | 01:08 | into this chartData ArrayCollection.
Now I am going to add code to the
| | 01:12 | readyHandler function. Whenever a module
is loaded into memory, the
| | 01:17 | readyHandler function is being called because
of the ready event listener on
| | 01:21 | the module loader component declaration here.
| | 01:24 | We already have a conditional block for
the form module and now I am going to
| | 01:28 | add another one for the chart module as
follows; else if (loader.child is
| | 01:35 | ChartModule). In this section of the conditional
block, I am going to be taking
| | 01:42 | the data from the form and passing it to
the chart, so I also need to check
| | 01:46 | whether the chartData variable is null. If
the user has submitted data from the
| | 01:51 | form module, then that data won't be null.
So I will add a Boolean ampersand,
| | 01:56 | ampersand as a Boolean And, and then I will
examine the chartData variable and
| | 02:00 | check to see whether it's null. So that's
my complete conditional block.
| | 02:06 | If loader.child is ChartModule and the chartData
variable isn't null, now I am
| | 02:12 | ready to pass data to the ChartModule object.
The next step is to get a handle
| | 02:17 | to the module object that was just loaded
into memory. I will use this syntax,
| | 02:22 | Var chart, data typed as ChartModule
= Loader.child as ChartModule.
| | 02:34 | The next step is to pass data to the ChartModule,
right now though the variable
| | 02:39 | being used within the ChartModule to manage
the data for the chart component is
| | 02:43 | private. I have to fix that, before I can
continue with this code. So now I
| | 02:48 | will go over to ChartModule.mxml and I will
change the access modifier for the
| | 02:53 | acExpenses Array Collection within the module
from private to public. I will
| | 02:58 | save that change and come back to the application.
And then I will add a line
| | 03:03 | of code to set that data as follows -- chart.acExpenses
= chartData. So now as
| | 03:13 | the chart module loads, we check to see whether
that data is null, and if it's
| | 03:17 | not, we pass it in.
| | 03:18 | Now the final step in this process is to
cause the chart to load when the form
| | 03:23 | has been submitted. Go back down to the
submitHandler function. This is where
| | 03:27 | we are currently capturing the data from
the data entry form module. Place the
| | 03:32 | cursor after the existing line of code that's
capturing and saving the data and
| | 03:36 | then call the existing function load
ChartModule. This will cause the
| | 03:40 | ChartModule to be reloaded after the data
has been saved to the persistent
| | 03:45 | Array Collection at the application level.
Save your changes and give it a try.
| | 03:50 | Run the application. Click the Load Chart
button and you will see that it loads
| | 03:55 | with its default data. Now go to the form
and fill in some numeric values, I
| | 04:01 | will enter values of 111, 222 and 333. Click
the Submit button and you should
| | 04:09 | see that the chart is reloaded this time
displaying the data from the data entry form.
| | 04:14 | So this is one mechanism for sharing data
between modules at runtime, because
| | 04:19 | module component instances don't stick
around in memory, that is, once the
| | 04:23 | module loader opens another module, it has
to discard the reference to the old
| | 04:27 | one. You have to have a way to save the data
persistently between module loads.
| | 04:32 | In this example, I am using a custom event
dispatched from the form module and
| | 04:37 | a public property in the display
or the ChartModule.
| | Collapse this transcript |
|
|
13. Localizing Flex ApplicationsCreating resource bundles in ActionScript| 00:00 | In this chapter of the video series, I am
going to describe how to use Resource
| | 00:04 | Bundles to localize Flex applications, that
is, how to create sets of phrases,
| | 00:09 | that you can then bind to a runtime and make
your application easy to read and
| | 00:14 | friendly to different international locations.
| | 00:17 | Internationalization and locale management
are built into the Flex framework.
| | 00:21 | There are two primary approaches that you
can use for creating what are known
| | 00:24 | as Resource Bundles for different locales.
In one approach, you create a set of
| | 00:29 | compiled files and these Resource Bundles
can either be compiled into the
| | 00:33 | application or loaded at runtime.
| | 00:35 | Creating compiled Resource Bundles is beyond
the scope of this chapter. I am
| | 00:39 | instead going to be focusing on how to
create Resource Bundles and use them
| | 00:43 | completely with the ActionScript programming
language; this is something you
| | 00:47 | can do completely in code without having
to go out to the Command-Line
| | 00:50 | Compiler, which you do have to use to
create the compiled versions of the
| | 00:54 | Resource Bundles.
| | 00:55 | For the demonstrations in this chapter,
I will use a Flex project from the
| | 00:58 | Exercises folder. If you have access to
the Exercises and you are following
| | 01:02 | along, you can import this project now.
From the Flex Builder menu, select
| | 01:07 | File, Import, Flex Project, click the
Browse button next to Archive file,
| | 01:13 | navigate to your Exercises folder which I
have installed on my desktop, then go
| | 01:17 | to the Chapter13 folder and from there
select and import the file
| | 01:21 | Chapter13BeginProject.zip. Then go to the
Flex navigator view, open the source
| | 01:26 | folder of the project and then open the
application, UseResourceBundle.mxml.
| | 01:32 | This application currently has label in two
buttons. The label has a text value
| | 01:37 | of Localizing Flex Applications and a font
weight of bold and the buttons have
| | 01:41 | labels but aren't doing anything yet. In
order to localize an application using
| | 01:45 | ActionScript, the first step is to create
an object named ResorceBundle, you
| | 01:50 | create one instance of the ResourceBundle
class for each locale that you want
| | 01:54 | to support. For Example, in this application
I am going to show you how to
| | 01:57 | switch back and forth between showing
English and French phrases in an application.
| | 02:02 | So I would need two ResourceBundles, one's
for each language. Initially I am
| | 02:06 | going to put the code for creating the ResourceBundles
in the init function.
| | 02:10 | That's being called upon application startup
but then I am going to move that
| | 02:14 | code out to a separate ActionScript class.
If you are following along, place
| | 02:18 | the cursor inside the init function, declare
a variable named myResources, data
| | 02:23 | typed as the ResourceBundle Class.
| | 02:26 | When you select this class from the list
of available classes, Flex Builder
| | 02:29 | adds an import statement for it. Finish
the declaration and then go down a
| | 02:34 | couple of lines. Now we are going to create
a ResourceBundle for US English.
| | 02:38 | The Code looks like this, myResources=new
ResourceBundle and I am calling the
| | 02:45 | ResourceBundle classes constructor method
here. And now I pass in a locale identifier.
| | 02:50 | Locale identifiers are typically made up
of two alpha strings separated by an
| | 02:55 | underscore. The first two character string
is the language and the second two
| | 02:59 | character string is the country. For example,
for English in the United States,
| | 03:04 | the correct locale identifier is en_US as
a string. Also add a name for your
| | 03:13 | ResourceBundle which we will call myResources.
The bundle name and the variable
| | 03:19 | identifier are two different things.
| | 03:21 | The variable name is used to refer to
the ResourceBundle, while you are
| | 03:25 | manipulating it in a code. The Bundle
string which you pass into the
| | 03:28 | constructor will be used to identify the
ResourceBundle when you want to use
| | 03:32 | phrases from the bundle in your application.
The next step is to add phrases.
| | 03:37 | Each phrase is added as a named Object
in the ResourceBundle's content
| | 03:41 | property. In order to properly control each
key that refers to a phrase, you
| | 03:46 | use bracket style syntax to refer to
the property name as follows,
| | 03:51 | Resources.content, and then I will use
a bracket and then the key for this
| | 03:56 | phrase, which I will set as the word Open
and then after an Equal As assignment
| | 04:01 | operator, the string that you want to use
for this key, when you are in the
| | 04:05 | en_US locale. And I will put
in the English word Open.
| | 04:09 | Now for each phrase that you want to localize,
you will add a new item to the
| | 04:12 | content Object, so I will add one more. I
will set another item in the content
| | 04:19 | Object, this time with a key of close.
You will continue on this phrase for
| | 04:23 | each phrase that you need to localize.
Now the next step is to add the new
| | 04:27 | ResourceBundle to what's called the resourceManager.
resourceManager is a
| | 04:32 | property of the application component.
It has a method called Add
| | 04:36 | ResourceBundle, so after you have constructed
the ResourceBundle in
| | 04:39 | ActionScript code, you call this method
and pass the ResourceBundle in as
| | 04:43 | follows, resourceManager.addResourceBundle
and then pass in your new
| | 04:49 | ResourceBundle which I have named myResources.
| | 04:52 | You will then repeat this for as many locales
as you want to support. I am
| | 04:57 | going to select this code, copy it and then
paste it and now I will be able to
| | 05:03 | create a second ResourceBundle for another
language. This one will be for
| | 05:07 | French which is the language French, fr_
in the country France, FR. Now I will
| | 05:17 | change the strings that will be used when
I am using that locale. The French
| | 05:21 | word for Open is Ouvrez and the French
word for close is Fermez.
| | 05:30 | So my application is now enabled with two
completely separate ResourceBundles,
| | 05:34 | the final step is to update your resources.
You do this by calling a method of
| | 05:39 | the resourceManager Object named Update.
I will move the cursor below all the
| | 05:44 | ResourceBundles creation and I will call
resourceManager.update and that causes
| | 05:51 | these resources to become immediately available
to the application. So that's
| | 05:55 | how we create the resources. In the next
video, I will show you how to create
| | 05:59 | labels that get their text values by
binding to these items in the
| | 06:04 | ResourceBundles.
| | Collapse this transcript |
| Using ResourceBundle binding expressions| 00:01 | In this video, I am going to describe how
to use resource bindings to use the
| | 00:05 | resources in the resource bundles that you
have created. The resourceManager
| | 00:08 | object or class has methods to retrieve strings,
numbers and other data types.
| | 00:13 | When you call the method you pass in two
values, the name of the bundle that
| | 00:17 | contains the resource you want and the key
for the resource. This results in
| | 00:22 | outputing the associated string or other
value that goes with that resource. I
| | 00:27 | am going to continue working in the application,
UseResourceBundle.mxml. And I
| | 00:31 | will go down to the bottom of the application
to where the visual controls are
| | 00:35 | and I will place the cursor after the
label with the text Localizing Flex
| | 00:39 | Applications. I will create a label control
and I will set it's text property
| | 00:44 | using a binding expression as follows.
| | 00:46 | I am once again going to refer to the
resourceManager object, which is a
| | 00:50 | singleton property of the application.
I will use this syntax,
| | 00:55 | resourceManager.getString and then I will
pass in the name of the bundle that
| | 01:01 | contains my resources, myResources and then
the key that's associated with the
| | 01:06 | string I want to output. I will refactor
the code a bit so we can see it all on
| | 01:15 | the screen at the same time. So I am calling
the getString method, passing in
| | 01:19 | the name of the bundle and the
name of the resource key.
| | 01:22 | Now this application starts up by default
with the English United States
| | 01:27 | locale. The reason this happens is because
when you create a brand new Flex
| | 01:32 | project using Flex Builder, the version
that's released in the United States,
| | 01:35 | the locale is automatically set in the compiler
arguments for the project. Flex
| | 01:41 | builder 3 is delivered with 2 pre-built
locales. One for English and one for
| | 01:45 | Japanese. The Localized versions of Flex
Builder of course come with locales
| | 01:49 | for French or German or whatever other locale
the product has been localized for.
| | 01:54 | But the version that's released in the United
States only has this one English
| | 01:58 | language locale, so that's the only one
that you can put in the compiler
| | 02:01 | arguments. I will show you in a later
video, how to switch to a different
| | 02:05 | locale at runtime though.
| | 02:07 | So now that we understand that we are working
with the en_US locale and that we
| | 02:13 | have added these resources to the locale
in the myResources bundle, we can now
| | 02:18 | run the application and you should see
that the label displays the string
| | 02:22 | associated with the key open. I will close
the browser and return to Flex
| | 02:27 | Builder and then clone the label and I
will change the key for the second
| | 02:32 | resource to the word close. I will save the
changes and run the application and
| | 02:38 | once again you can see that the associated
string is displayed.
| | 02:42 | Right now I am creating all of my resources
in the application's init function,
| | 02:47 | it will be nice to take all of these code
and put it in a separate ActionScript
| | 02:51 | class. I have prepared a class named ResourceUtility,
that's in the utilities
| | 02:56 | folder of the source root. Open that ActionScript
class now. Notice that this
| | 03:02 | class has a static function named setResources
that receives a single argument
| | 03:06 | named resourceManager, datatyped as an
interface named iresourceManager. At
| | 03:13 | application startup, I am going to call
this function and pass in a reference
| | 03:17 | to the application's resourceManager object.
I am going to move the code from
| | 03:21 | the application level into the
static function first.
| | 03:24 | I will go back to the application, and
I will select all of the code in the
| | 03:29 | init method and I will cut it to the clipboard.
I will then go back to the
| | 03:33 | ResourceUtility class and then I am
going to paste that code into the
| | 03:38 | setResources static function and I will
un-indent it a little bit so it looks
| | 03:43 | right in the context of that code.
| | 03:46 | Now I will save the changes to that code
and you will see that there are some
| | 03:49 | compiler errors that are generated because
I need an Import statement for this
| | 03:53 | ResourceBundle class. I will place the cursor
after the class name and press
| | 03:57 | Ctrl+Space and Flex Builder adds the required
Import statement. I will save the
| | 04:02 | changes again and the errors go away.
| | 04:06 | Now we will go back to the application, UseResourceBundle.mxml.
Within the init
| | 04:12 | function, I will call the ResourceUtility
class's setResources method and pass
| | 04:18 | in the application's resourceManager Object.
| | 04:21 | Now, if the application starts up, I am once
again executing all of the code to
| | 04:26 | create my resources in ActionScript. It's
all now encapsulated though in the
| | 04:31 | static function and as the functionality
of my application grows and I have to
| | 04:36 | add new phrases, I have one place to go and
do the work, the static function of
| | 04:41 | this class. I will go back to the application
save the changes and run the
| | 04:46 | application one more time and you will
see that once again the strings are
| | 04:50 | being correctly displayed.
| | 04:52 | Now in the next video, I will show you how
to switch from one locale to another
| | 04:55 | at runtime, so you can switch from one
complete language to another.
| | Collapse this transcript |
| Setting locales at runtime| 00:01 | In this video, I am going to describe how
to change from one locale to another
| | 00:04 | at runtime, so that you can display the
values or resources in a resource
| | 00:09 | bundle that are associated with the new locale.
| | 00:12 | In order to change locales, you set a property
of the resourceManager object
| | 00:16 | named localeChain to an array of locales.
You put the locales in, in the order
| | 00:22 | of preference. Then for each resource
that you bind to using the resource
| | 00:26 | manager's method such as getString, the
resource manager will go through the
| | 00:30 | locales one at a time and as soon as it finds
the key that you have requested,
| | 00:35 | it will return the value that's associated
with it. This allows you to combine
| | 00:39 | resources where in some cases, the resource
maybe translated in every language
| | 00:44 | and in other cases the resource may only
occur in one language. And it allows
| | 00:49 | you to add your locales in the desired order.
| | 00:52 | For this demonstration, I will use an application
named SwitchLocales.mxml.
| | 00:58 | This application is in the same state
as the previous video. It sets up
| | 01:02 | resources using the resource utility class's
setResources static function.
| | 01:07 | There are two resource bundles, one for
English and one for French. The
| | 01:11 | application in it's default state is using
the English locale because of the
| | 01:15 | compiler arguments that I showed in an earlier
video. For this demonstration,
| | 01:21 | add a new function to the application.
Name the function changeLocale and
| | 01:28 | design it to receive a single argument named
locale, datatyped as a string. And
| | 01:35 | the function will return void.
| | 01:37 | Now within the function set the localeChain
property of the resource manager as
| | 01:41 | follows, resourceManager.localeChain = and
then a pair of brackets indicating
| | 01:48 | that we are creating an array and then pass
the locale argument into the array.
| | 01:53 | So now we have a single function that we
can call and we can pass the locale
| | 01:57 | into the function and that locale will be
triggered instantly. Now go down to
| | 02:01 | the bottom of the application, there are
two buttons labeled English and
| | 02:04 | French. Add a click event listener to
the first button and call the new
| | 02:10 | changeLocale function and pass in a string
of en_US. Add a click handler also
| | 02:19 | for the button with a label of French,
and once again call the changeLocale
| | 02:23 | function and pass in the appropriate locale
id fr_FR, save your changes and run
| | 02:31 | the application.
| | 02:32 | Once again as the application opens, it shows
the English phrases, but now you
| | 02:38 | can click the French button and the values
change instantly and you can click
| | 02:42 | the English button to go back to the original
phrases. Resource bundles work
| | 02:46 | throughout the entire application including
in any component instances that are
| | 02:51 | a part of the application.
| | 02:53 | To demonstrate this, I am going to make
a copy of the code for these two
| | 02:56 | labels. I will select the lines of code that
declare the label objects and copy
| | 03:01 | them to the clipboard. Now I will go to
the components folder of the project
| | 03:06 | where there is a MyComponent.mxml component.
This is a simple component that
| | 03:10 | just contains a Vbox. I will paste in
the labels and then so I can really
| | 03:17 | clearly see where the component is, I am
going to add a background color style
| | 03:21 | of yellow. I will save the changes to the
component and I will return back to
| | 03:26 | the application SwitchLocales.mxml. Now
I will place the cursor after the
| | 03:31 | buttons and using MXML I will declare
an instance of the component, my
| | 03:36 | component. I will save the changes
and run the application.
| | 03:41 | So, you will see in the application that
the locale strings are working both at
| | 03:46 | the application level and in the nested
component level and when you change
| | 03:51 | locales by changing the localeChain property
of this singleton resource
| | 03:55 | manager, the new values will appear right
away regardless of where they are
| | 03:59 | used in the application. I will click the
French button and you will see it
| | 04:02 | changes both in the application and in the
component and then I will go back to
| | 04:06 | English. So this is a very simple way
of implementing a localization
| | 04:11 | architecture in your application.
| | 04:14 | Again, it's not the only approach, you can
also use compiled resource bundles
| | 04:19 | and as an application becomes larger and
more complex, it's worth checking out
| | 04:23 | the compiled resource bundle architecture
and create complete resource bundles
| | 04:27 | for each of the locales that
you have to support.
| | Collapse this transcript |
|
|
ConclusionGoodbye| 00:01 | Hi, David Gassner here again. Thanks
for sitting with me through this video
| | 00:04 | series on building and deploying applications
with Flex Builder 3 and the Flex 3 framework.
| | 00:10 | In this series I showed how you can
extend your Flex application development
| | 00:14 | skills and use more of the great tools
that this development platform offers.
| | 00:18 | If Flex development appeals to you, checkout
my other titles on lynda.com that
| | 00:23 | describe how to use Flex Builder to create
desktop applications that run on
| | 00:27 | multiple operating systems including
Windows and Mac using AIR, the Adobe
| | 00:31 | Integrated Runtime and in the mean
time, happy programming with Flex.
| | Collapse this transcript |
|
|