Drag n’ Drop in OutSystems, the recipe!

Joaopedrodelopes
Noesis Low-Code Solutions
6 min readFeb 22, 2021
outsystems drag and drop

There is a reason why development in OutSystems is done by drag and dropping widgets to a canvas — It’s simple! The user experience is great! Also, you do it everywhere: in Trello to rearrange cards; in Gmail to move emails to folders; with the Google Calendar to move appointments, among others.

“It is widely used in PCs, mobile phones (…) A majority of users are familiar with this function as it is useful for moving, grouping, or resizing objects.”
Umesh Kumar

Did you know about the fun fact below?

Regarding OutSystems’ applications, given the wide range of possible parents and childs in both web and mobile applications, it is important that whatever the solution we come up with, it has to be able to handle all of these.

By parents, we mean what will contain the draggable items and/or will be a droppable section: lists (ordered or unordered), tables, containers, among others. Additionally, childs are the draggable items that could be inside those parents, such as list items, containers, and more.

SortableJS Library

The SortableJS library¹ was the solution to this problem. First and foremost, it makes use of the HTML5 native DnD functionalities, avoiding the use of complex JQuery. Also, another great advantage is that although DnD [2, 3] is not prepared for touch devices, this is not the case with this library, as it overcomes this problem by saving the link to an element by its coordinates, uses the setInterval function to check if the dragged element is under the finger every 100 ms and clones the element afterwards.

Moreover, this library allows [4, 5]:

  • To select the elements to be sorted using a CSS-selector;
  • To create DnD groups and configure them, eg. items from group A can be moved to C, but can not be moved to B;
  • To choose what elements can and cannot be dragged;
  • To add a CSS class to the moved element and to add animations when moving items;
  • To have onAdd; onUpdate; and onRemove events;
  • To change a list (add; remove; edit) dynamically;
  • Among others.

At this point, it becomes clear how this library is so useful and why it is the go-to option to add this feature to OutSystems web and mobile applications. It is now our task to make a simple-to-use Forge component out of this complete and versatile library.

SortableJS Forge Component

After loading the minimized Javascript code to an OutSystems script and studying some available demos of the library [4, 5, 6, 7, 8], it was decided that the go-to development approach was to have a placeholder which could either be the parent (wrapper), or contain the parent (with a CSS-selector being required in this case). This placeholder would have the following Javascript snippet on the OnReady event of the Web Block:

function merge(dest, src) {
for(var key in src) {
dest[key] = src[key];
}
return dest;
}
function onDragEnd(e){
var itemEl = {
‘from’: e.from.getAttribute(‘data-list-id’), // previous list
‘to’: e.to.getAttribute(‘data-list-id’), // target list
‘oldIndex’: e.oldIndex, // element’s old index within old parent
‘newIndex’: e.newIndex, // element’s new index within new parent
}

$actions.TriggerOnDragEnd(JSON.stringify(itemEl));
}
var list_wrapper = document.querySelector($parameters.WrapperQuerySelector), // eg. “div > p”
options = JSON5.parse($parameters.OptionsJSON),
event = {
onEnd: function (e) {
onDragEnd(e);
}
};
options = merge(options, event);
if (list_wrapper){
list_wrapper.setAttribute(‘data-list-id’, $parameters.ListName);
Sortable.create(list_wrapper, options);
}
else
console.log(“There was an error retrieving wrapper!”);

And this is all that’s required to make a simple to use drag and drop component. You can notice that there’s also a TriggerOnDragEnd client action, which will send information about the drag and drop operation: the To and From wrappers and the old and new index, either from different wrappers, or from new wrappers. This information will be sent through an OutSystems event. The list can receive a JSON (allowing you to provide configurations), as well as the CSS-selector and the list name.

The Recipe

Here’s the recipe to add DnD [2, 3] to your OutSystems’ applications:

1.. Drag and drop the SortableJS placeholder to any screen/Web Block;

2.. Give a name do the placeholder and add that same name to the ListName input;

3.. Add sortable items inside (note that they can be inside a wrapper or not). An example could be a Table (Figure 1 and 2) with rows inside as the sortable items; a List; or simply containers (Figure 3);

Fig. 1 — Drag and dropping table elements within the same table or from one table to another (SortableJSDemo). The mouse pointer you see in the .gif does not correspond to the actual mouse position. It was a problem during the recording of the .gif.
Fig. 2 — Example of SortableJS usage with a table inside the SortableJS placeholder (from SortableJSDemo: see Fig. 1).
Fig. 3 — Example of SortableJS usage with a set of containers inside the SortableJS placeholder.

4.. If you need to drag items from one wrapper to another, repeat steps from 1 to 3, as many times as the number of wrappers you need;

5.. Add the CSS-selector to the wrapper. In the case of Figures 1 and 2, the query selector was the following:

“#” + Table.Id + “ tbody”

6.. Optionally, add some configurations in the JSON input, such as:

“{
animation: 200,
group: {
name: ‘list_group’
},
sort: true,
handle: ‘.table-handler’
}”

Note that the group property is required if one has several wrappers to drag and drop items from/to. All wrappers must be in the same group, in order to move items between them. Also, a handle can be added. In this case, the CSS class would be added to the icon on the right in Figure 2. This is just a simple JSON example, but you can already understand its usefulness. For more configuration options, see the library documentation⁹.

7.. Add an OnDragEndHandler to eventually save the novel list(s) configurations. An example of this client action is shown below:

Fig. 5 — Client action with the SortableJS onDragEnd event handler (example). On the server action you can store the current configuration/order of the cards, for instance.

That’s it! No more steps! This is as easy as it gets!

The Sky Is The Limit

Did we mention that you can add draggable sections, droppable sections, groups, CSS classes to several behaviours… Ahh! And it is compatible with mobile/touch devices!

Fig. 6— Dashboard cards being dragged and dropped. Again, the mouse pointer in the .gif above is not positioned correctly due to a problem when recording the .gif.
Fig.7 — Drag and dropping cards on a list on a physical mobile device.

The component is available in the OutSystems Forge:

[1]: SortableJS — Github Repository. https://github.com/SortableJS/sortablejs. Accessed: 06–07–2020.

[2]: HTML Drag and Drop API.
https://developer.mozilla.org/en-US/docs/Web/API/HTML_Drag_and_Drop_API Accessed: 04–01–2021.

[3]: Using the HTML5 Drag and Drop API
https://web.dev/drag-and-drop/ Accessed: 04–01–2021.

[4]: Sorting with the help of HTML5 Drag’n’Drop API. https://github.com/SortableJS/sortablejs/wiki/Sorting-with-the-help-of-HTML5-Drag'n'Drop-API. Accessed: 21–04–2020.

[5]: Sortable v1.0 — New capabilities. https://github.com/SortableJS/sortablejs/wiki/Sortable-v1.0-%E2%80%94-New-capabilities. Accessed: 21–03–2020.

[6]: SortableJS — JavaScript library for reorderable drag-and-drop lists. http://sortablejs.github.io/Sortable/. Accessed: 22–03–2020.

[7]: Swap Thresholds and Direction. https://github.com/SortableJS/sortablejs/wiki/Swap-Thresholds-and-Direction. Accessed: 22–03–2020.

[8]: Dragging Multiple Items in Sortable. https://github.com/SortableJS/sortablejs/wiki/Dragging-Multiple-Items-in-Sortable. Accessed: 22–03–2020.

[9]: Sortable — Options.
https://github.com/SortableJS/Sortable#options. Accessed: 06–07–2020.

--

--