Follow Flex After Dark on Twitter

Flex Drag-and-Drop: The Definitive Tutorial

Drag-and-drop lets you move components and transfer data in a Flex application via the mouse and ubiquitous "click-drag-drop" paradigm. All Flex components support drag-and-drop operations with the proper enablement.

We're going to follow these steps to learn about Drag-and-Drop in Flex:

  1. Create a Project and Application
  2. Create some Boxes (one for dragging, one for dropping)
  3. Make the Red Box Draggable
  4. Make the Blue Box a Drop Target
  5. Handle the Drop
  6. Show Feedback
  7. Use Drag Source

Step 1: Create a Project and Application

Create a Flex Project: FlexTutorials

First we'll want to create a Flex Project to hold this, and potentially other, tutorial applications. If you've already completed another Flex After Dark Tutorial, you can use the same project, or a different one.

To create a new Flex project using Flex/Flash Builder:

  1. Select File > New Flex Project
  2. Give your project a name (i.e. FlexTutorials)
I've created a Flex Project for holding my tutorial application.

When you create a Flex project using Flex/Flash Builder it will automatically create an application with the same name as the project. However, we are not going to use that application in this tutorial. In the next step we'll create another application specifically for this Drag-and-Drop tutorial.

Create a Flex Application: DragDrop.mxml

Next we'll create a new MXML Application called "DragDrop" (or anything you want really). This MXML file will hold all of our code for this tutorial.

To create a new Flex project using Flex/Flash Builder:

  1. Select File > New MXML Application
  2. Give your application a filename (i.e. DragDrop)

The fresh application will look something like the following code.

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute">
   
</mx:Application>

Let's update the application code a little:

  1. Change the layout attribute to be "vertical"
  2. Add a name attribute with a value of "Drag and Drop Tutorial"
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical" 
   name="Drag and Drop Tutorial">
   
</mx:Application>
I've created a Flex Application for holding my Drag-and-Drop tutorial code.

Add an init() function

Next we're going to finish our application setup by adding a <mx:Script> block and init() function. The <mx:Script> block will hold our application's ActionScript and the init() function will be called when our application starts.

Add the <mx:Script> and init() function:

  1. Add a <mx:Script> block to your application
  2. Add an init() function (empty for now)
  3. Call the init() function on creationComplete
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical" 
   name="Drag and Drop Tutorial"
   creationComplete="init()">
   
   <mx:Script>
      <![CDATA[
         
         public function init():void
         {
            
         }
         
      ]]>
   </mx:Script>
   
</mx:Application>

We're going to use the <mx:Script> block in a future step to setup listeners.

I've added an init() function to my application's <mx:Script>.

Step 2: Create some Boxes

Create a Red Box and a Blue Box

Next were going to use MXML to create a Red Box and a Blue Box for our application. We'll add the following code inside our <mx:Application> tag in application's MXML file.

   <mx:HBox horizontalGap="100">
      <mx:Canvas id="redBox" width="100" height="100" backgroundColor="Red" />
      <mx:Canvas id="blueBox" width="100" height="100" backgroundColor="Blue" />
   </mx:HBox>

We can now launch our application for the first time and see the results.

To launch your DragDrop application using Flex/Flash Builder:

  1. Select Run > Run DragDrop from the main application menu

The result should look like this, with a Red Box and Blue Box.

The result should look like this, with a Red Box and Blue Box.

We'll start the fun drag-and-drop stuff in the next step.

I've created two boxes, one red and one blue, in MXML.

Step 3: Make the Red Box Draggable

Initiation of a drag-and-drop operation occurs when a "drag-enabled" component is selected with the mouse and moved while holding down the mouse button. The component selected and dragged is called the drag initiator.

Red Box listens for Mouse Event

To kick off a drag-n-drop, we'll need to listen for a "mouse down" MouseEvent for the component to be dragged.

  1. Add listener for MouseEvent.MOUSE_DOWN to the init() function
  2. Determine drag initiator and call DragManager's beginDrag() function
   public function init():void
   {
      // a mouseDown event will start the drag
      this.redBox.addEventListener( MouseEvent.MOUSE_DOWN, beginDrag );
   }
   
   public function beginDrag( mouseEvent:MouseEvent ):void
   {
      ...
   }

We'll cover the beginDrag() method in the next step...

I've made the Red Box draggable by adding a "mouse down" listener.

Start the Drag using DragManager

Dragging occurs when the user, still holding down the mouse button, moves the drag initiator component around the application.

The mx.managers.DragManager class is used for managing drag-and-drop operations for Flex applications. All its methods and properties are static, so you do not need to create an instance of it.

Here we'll fill in our beginDrag() function that handles our "mouse down" event.

   import mx.core.DragSource;
   import mx.core.IUIComponent;
   import mx.managers.DragManager;
   
   ...
   
   public function beginDrag( mouseEvent:MouseEvent ):void
   {
      // the drag initiator is the object being dragged (target of the mouse event)
      var dragInitiator:IUIComponent = mouseEvent.currentTarget as IUIComponent;
      
      // the drag source contains data about what's being dragged
      var dragSource:DragSource = new DragSource();
      
      // ask the DragManger to begin the drag
      DragManager.doDrag( dragInitiator, dragSource, mouseEvent, null );
   }

The above code accomplishes the following:

  1. We use the mouse event's currentTarget (the Red Box) as the drag initiator
  2. We create a drag source object (we'll come back to this later in the tutorial)
  3. We call the DragManager.doDrag() function to begin the drag operation

The Red Box is now draggable (though you can't yet drop it anywhere).

The Red Box is now draggable (though you can't yet drop it anywhere).
I've drag-enabled the Red Box by passing it as a drag initiator to the DragManager.

Note the new imports we used in the above code:

  • import mx.core.DragSource;
  • import mx.core.IUIComponent;
  • import mx.managers.DragManager;

Step 4: Make the Blue Box a Drop Target

Our next step is to make the Blue Box a drop target capable of accepting a drop. To do this we must first add an event listener for the DragEvent.DRAG_ENTER event to our Blue Box.

The DragEvent.DRAG_ENTER event occurs when a drag initiator is dragged over another component during a drag-drop operation.

   import mx.events.DragEvent;
   
   ...
   
   public function init():void
   {
      // a mouseDown event will start the drag
      this.redBox.addEventListener( MouseEvent.MOUSE_DOWN, beginDrag );
      
      // accepting a drag/drop operation...
      this.blueBox.addEventListener( DragEvent.DRAG_ENTER, acceptDrop );
   }
   
   public function acceptDrop( dragEvent:DragEvent ):void
   {
      ...
   }

We'll code out the acceptDrop function next to actually accept the drop.

I've drop-enabled the Blue Box by adding a "drag enter" event listener.

Note the new import we used in the above code:

  • import mx.events.DragEvent;

Accept the Drop using DragManager

To accept the drop we must notify the DragManager with a drop target (the Blue Box) in response to the DragEvent.DRAG_ENTER event.

   public function acceptDrop( dragEvent:DragEvent ):void
   {
      var dropTarget:IUIComponent = dragEvent.currentTarget as IUIComponent;
      
      // accept the drop
      DragManager.acceptDragDrop( dropTarget );
   }

Now that we have accepted the drop we can let go of the Red Box on the Blue Box. Nothing exciting happens when we drop, yet, that'll be in our next step when we handle the drop.

The Red Box can be dragged to and dropped on the Blue Box.

The Red Box can be dragged to and dropped on the Blue Box.
I've drop-enabled the Blue Box by passing it as a //drop target// to the DragManager.

Step 5: Handle the Drop

Handling the drop is the magic step of a drag-drop operation where your application performs the "business logic" of dragging an initiator to a target.

We are notified of a drop by adding a DragEvent.DRAG_DROP event listener on a drop target.

   public function init():void
   {
      // a mouseDown event will start the drag
      this.redBox.addEventListener( MouseEvent.MOUSE_DOWN, beginDrag );
      
      // accepting a drag/drop operation...
      this.blueBox.addEventListener( DragEvent.DRAG_ENTER, acceptDrop );
      
      // handling the drop...
      this.blueBox.addEventListener( DragEvent.DRAG_DROP, handleDrop );
   }
   
   public function handleDrop( dragEvent:DragEvent ):void
   {
      var dragInitiator:IUIComponent = dragEvent.dragInitiator;
      var dropTarget:IUIComponent = dragEvent.currentTarget as IUIComponent;
      
      Alert.show( "You dropped the Red Box on the Blue Box!" );
   }

When the listener function of a DragEvent.DRAG_DROP event is called we can get the drag initiator and drop target from the event as seen in the code above.

Our example for this tutorial simply shows an Alert message when a drop is completed.

When the Red Box is dropped on the Blue Box we get alerted.

When the Red Box is dropped on the Blue Box we get alerted.
I've handled the drop by adding a "drag drop" event listener to the Blue Box.

Note the new import we used in the above code:

  • import mx.controls.Alert;

Step 6: Show Feedback

The DragManager provides a static showFeedback() function that can be used to display what type of drop operation will be performed. The feedback is shown as a small icon next the cursor when the drag initiator is over an accepting drop target.

DragManager feedback types:

  • COPY - signifies that the drop will copy some data
  • LINK - signifies that the drop will link some data
  • MOVE - signifies that the drop will move some data
  • NONE - no feedback (default)
   public function acceptDrop( dragEvent:DragEvent ):void
   {
      var dropTarget:IUIComponent = dragEvent.currentTarget as IUIComponent;
      
      // accept the drop
      DragManager.acceptDragDrop( dropTarget );
      
      // show feedback
      DragManager.showFeedback( DragManager.COPY );
   }

The last line of code above shows how we call DragManager.showFeedback() passing the DragManager.COPY value. Notice now when the Red Box is held over the Blue Box we get a green "copy" icon next to the cursor showing the drag-drop operation will copy some data.

Thanks to feedback, the drop icon is now different, showing a "copy" action will be performed.

Thanks to feedback, the drop icon is now different, showing a "copy" action will be performed.
I've enhanced the drag-drop by adding feedback support via the DragManager.

Step 7: Use Drag Source

Back in Step 3 when we started the drag operation you may remember that we created a DragSource object to pass to the DragManager.doDrag() function.

A DragSource object is used to communicate data between the components of a drag-drop operation. We do this by putting data in the drag source when the drag begins that we can then inspect when deciding whether or not to accept a drop.

Below we'll modify our beginDrag() code to add data to the drag source using the addData() function.

The addData() function takes two arguments:

  • data:Object - object that specifies the drag data
  • format:String - specifies the format of the data
   public function beginDrag( mouseEvent:MouseEvent ):void
   {
      // the drag initiator is the object being dragged (target of the mouse event)
      var dragInitiator:IUIComponent = mouseEvent.currentTarget as IUIComponent;
      
      // the drag source contains data about what's being dragged
      var dragSource:DragSource = new DragSource();
      
      // add some information to the drag source
      dragSource.addData( "Red", "color" );
      
      // ask the DragManger to begin the drag
      DragManager.doDrag( dragInitiator, dragSource, mouseEvent, null );
   }

Now we'll modify our acceptDrop() function to only accept the drag-drop if the drag source has format data for the color (which we added above). To do this we get the dragSource property from the dragEvent and check if it has data of a specified format by calling dragSource.hasFormat() passing the format we're looking for ("color").

   public function acceptDrop( dragEvent:DragEvent ):void
   {
      var dropTarget:IUIComponent = dragEvent.currentTarget as IUIComponent;
      var dragSource:DragSource = dragEvent.dragSource;
      
      // accept the drop if the drag source has a "color" format
      if( dragSource.hasFormat( "color" ) )
      {
         DragManager.acceptDragDrop( dropTarget );
      }
   }

Obviously the drag source example we've used is quite simple, but we could put any data/format in the drag source to enable smart drag-drop operations.

Use DragSource to communicate data between the components of a drag-drop operation.

Use DragSource to communicate data between the components of a drag-drop operation.
I've enhanced the drag-drop by adding information to the DragSource object.

We're Done, Thank You!

Thank you for following along. If you found this tutorial helpful, please spread the word with a blog post or via Twitter.

Let others know about this tutorial via Twitter

@flexafterdark The Definitive Tutorial on Flex Drag-and-Drop: http://bit.ly/kWh0K

Ben Edwards
  • This tutorial was written by Ben Edwards, a professional Flex junkie, who wants to help you learn Flex.
  • Ben Edwards
  • Ben is the creator of Flex After Dark.
  • Check out Ben's Blog
  • Follow Ben on Twitter: @bennybeta
  • If you find this tutorial helpful, please spread the word with a blog post or via Twitter with a @flexafterdark and/or @bennybeta tag. Thank you!