Skip to content

A Flex 3 custom events primer

Dear Reader,

I am a web developer. It’s been over 10 years since I’ve done serious desktop application development. So when I fire up Flex Builder to write my first AIR application, it takes a while for things to start coming back to me. One of the things that is only now starting to come back is Event Driven Programming.

This past week I decided to start working on a small project to scratch a personal itch. The project itself fizzled but I learned something none-the-less. I learned how to create custom events in Flex 3.

The project required selecting a file for processing. Flex 3 has a control for actually opening the dialog box and selecting the file but no control that shows the button and the selected file name.


Since I plan on working with Flex a lot, I decided to start my own library of controls and build my own. The first thing I learned is that to be included in a package, you have to use code, not visual classes. Here’s the code for my FilePicker control.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
package com.calevans.controls
{
	import com.calevans.Events.FileSelected;
 
	import flash.events.Event;
	import flash.filesystem.*;
 
	import mx.binding.utils.BindingUtils;
	import mx.containers.HBox;
	import mx.controls.Button;
	import mx.controls.Spacer;
	import mx.controls.TextInput;            
 
	[Event(name="fileSelected", type="com.calevans.Events.FileSelected")]
	public class FilePicker extends HBox
	{
		[Bindable] public var buttonLabel:String = "Select File";
 
		protected var selectedFile:File;
		protected var btnMain:Button;
		protected var tiFileName:TextInput;
 
		private var defaultDirectory:File; // The default directory
 
		public function FilePicker()
		{
			defaultDirectory = File.documentsDirectory;
			this.addChild(new Spacer());
			/*
			 * Select file Button
			 */
			btnMain = new Button();
			btnMain.addEventListener('click', openFile);
			BindingUtils.bindProperty(btnMain,"label",this,"buttonLabel");
			this.addChild(btnMain);
 
			/*
			 * textInput to display the file name
			 */
			tiFileName = new TextInput();
			tiFileName.percentWidth=100;
			tiFileName.editable=false;
			this.addChild(tiFileName);
 
			this.addChild(new Spacer());
			return;					
		}
 
 
		private function openFile(event:Event):void 
		{	
			var fileChooser:File;
			fileChooser = defaultDirectory;
			fileChooser.browseForOpen("Open");
			fileChooser.addEventListener(Event.SELECT, fileOpenSelected);
			return;
		}
 
		private function fileOpenSelected(event:Event):void 
		{
			selectedFile = event.target as File;
			selectedFile.removeEventListener(Event.SELECT, fileOpenSelected);
			tiFileName.text = selectedFile.nativePath;
			dispatchEvent(new FileSelected(FileSelected.FILE_SELECTED,false,false,selectedFile)); 
			return;
		}
 
 
	}
}

As you can see, there’s not a lot of ground breaking code here. Most of this is standard Actionscript code. However, once I got it written and working, I realized that to be useful in an application, something needed to happen in the main application after I selected the file. I knew what I needed, I need for the control to allow me to define an event and assign it code to execute.

Looking through the docs was informative but confusing. Most of the examples I could find on the web were contrived and not really helpful. I finally pieced together almost all of the piece. With the help of my friend Marco Tabini I got it working. Here’s what I did.

The first thing you have to do is define an Event class. Here is mine.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
package com.calevans.Events
{
    import flash.events.Event;
    import flash.filesystem.File;
 
    public class FileSelected extends Event
	{
		public static const FILE_SELECTED:String = 'fileSelected';
		private var _selectedFile:File;
 
	   // Public constructor.
		public function FileSelected(type:String, bubbles:Boolean, cancelable:Boolean, selectedFile:File=null) 
		{
			super(type,bubbles,cancelable);
			_selectedFile = selectedFile;
			return;
		}
 
		public function get selectedFile():File{
			return _selectedFile;
		}
 
		override public function clone():Event 
		{
            return new FileSelected(type, bubbles, cancelable, _selectedFile);
        }
 
	}
}

I am still new at Flex so I’m not going to pretend to tell you what each of these pieces mean. My hope is to tell you what you need to get it working.

  1. The constructor, you can pass your own parameters in but you have to pass in the first three. Inside the constructor, call the super passing the three default parameters
  2. You have to override the clone function. I don’t know why but every tutorial out there said you had to. Make sure you pass the standard parameters plus any custom parameters you defined. The signature has to match the constructor.
  3. The public static constant is important as it define the name (or names) of the events you can dispatch with this class.

Now to use it.

1
<controls :filepicker="" buttonlabel="Select File" width="90%" fileselected="doMe(event);"></controls>

The thing I missed in all the tutorials was this.

1
2
3
public static const FILE_SELECTED:String = 'fileSelected';
[Event(name="fileSelected", type="com.calevans.Events.FileSelected")]
<controls :filepicker="" buttonlabel="Select File" width="90%" fileselected="doMe(event);"></controls>

In all three of these lines above, the word “fileSelected” has to match. The first one is the constant in the Event class, you have to define this. The second one is where you tell Flex that this control will dispatch a custom event, the name of it has to be the same as one of the constants in the class. You can define multiple constants in the same class to allow the class to be used multiple times.

The third one is the MXML definition of the use of the class. If you’ve done everything right, Flex Builder will know that your control has a custom event fileSelected and show it in the list of properties, methods and events.

The final piece that I missed was actually dispatching the event. I’m not sure what I was thinking but I got everything working and it still wasn’t dispatching the event and calling my function. The simple piece I missed was that I had to tell my code when to dispatch the event.

dispatchEvent(new FileSelected(FileSelected.FILE_SELECTED,false,false,selectedFile));

Adding that to FilePicker.as in the fileOpenSelected method solved the problem.

Side Note: As far as I can tell, this particular control will only work in AIR apps as Flash doesn’t have direct access to the file system. (I could be wrong on that though, please feel free to correct me)

This is a very simple example of a custom event but it’s a working one and not a contrived example. If you are struggling with them, put this code in your test application and play with it. Break it and fix it and see what is possible. While I’m sad that I couldn’t actually build the tool I wanted to build, it’s always nice to take something away from every project.

Until next time,
I <3 |<
=C=

[DISCLAIMER: I work with Blue Parabola, Adobe is a customer of Blue Parabola. ]

2 thoughts on “A Flex 3 custom events primer

  1. Most of the time the clone method won’t factor in but here’s an explanation for you.

    http://life.neophi.com/danielr/2006/06/events_in_flex_2.html

    When you re-dispatch an event the clone method is used to create a “copy” of the event so you if you don’t have one defined you can run into trouble. It’s a good habit to develop just for this case which might not happen most of the time but could once you make a change in how the event is used later on.

Comments are closed.