Article
10 comments

SPFX Sample – Drag and Drop elements across web parts

The SharePoint framework improved a lot during the last drops. I thought to myself what fancy sample can I build using the framework. During the Hackathon at the European SharePoint Conference we saw a lot of great uses of this new framework. One team was even able to add a framework web part to SharePoint 2007.
Actually, last weekend I came up with an idea. It was more a proof of concept I would like to try. I asked myself the question. Will I be able to drag and drop data between two individual web parts.

The base setup

I created a new SharePoint Framework project and added two web parts. It might would have been easy to move elements in just one web part, but I wanted to try this approach across different web parts.
The first thing I did was to created two React components. One of those components provides an area where items could be dropped. The other component defines how the entries will be rendered.
To use this component in both web parts I created a single reusable component apart from the actual web part code.

SPFX - Reusable core component

SPFX – Reusable core component

For styling, this component I attached the style sheets directly in my core component. I also disabled the auto prefixing of style sheet classes provided by the framework because I wanted to share the style sheet definitions across both web parts too.

SPFX Rendering both Web-parts - With and without data

SPFX Rendering both Web-parts – With and without data

From my perspective, it is a good approach to develop components that are intended to be used in multiple web parts beside the actual web part code.
It is an approach similar to asp.net web controls.

Add reusable component to web part

To add these components to the web parts all that needs to be done is to import the component first.

View on Github
At the top of ‘FirstWebPart.ts’ and ‘SecondWebPart.ts’ I imported the components as ‘DragNDrop’ from a folder that actually was one level higher than the web part code.
The next thing that needed to be done is to create instances of the control in the render method of the web part.

View on GitHub
In the first web part code I added some predefined items while the second web part doesn’t contain any predefined items.
Now everything was ready to implement the drag and drop functionality.

Drag and Drop event handlers and handler binding

In general drag and drop on the web pages is no rocket science. All that needs to be done is to combine various events that will be fired on the start, during and after an item was dragged across the screen. Let’s take a look on which component what event needs to be registered.

DragNDropContainer

The drop container component is named ‘DragNDropContainer’. The events that need to be bound to this component are:

  • onDrop
    This event will be fired when a new element was dropped in the container.
  • onDragOver
    This event occurs during dragging the item around and contains useful information.

DragNDropItem

The name of the other component is ‘DragNDropItem’ and handles the following events

  • onDragStart
    This event occurs when you grab an item and start to move it around.
  • onDragEnd
    This event happens after the user stopped dragging the item around.

Last but not least the attribute ‘draggable’ needs to be defined on every instance of this component. Without this attribute the item is locked and cannot be moved.
So far so good, but now for the tricky parts. To be able to move items around the React data binding, and event firing needs to be implemented the following way.

Databinding

The first problem I faced with React was how to be able to access the parent container from every child item instance. Normally only data of the current element can be accessed through the events.
The solution was that I passed the parent container directly to the items. This way I was able to access both data, data of the child element and the parent container.
The generation and rendering of the ‘DragNDropContainer’ look like this.

View on GitHub

During the generation of the ‘DropNDropItems’ I simply passed the current container as a ‘parentList’ parameter.
Through this method I was able to update the state of the parent container and remove the already moved element.

Event

Finally, let’s take a closer look on the event firing order.
When you drag items around you actually not drag the item itself, you simply drag the data or the DOM content of the element. After you moved an element, the originating element needs to be removed manually.
For the user it looks like dragging the item around.

onDragStart

This is the first event that will be fired when you start to drag an item. Now its time to attach information about the selected element to the event. For storing those the data the ‘dataTransfer’ object needs to be used.

View on GitHub
The itemData variable stores all information of the component and only was converted to a JSON string. This ‘data’ is persistent throughout the whole event.

onDrop

The second event that needs to be handled once the item was dropped in the drop container. This is attached to the ‘DragNDropContainer’. All that needs to be done in here is to create a new instance of the moved element.
All that this event does it to request the previously stored event data. Then the data were pushed to the state of the ‘DragNDropContainer’.

View on GitHub
The update of the state automatically adds a new item instance, as a child control of the user interface.
The last thing that needs to be done is to remove the origin element and identify if the drag was successful or failed.

onDragEnd

Again this event is registered on the child items but not on the container. This event contains the same stored data in the dataTransfer object. In addition the dataTransfer contains a variable named dropEffect. This ‘dropEffect’ indicates the state of the dragging transaction.

The value ‘none’ means that the move was canceled or unsuccessful. In this case the item will automatically return to its original position on the screen.
Other possible values of the dropEffect are:

  • copy
    A copy of the source item is made at the new location.
  • move
    An item is moved to a new location.
  • link
    A link is established to the source at the new location.
  • none
    The item may not be dropped.

If the transaction contains ‘move’ the originating item can be removed again by updating the state of the parent container.
I hope this helped a bit to demystify the drag and drop handling in components.
Finally, let’s take a look at the final solution.

The finished solution and thoughts

SPFX - Drag and Drop between the web parts

SPFX – Drag and Drop between the web parts

Like I promised. Drag and drop in web applications are no rocket Science and helps to improve the user experience for certain scenarios. Just to mention some. You might be able to create your own Kanban board and update the state of a task element.
Another scenario is that you will be able to drag and drop documents across libraries. I think there are many things this user interaction pattern can be useful.
Sadly drag and drop is currently not supported on mobile or tablet devices.
In future I expect that this will become more relevant because the number of devices that are touch enabled will increase in future.
If you like to try this solution yourself. Please feel free to clone it from my GitHub repository.
In case you experience any problem you can create a new issue on the repository or comment below.
I’ll love to hear from you and what you think about this solution.