Draggable Popups with Angular and ArcGIS API for Javascript 4.x

Out of the box, the ArcGIS API for JavaScript has no way of allowing the Popup widget to become draggable.  Read on to find out how to fix it!

Instead, it employs docking as means of moving the popup away when it is blocking features from view that are important for the user to see. By default, the Popup widget contains an icon that, when clicked, docks the popup to a preset corner of the view. While docked, the popup is stuck to the corner even if the view extent changes.

The difference between a dragged popup and a docked popup, is that is that the dragged popup will be stuck to the same place on the map, so that it moves with the extent of the view. In some cases, clients may already be accustomed to this behavior and will be slow to adopt docking. We will be showing how to implement draggable popups in a GIS web application using Angular 6, angular2-draggable, and ArcGIS API for JavaScript 4.9.


We will assume you have a web application setup using Angular and esri-loader. In your HTML, you have a div element which holds the map with an ID assigned:

In your TypeScript, you have the MapView and Popup setup and some layer or method which causes the Popup to appear. In this example it will be an Identify Task using the publicly accessible Soil Survey Map layer tied to the view “click” event:

STEP 2: Setup Popup Container

In your HTML, you will need to create a new angular2-draggable div container within the map container in order to hold the Popup widget:

We have added the ngDraggable directive to make the div draggable and set an ID value that the Popup widget will contain itself within. We have also set the ngDraggable “handle” property to a variable “popupHandle” which we will declare in our TypeScript. We also set the “position” property to a variable and set the ngDraggable “started” event to a function we will later declare.

Back in the TypeScript, we will modify the Popup widget in the MapView properties so that it plays with the ngDraggable directive:

This will set the popup container to the draggable div we created in the HTML. It also disables the docking behavior and collapse behavior. Collapse allows the user to hide the main body of the popup by clicking on the header. Since we want to use the header for dragging, we will want to disable collapse so that it isn’t triggered at the end of dragging.

STEP 3: Set the PopupHandle and Position Variables

Next, we set the handle that the user will use to drag the popup as well as the popup position variable. Create variables for these before the initializeMap function:

Because the Popup widget can open from different locations around a feature depending on where it is within the view, we will check it’s class list to determine which HTML element to assign the handle to. This can be done by using watchUtils to keep track of the Popup widget’s “visible” property. We can also use this property to reset the popup position every time the popup is opened:

When the popup opens, it’s “visible” property becomes true. It also has a class added which determines if the popup title is above or below the main body. We want to use the element that is above the main body as the drag handle every time, so this helps us decide if this is the element which contains the title or the action buttons. In the code above, we reset the position by setting the x and y properties to zero. Then, we check the classList to decide which element to set as the popup handle. We also change this element’s style by setting the cursor to the “move” cursor.

STEP 4: Wire the DragStart Event and Control the Pointer Visibility

The popup can now be dragged around by its handle but the pointer, or triangle, that extends out from the popup to the feature location is still visible. We want to hide this when the popup has been dragged and show it when the popup is first opened. To hide the pointer, we will wire up the dragStart event and find it by class to set it’s display property to “none”:

Next, we will add a few lines to our popup visibility watch function. Instead of setting the display to none, we will reset it back to “block”:

And that’s it! You now have a draggable Popup widget.


Leave a comment

You must be logged in to post a comment.