10 min read

How to Add Drag and Drop to Wix Website

Ever wanted to add drag and drop functionality to your Wix website? Learn how in this article.
How to Add Drag and Drop to Wix Website
File Upload Image from Adobe Stock

Adventures with Wix Development

The ability to drag and drop files for uploading can drastically simplify websites. Many modern websites implement this functionality, allowing website visitors to simply ‘Drag’ the files they wish to upload to the screen and then ‘Drop’ them to trigger an upload.

Wix doesn’t support this functionality out of the box. This means that you’re often stuck using ‘Upload’ buttons, a solution that can be a bit ugly. Worse, this can introduce extra clicks for visitor interactions, which has been shown to reduce sales.

What You’ll Get

In this article, I’ll show you how to implement drag and drop on your Wix website. All you need is a basic understanding of Javascript, the ability to add an HTML Component to your website, and enough knowledge to navigate the Wix Editor.

If you’d like to see a working example of this functionality, check out this link where I’ve implemented it (note, as discussed later in the article you will need to sign up for a free login to see it). However, if you don’t want to sign up, I’ve made sure to include helpful screenshots throughout.

Throughout the article, I’ve used a common color scheme and logo combination, to demonstrate easy ways to brand this content for yourself. All images were developed by me on Canva.

Get Started

To get started, set up a new project on your Wix account. At a minimum, you’ll need the following:

  1. A blank page where you can put the components
  2. Your Wix Editor set to ‘Dev Mode’

Add the Following

Now we’ll start adding the base components you’ll need to get started.

  1. Empty HTML Component. This can be found by searching the + section of the Editor.
  2. A new collection called Drag and Drop Upload. This section should have the columns UserId, Image, and the optional CartId if you’re attaching this functionality to the Wix Store app.

Upload Process Overview

I’ll outline a few complexities to help frame the the article.

  1. An HTML Component is considered by your Wix page as an entirely separate webpage. This means we need a way to securely transfer information to and from the parent and component pages
  2. We need to choose when we’ll store the data a user uploads. There are multiple different points when this could happen, I’ll choose one and demonstrate.

Here’s what the upload process flow we’ll be implementing looks like:

Articulates the five steps this article works through
Five Step Process for Wix Drag and Drop Upload

Upload Process Steps

  1. User drags and drops file(s). This is the first step and it triggers the process flow. A user drags and drops the file(s) they need to upload. This is the step where we’ll filter file types.
  2. HTML Component handles interaction. The HTML component deals with the user interaction in a seamless manner.
  3. Uploaded files sent to Parent page. The files are sent to the parent page for further interaction.
  4. Parent page receives files. The parent page receives the uploaded files, and processes them further
  5. Uploaded files saved. File(s) saved to Wix collection

User Drag and Drop

Let’s set up the drag-and-drop HTML component in way that:

  1. Indicates that this is the place to drag-and-drop
  2. Recognizes a drag event
  3. Recognizes a drop event
  4. Provides visual cues to users of events

Indicate Drag and Drop

To do this, we must declare the HTML page. Insert the code below in your HTML Component.

<html> 
  <head> 
    <title>File Upload</title> 
    <script type="module" src="./index.js"></script> 
    <style> 
      body { 
        border-style: solid; 
        border-color: #29c1e8; 
        margin: 0px 0px 0px 0px; 
      } 
    </style> 
  </head> 
  <body> 
  </body> 
</html>

If you save this, you’ll see your page now has a nice border around it. I’ve chosen to go with a border color that matches the coloring of my brand, but you can use any color you want.

Make it Pretty

Add a new div to the <body>of your HTML component which declares the drag-and-drop event handlers (links to the Javascript functions at bottom of article).

<div 
   id="dropzone" 
   style="height: 100%; width: 100%;" 
   > 
</div>

Within the <div>, add a <img> declaration and provide a link to an upload image you’d like to use.

<img 
  id="displayImg" 
  src="your_url.svg" 
  style="width:100%; height:100%;" 
>
Note. I always prefer to use the .svg format in this scenario. SVG’s are smaller, and look great on any size screen.

Here’s what my upload HTML component looks like in my Wix Editor:

Blue arrow pointing up into a blue cloud.
HTML Component Outline on Wix Editor. Part of article “How to Add Drag and Drop to Wix Website”.

Handle Drag And Drop Events

Now, let’s handle our drag events and drop events. We need to:

  1. Inform the page what to do next with an event
  2. Update our <img> tag to show different images to visually indicate to users what to do next.

Here’s how:

  1. Find an image you’d like to display while users are hovering over the upload box
  2. Find an image or gif to display while files are being uploaded
  3. Add the following two functions within some <script> tags
<script> 
    const imageList = document.querySelector('.image-list'); 
    const fileInput = document.querySelector('files'); 
    const dropzone = document.querySelector('.dropzone'); 
 
    const setActive = (dropzone, active = true) => { 
      const hasActiveClass = dropzone.classList.contains('active'); 
 
      if(active && !hasActiveClass){ 
        document.getElementById("displayImg").src = "https://static.wixstatic.com/shapes/c76efe_dbbb002c4ac04c96b3a463d0f3e49141.svg"; 
        return dropzone.classList.add('active'); 
      } 
 
      if(!active && hasActiveClass){ 
        document.getElementById("displayImg").src = "https://static.wixstatic.com/shapes/c76efe_0c1c63fb6eea49aaafdfe9d2008d56a5.svg"; 
        return dropzone.classList.remove('active'); 
      } 
    } 
 
    dropzone.addEventListener('dragenter', (e) => { 
      e.preventDefault(); 
      setActive(dropzone); 
    }); 
 
    dropzone.addEventListener('dragover', (e) => { 
      e.preventDefault(); 
      setActive(dropzone); 
    }); 
 
    dropzone.addEventListener('dragleave', (e) => { 
      e.preventDefault(); 
      setActive(dropzone, false); 
    }); 
 
    dropzone.addEventListener('drop', (e) => { 
      e.preventDefault(); 
      setActive(dropzone, false); 
      document.getElementById("displayImg").src = "https://static.wixstatic.com/media/c76efe_d623f6694f9c434bb2b1b07d286fa697~mv2.gif"; 
    }); 
  </script>

As you can see, we’ve now added some event handlers to our page. We track:

  • When a user drags an element into or out of the HTML Frame
  • When the user ‘drops’ an image into the HTML Frame

Here’s what mine looked like in Preview mode (Windows Game bar doesn’t show you the file I drag and drop):

Gif that shows two different event handlers interacting. Event one, blue arrow to cloud turns to grey. Event two is a gif with text “Uploading…”
Demonstration of Upload box changing as users interact.

Send Files to Parent Page

With our event handlers in place, it’s time to send our uploaded files to the Parent page.

Security Note. Sending information from an HTML Component to a parent page can cause insecurity on your webpage. Make sure you always specify and filter incoming messages.

Enable HTML Component to Send Messages

Return to the HTML Component and update it with the functionality to send messages to the Parent page.

Note. The getParentURL() function below ensures that you only send information to the Parent page. If you don’t include it, you may find some browsers block you as this is a common information security problem.
// Get the parent URL 
function getParentUrl(){ 
  var parentURL = "No URL" 
  parentURL = (window.location != window.parent.location) 
      ? document.referrer 
      : document.location.href 
  return parentURL; 
} 
 
// Send messages to parent 
function sendMessageToParent(type, message){ 
  var parentURL = getParentUrl(); 
  let messageObject = { 
      type: type, 
      message: message, 
  } 
  window.parent.postMessage(messageObject, parentURL) 
}

Send Drop Files to the Parent Page

With message sending/receiving enabled, dropped files need to be processed. We need to:

  1. Filter files to only send certain types
  2. Send image data to parent page

Add the below functions to your HTML Component:

// Handle files 
    const handleFiles = (files) => { 
      // Get valid files 
      let validFiles = [...files].filter((file) => 
        ['image/jpeg', 'image/png'].includes(file.type) 
      ); 
 
      // Show the image 
      validFiles.forEach(uploadFiles); 
 
      // Return display at completion of upload 
      document.getElementById("displayImg").src = "https://static.wixstatic.com/shapes/c76efe_0c1c63fb6eea49aaafdfe9d2008d56a5.svg"; 
    } 
 
    // Show Image function 
    const uploadFiles = (image) => { 
      const reader = new FileReader(); 
      reader.readAsDataURL(image); 
      reader.addEventListener('load', (e) => { 
        sendMessageToParent("File", e.target.result); 
      }); 
    }

As you can see, the line validFiles filters so that only .png and .jpeg files will be uploaded. A list of file types is included in the resources section at the bottom.

Now update the dropzone.addEventListener(‘drop’ function from the previous section so that it triggers handleFiles. Here’s what it should look like:

dropzone.addEventListener('drop', (e) => { 
  e.preventDefault(); 
  setActive(dropzone, false); 
  document.getElementById("displayImg").src = "https://static.wixstatic.com/media/c76efe_d623f6694f9c434bb2b1b07d286fa697~mv2.gif"; 
  // Get the FileList 
  const {files} = e.dataTransfer; 
  handleFiles(files); 
});

Receive Images on Parent Page

Prepare Parent Page to Receive Messages

In order for the images to be processed by your Wix site, you need to enable the site to receive messages from the HTML Component.

Add the following to your Wix Drag and Drop page:

$w.onReady(function () { 
 
$w('#dragAndDrop').onMessage((event) => { 
  let receivedData = event.data; 
  // Send the received message to our processMessage function 
  if(receivedData.type == "File"){ 
   processImage(receivedData); 
  }else if(receivedData.type == "Debug"){ 
   console.log(receivedData.message); 
  } 
 }); 
 
}); 
 
 
export async function processImage(imageData) { 
 console.log("New Image Received"); 
}

Astute readers will probably notice that I’ve incorporated a couple of different message options. This allows me to send custom logging from the HTML Component — something which is particularly helpful when troubleshooting or running your website at scale!

Save Uploaded Files

With the files being sent to the parent page, it’s time to store them in the collection created near the start (Drag and Drop Upload).

Start by updating your Wix page in a way that will allow you to definitively link files to users. Two easy ways to do this are to use the Cart Id (which is unique to a user and order but requires the Wix Stores App) or User Id (which is unique to a user). In my example, I haven’t linked my upload page to a store, so I’ll hide the page behind a (free) login.

Next, create a backend function called wixDragAndDrop.jsw in your backend. This function will take files uploaded by users, associate them with the userId, then save them into the Drag and Drop Upload collection. Here’s the code:

import wixData from 'wix-data'; 
import {currentMember} from 'wix-members-backend'; 
 
export async function addFile(fileImage){ 
    let logging = { 
        "function": "addFile", 
        "location": "backend/tutorials" 
    } 
 
    let memberOptions = { 
        fieldsets: ['FULL'] 
    } 
 
    // Add user email for tracking 
    let userId = await currentMember.getMember(memberOptions).then(member => { 
        return member._id; 
    }).catch(err => { 
        console.error(err); 
    }) 
    logging.userId = userId; 
 
    // Create the insert object 
    let insertObject = { 
        userId: userId, 
        image: fileImage 
    } 
 
    // Set permissions 
    let options = { 
        "suppressAuth": true 
    } 
 
    console.log(logging); 
 
    wixData.insert("DragAndDropUpload", insertObject, options).then(item => { 
        console.log("Inserted Successfully"); 
    }).catch(err => { 
        console.log(err); 
    }); 
}

Return to the parent page, import the backend function, then update the processImage function with the following:

addFile(newImage);

Here’s a demonstration of the functionality working:

Display of website drag and drop working
Drag and drop events working on website

Say Hi!

I love hearing from my readers, so feel free to reach out. It means a ton to me when you clap for my articles or drop a friendly comment — it helps me know that my content is helping.

Resources

  1. Wix
  2. Canva
  3. Filetypes recognized by Javascript
  4. Filetypes recognized by Wix

HTML Component Full

<html>
  <head>
    <title>File Upload</title>
    <script type="module" src="./index.js"></script>
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css">
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.1/jquery.min.js"></script>
    <style>
      body {
        border-style: solid;
        border-color: #29c1e8;
        margin: 0px 0px 0px 0px;
      }
    </style>
  </head>
  <body>
    <main>
      <div
       id="dropzone"
       style="height: 100%; width: 100%;"
       >
        <img
          id="displayImg"
          src="https://static.wixstatic.com/shapes/c76efe_0c1c63fb6eea49aaafdfe9d2008d56a5.svg"
          alt="Wix Drag and Drop Upload"
          width="100%"
        />
      </div>
    </main>
  </body>
  <script>
    const imageList = document.querySelector('.image-list');
    const fileInput = document.querySelector('files');
    const dropzone = document.querySelector('.dropzone');

    const setActive = (dropzone, active = true) => {
      const hasActiveClass = dropzone.classList.contains('active');

      if(active && !hasActiveClass){
        document.getElementById("displayImg").src = "https://static.wixstatic.com/shapes/c76efe_dbbb002c4ac04c96b3a463d0f3e49141.svg";
        return dropzone.classList.add('active');
      }

      if(!active && hasActiveClass){
        document.getElementById("displayImg").src = "https://static.wixstatic.com/shapes/c76efe_0c1c63fb6eea49aaafdfe9d2008d56a5.svg";
        return dropzone.classList.remove('active');
      }
    }

    dropzone.addEventListener('dragenter', (e) => {
      e.preventDefault();
      setActive(dropzone);
    });

    dropzone.addEventListener('dragover', (e) => {
      e.preventDefault();
      setActive(dropzone);
    });

    dropzone.addEventListener('dragleave', (e) => {
      e.preventDefault();
      setActive(dropzone, false);
    });

    dropzone.addEventListener('drop', (e) => {
      e.preventDefault();
      setActive(dropzone, false);
      document.getElementById("displayImg").src = "https://static.wixstatic.com/media/c76efe_d623f6694f9c434bb2b1b07d286fa697~mv2.gif";
      // Get the FileList
      const {files} = e.dataTransfer;
      handleFiles(files);
    });

    // Handle files
    const handleFiles = (files) => {
      // Get valid files
      let validFiles = [...files].filter((file) =>
        ['image/jpeg', 'image/png', 'application/pdf'].includes(file.type)
      );

      // Show the image
      validFiles.forEach(uploadFiles);

      // Return display at completion of upload
      document.getElementById("displayImg").src = "https://static.wixstatic.com/shapes/c76efe_0c1c63fb6eea49aaafdfe9d2008d56a5.svg";
    }

    // Show Image function
    const uploadFiles = (image) => {
      const reader = new FileReader();
      reader.readAsDataURL(image);
      reader.addEventListener('load', (e) => {
        sendMessageToParent("File", e.target.result);
      });
    }

    // Get the parent URL
    function getParentUrl(){
      var parentURL = "No URL"
      parentURL = (window.location != window.parent.location)
          ? document.referrer
          : document.location.href
      return parentURL;
    }

    // Send messages to parent
    function sendMessageToParent(type, message){
      var parentURL = getParentUrl();
      let messageObject = {
          type: type,
          message: message,
      }
      window.parent.postMessage(messageObject, parentURL)
    }
  </script>
</html>

Parent Page Full

import {addFile} from 'backend/tutorials/wixDragAndDrop'

$w.onReady(function () {

	$w('#dragAndDrop').onMessage((event) => {
		let receivedData = event.data;
		// Send the received message to our processMessage function
		if(receivedData.type == "File"){
			processImage(receivedData);
		}else if(receivedData.type == "Debug"){
			console.log(receivedData.message);
		}
	});

});


export async function processImage(imageData) {
	console.log("New Image Received");
	// Receive the new image
	let newImage = imageData.message
	addFile(newImage);
}

Backend File

import wixData from 'wix-data';
import {currentMember} from 'wix-members-backend';

export async function addFile(fileImage){
    let logging = {
        "function": "addFile",
        "location": "backend/tutorials"
    }

    let memberOptions = {
        fieldsets: ['FULL']
    }

    // Add user email for tracking
    let userId = await currentMember.getMember(memberOptions).then(member => {
        return member._id;
    }).catch(err => {
        console.error(err);
    })
    logging.userId = userId;

    // Create the insert object
    let insertObject = {
        userId: userId,
        image: fileImage
    }

    // Set permissions
    let options = {
        "suppressAuth": true
    }

    console.log(logging);

    wixData.insert("DragAndDropUpload", insertObject, options).then(item => {
        console.log(item);
    }).catch(err => {
        console.log(err);
    });
}