---
schema_version: "1"
id: 283aa9288ee729a929543768a93d3190a5edc7079a71a5a6ed1e93d3c574a2ac
title: Draggable actions
collection: developer
version: current
locale: en-us
portal_url: https://docs.salesforce.com/developer/current/en-us/lwc/utam/guide/draggable-actions.md
canonical_url: https://developer.salesforce.com/docs/platform/utam/guide/draggable-actions.html
source_site: developer.salesforce.com
content_type: documentation
content_hash: 9b94eb0594a1187acb2831758da3bd62ea9348503b8c21253cfd7ebb5bc849c9
products:
  - UI Test Automation Model
  - lwc
---
# Draggable actions

A draggable element can be selected by the user with a mouse, dragged to a droppable element, and dropped by releasing the mouse button.

## Draggable element declaration

A draggable element must include `draggable` in its `type` property. In this example, one element is just draggable, but usually an element is both clickable and draggable because a user needs to click before they can drag.

```json
{
  "elements": [
    {
      "name": "onlyDraggable",
      "type": ["draggable"],
      "selector": {
        "css": ".drag-me"
      },
      "public": true
    },
    {
      "name": "myDraggable",
      "type": ["clickable", "draggable"],
      "selector": {
        "css": ".drag-me-too"
      },
      "public": true
    }
  ]
}
```

## DragAndDrop API

The `draggable` type exposes the following API for an element:

- `dragAndDrop(target: Element, hold: number)` clicks and drags an element to the location of the target element, then drops. The target element is provided as a parameter and doesn't have to be draggable.

A second optional parameter defines a hold duration in seconds that is applied after the click and before the drag. This hold duration can be useful to simulate a real user in some cases.

Usage in a JavaScript test:

```js
const source = await pageObject.getMyDraggable();
const target = await pageObject.getDropTarget();
// drag and drop without hold
await source.dragAndDrop(target);
```

Usage in a Java test:

```java
Draggable source = pageObject.getMyDraggable();
BasicElement target = pageObject.getDropTarget();
// drag and drop with 3 sec hold
source.dragAndDrop(target, 3);
```

- `dragAndDropByOffset(xOffset: number, yOffset: number, hold: number)` drops an element using coordinates relative to the current location of the element. It has an optional parameter for hold duration in seconds.

Usage in a JavaScript test:

```js
const source = await pageObject.getMyDraggable();
// drag and drop with 3 sec hold
await source.dragAndDropByOffset(100, 100, 3);
```

Usage in a Java test:

```java
Draggable source = pageObject.getMyDraggable();
// drag and drop without hold
source.dragAndDropByOffset(100, 100);
```

## Compose dragAndDrop

It's a good practice to compose a UI interaction as a public method inside a page object. Here are some examples of how to compose `dragAndDrop` and `dragAndDropByOffset` and how to provide a target element as a parameter.

### Drop at a known target element

The most common use case is to drop an element at a known target element location.
To do that, we pass `elementReference` to a known element as an argument:

```json
{
  "elements": [
    {
      "name": "myDraggable",
      "type": ["draggable"],
      "selector": { "css": ".foo" }
    },
    {
      "name": "dropTarget",
      "selector": { "css": ".moo" }
    }
  ],
  "methods": [
    {
      "name": "dragAndDropAtTarget",
      "compose": [
        {
          "element": "myDraggable",
          "apply": "dragAndDrop",
          "args": [
            {
              "type": "elementReference",
              "value": "dropTarget"
            }
          ]
        }
      ]
    }
  ]
}
```

The generated method declarations have no parameters because the target element is referenced inside the statement of the `dragAndDropAtTarget` method.

Generated JavaScript method declaration:

```js
dragAndDropAtTarget(): Promise<unknown>;
```

Generated Java method declaration:

```java
public void dragAndDropAtTarget();
```

### Drop at a known target element with hardcoded arguments

It's possible that the target element needs arguments for the selector or filter. Those arguments can be hardcoded in a compose statement. This example passes a hardcoded `myClass` value to the `dropTarget` in the `dragAndDropAtTarget` method.

```json
{
  "elements": [
    {
      "name": "myDraggable",
      "type": ["draggable"],
      "selector": { "css": ".foo" }
    },
    {
      "name": "dropTarget",
      "selector": {
        "css": "target[class='%s']",
        "args": [
          {
            "name": "classStr",
            "type": "string"
          }
        ]
      }
    }
  ],
  "methods": [
    {
      "name": "dragAndDropAtTarget",
      "compose": [
        {
          "element": "myDraggable",
          "apply": "dragAndDrop",
          "args": [
            {
              "type": "elementReference",
              "value": "dropTarget",
              "args": [{ "value": "myClass" }]
            }
          ]
        }
      ]
    }
  ]
}
```

If we omitted the `"value" : "myClass"` hardcoded value for the `dropTarget` element, it would be inferred and added to the method parameters.

JavaScript example:

```js
dragAndDropAtTarget(classStr: string): Promise<unknown>;
```

Java example:

```java
public void dragAndDropAtTarget(String classStr);
```

## Drop by offset inside a frame

It's always more reliable to `dragAndDrop` with a target element as shown in the previous section. However, that's not possible if the target element is inside a frame. Here's an example for Java:

```java
// get source element coordinates
ElementRectangle source = sourceElement.getRect();

// enter frame and get target coordinates
MyPageObject targetPageObjectInsideFrame = utam.enterFrameAndLoad(frameElement, MyPageObject.class);
ElementRectangle target = targetPageObjectInsideFrame.getTargetElement().getRect();
utam.exitFrame();

// offset is a difference between element centers
int xOffset = (target.getX() + target.getWidth()/2) - (source.getX() + source.getWidth()/2);
int yOffset = (target.getY() + target.getHeight()/2) - (source.getY() + source.getHeight()/2);

// drag and drop with a 5 second pause
source.dragAndDropByOffset(xOffset, yOffset, 5);
```

We don't show JavaScript code here but it's similar and uses the same methods.
