Skip to Main Content

Breadcrumb

Overview

The FOS - Drag and Drop dynamic action plug-in makes it possible to drag & drop elements inside a region. This could be a Cards region, a Badge list or basically everything that has a group of elements.

On every change of the order of items an event is fired passing the necessary change information accessible via "this.data" within your dynamic action handler. Additionally you can execute PL/SQL code to do an update of your database tables or execute some additional Javascript code.

The plug-in is built around Shopify's Draggable library (https://github.com/Shopify/draggable).

Thanks to the plug-in's structure and to the simple interface it comes with, it is very easy to add the functionality to any component. The only thing you have to take care of is that the draggable DOM elements inside the component must be uniquely identifiable. If there is no unique ID, the plugin can't inform the dynamic action of the correct sequence. There are two ways to pass the identifiers: either set a data-id attribute on the draggable elements (this would be the default behavior) or utilize the config.dataIdFn property in the JavaScript Initialization Code. If you define this function, the first and only parameter it would receive is the dragged DOM element. You should return a unique ID from this function for every element. Here is an example how the DOM ID could be used instead of the (default) data-id attribute:


function (config) {
    config.dataIdFn = function (el) { return el.id };
}

The presence of the data-id attribute depends not only on the Component but on the selected Template as well, e.g. the Menu Popup Template on a List component has a declarative Data ID attribute, but the Badge does not. While in the first case, you can just pass the value to the attribute and that's it; in the latter you must add it by yourself; in the examples below we show you a few very simple workarounds how to achieve it.

Examples

Swap or Sort

There are two different ways how the re-ordering can happen, this is what you can define with the Mode option:

- Swap: the dragged element is changing place with the element it is being dropped on, only these two elements will be updated.

- Sort: the dragged element will be placed before or after the element it is being dropped on and the elements following it may get resequenced as well.

Add a Drop Action

With the help of the Drop Action attribute you can define what should happen when an element has been dropped.

Plug-in Events

There're two different events of interest dispatched by the plug-in:
- the Sequence Updated event - it happens right after an item was dropped and the new sequence is calculated for the group,
- and the Update Complete event - (it's triggered only if the Drop Action is set to Execute PL/SQL Code) when the provided code is executed and the response has returned successfully.

In the first case, all the important information is accessible through the this.data object.

The example below - a List component with Linked List template - when you move an element to a new position, on the Sequence Updated event we output the content of the this.data object.

Execute PL/SQL Code

Just as in the JavaScript context, all the plug-in related data is accessible on the server too.

The apex_applicaiton.g_clob_01 provides you with the very same JSON object but to make it more comfortable, you can also access these bind variables: :DRAG_ID, :DROP_ID, :BEFORE_SEQUENCE, and :AFTER_SEQUENCE. Those variables will provide the element-id's taken out of the data-id HTML attribute (or your dataIdFn as explained above).

In this example the Drop Action is set to Execute PL/SQL Code, so we're able to react to the Update Complete event; - a notification will be displayed after an Item Drop and the code execution.

Use it with Reports

You can easily use this dynamic action on Reports as well. The thing to note is that you will need to re-initialize the drag and drop setup when the report data changes - such as on refresh, pagination, sorting (as you can see in both examples when you sort or filter)

Classic Report

Classic Report Example

 
7839KINGPRESIDENT-11/17/1981100010;)
7698BLAKEMANAGER78395/1/1981100030-
7782CLARKMANAGER78396/9/1981100010-
7566JONESMANAGER78394/2/1981100020-
7788SCOTTANALYST75664/19/1987100020-

Interactive Report

Interactive Report Example

EmpnoEnameJobMgrHiredateSalDeptnoCommBio
7839KINGPRESIDENT-11/17/1981100010-;)
7698BLAKEMANAGER78395/1/1981100030--
7782CLARKMANAGER78396/9/1981100010--
7566JONESMANAGER78394/2/1981100020--
7788SCOTTANALYST75664/19/1987100020--
  • 1 - 5

There are three important configuration settings to mention which are very useful when working with different types of regions: groupSelector, itemSelector and handle:

  • groupSelector - Defines the parent/ancestor element which contains/houses your draggable elements. This must be a selector (class name, id) of an element in your region. E.g. in the Interactive Report's example it is set to tbody.
  • itemSelector - Defines the draggable elements' selector inside your region. The elements must be descendants of the element defined by the groupSelector. E.g. in the Interactive Report's example it is set to tr:not(:first-child). This selector queries relatively to the group element (defined by groupSelector).
  • handle - In case you wish to utilize a handle element by which you can drag, you need to provide a selector for it as well. You can see an example of this handle in the Classic Report example. This selector queries relatively to the draggable element (defined by itemSelector).

To recap: define a group element in your region by setting groupSelector, this group will then be queried by the itemSelector to get the draggable items and if you are using handle, the draggable items will be queried to get the handle-elements.

Design

You can preview the plug-in setup as you would see it in page designer. You can either do this by clicking this button in the top right corner of each example, or you can see all the examples together in the region below.

Looking at the examples you'll see just how easy the plug-in is to use. Don't worry about changing any values as they aren't saved. We actually encourage you to change them, so you can see the behaviour of the attributes and their help text.

FAQ

  • Why is drag and drop not working after the user filtered/refreshed the report?

    Every time your region's markup changes (adding items/rows or refreshing) you should always initialize the Drag and Drop DA action again. This is because the plug-in needs to attach its listeners to the newly created DOM elements.

  • Can I use this plug-in with the Interactive Grid?

    There are too many restrictions that you must impose on the interactive grid to make this plugin work with it. In particular frozen columns make it impossible for the plugin to work, and there is no declarative way to disable columns from being able to be frozen. There are a number of other blocking issues too.

  • Are there any restrictions when I use this plug-in with the Interactive Report?

    Yes. Things like control breaks are not supported using the example code provided. You have the ability to tweak your interactive report settings and also the "Intiialization Javascript Code" of the plug-in to try and get more advanced features working. If you do manage to support these features after making changes please provide a demo on apex.oracle.com and let us know and we will update this page with your custom example.