How to Drag and Drop to Reorder Things in a List of Things Field

If you’ve landed on this page, you’ve likely seen a lot of posts and YouTube videos about how to drag and drop to reorder things in a repeating group. A quick search of the forums will reveal a number of good guides and Q&As.

The gist of what you’d be doing is that you are going to create a field called “order” and when you drop an item from your list on the drop area, you are going to create a workflow that changes the number that is stored in the order field. Your list is then sorted based on that order number.

This solution makes a lot of sense in the context in which it is offered, but I was trying to accomplish something different. My users select artwork to add to a portfolio, and I wanted them to be able to change the order of artwork in the portfolio by dragging and dropping. This is a different situation because my user will create a portfolio (the data type is Portfolio), and I will then store artwork in a field called Featured Artwork, which is a list of Artworks (also a data type).

In other words, the user can add as many artworks as they would like to this field, and I then display them from this list of artworks in a repeating group. I can’t associate an order number field easily with the individual artworks in the list.

I could imagine more complicated ways to accomplish what I was aiming for by creating a new data type that contains the artwork and portfolio and then adding a field for order, but I didn’t want to do this if I didn’t have to. I was looking for a simple way to change the order of the artwork stored in the list.

In setting out to do this I scoured the forums and couldn’t find any guidance. I’m sharing this in case you are trying to accomplish the same thing and hope that you can avoid the brain damage I suffered in figuring this out.

I have to begin by saying that I’m not a developer, I’m a retail business owner who has created an app to help artists. I will likely use incorrect terms, and I am probably doing things here that are less efficient than they could be. Be that as it may, I hope the concept I’m sharing here is helpful, and that you can use it to accomplish the same thing, likely in a more efficient and elegant way.

Let’s start by looking at my Data type for the portfolio:

Nothing too exciting here. This type will store inputs from the artist that will be used to create the portfolio. The relevant one for this conversation is the Featured Artwork, which is simply a list of Artworks.

So the first step for a user is selecting the artwork they want in the portfolio. I created a repeating group with all of the user’s artwork. They click on the artwork they want to add. I have each artwork added to a custom state on the page called “State - Selected Artwork”.

When the user is done selecting the desired artwork, they click on the save button and all of the artwork in the list is saved into the Portfolio data type, with the following workflow.

Nothing special here, but we’re going to be coming back to this field and using the Selected Artwork state repeatedly in the coming steps. The important thing I found is that the order in which items are added to custom states is retained when you then set the field from the custom state. So for my users, the order in which they select the artwork is the same order in which it’s going to get added to this list.

Once the list is saved, I present the user with a repeating group that shows the order that has been set and which will allow them to drag and drop the artwork into a new order or alphabetize the artwork.

Reordering

The steps to achieve this:

We have to have a drag and drop set up using the Draggable Elements plugin, which is a free plugin developed by Bubble. See: Draggable Elements | Bubble Docs

I’m not going to provide detailed guidance on how to set this up - all of the other guides and videos show you how to do this, and there’s nothing particularly tricky about the setup. The basics are that you are going to have a repeating group of your artwork, and within the RG, you create a drop area that then contains a drag/drop group, within which you place your image and text for the artwork you are going to be dealing with. Now, when your user drags the artwork, the user is picking up the Drag/Drop Group, and when they move it over another item in your list, it is now on top of the Drop Area. When they release, you can trigger a workflow to tell Bubble what to do with the dropped item.

In the traditional setup, you would change the order of the dropped item by setting a new number in the order field.

We’re going to do something different - we’re going to set several different states, that are then going to send a new list of artworks in the order we want, to the Portfolio Data type Featured Artwork field.

To understand this, we need to think about what happens when we drag and drop. Let’s say I grab the first artwork and want to move it down lower in the list. What we are doing then is changing the order of the items in the list, and shuffling them into a new order.

The first item is going to become the third item (for example), and now, what was the second item is going to become the first, what was the third item will become second, what was third will become second, and the first item is now the third. Anything after the third item will stay where it was.

In order to achieve this, we are first going to need the index of drop location-1 this will allow us to get the group of artwork located before the drop point.To achieve this we need a state which I named:

State Dropped Index-1

(I’m going for descriptiveness, not creativity in my state names)

We set it as follows in the workflow

Now that we have the index number stored in a state we can store each of the three groups of artwork, the dragged artwork, artwork prior to the drop location, and artwork after the drop location.
It looks like this:

If you look at the states, you’ll see I have states:

State-Artwork Prior to Drop

States-Artwork After Drop

(In know, my state naming convention isn’t consistent or creative. Oh well)

The first state is set by by pulling the state Selected Artwork, which was set when the user first selected artwork to be included in the portfolio up to the index number of the drop location -1, which we set in Step 1 of the workflow, but we’ll minus out the artwork that we’re dragging, which you’ll see here as the current workflow’s artwork. This gives us all the artwork before the drop point, except the dragged artwork if it happened to be among the works prior to the drop point. You will notice that I’ve then added the dragged artwork at the end of this value with “plus item Current workflow. I should rename this state to Artwork Prior to Drop, plus Dragged Artwork.

The second state is all of the artwork starting with the current cell’s index to the end of the list, minus the current workflows artwork, in case the dragged artwork came from a point after the drop location. Now we have all of the artwork from our portfolio in groups that we can place back into our selected artwork state in a new order, which is the next step of the workflow.

Now you might be looking at these first two steps of the workflow and asking, why bother with step 1 of the workflow, why not just use the index location-1 in creating the value in step two? Well, I tried that, and there must be something in Bubble’s order of operations or something else that I’m missing that prevented me from getting the index calculation I needed as part of one step. I had to first find the index, set a state, and then, in step two use the state number to create my lists of artworks.

Now we proceed to Step 3 and, based on the states we have set, reset the Selected Artwork state with our new order of artwork.

You can see here that we’re setting the Selected Artwork state by first including the group of artwork prior to the drop (which also includes the dropped artwork), merged with the artwork after the dropped artwork. In other words we’re taking the lists of artwork we have stored in those states and merging them together to create our new list of selected artworks, and because Bubble will retain the order in which we’re adding artwork to these various states, we end up with the new list of artworks in the Selected artwork state in exactly the order we want them.

There’s only one problem remaining with this approach. What we’ve done so far will work in every scenario where we drag the artwork around except in the case where we want to move the artwork we’re dragging to the end of the list. In that case this approach fails because the way we’ve set up the groups finds the artwork before the drop point, inserts the dragged artwork after it, and then includes all of the artwork after the drop point. This means that we’re able to make the dragged artwork the second to last artwork by dropping it on the last artwork in the repeating group, but have no way to make it the last artwork. To solve this, we simply need to add another drop point after our repeating group - it will look like this:

And its workflow looks like this:

This one is easier to set up and can be done in one step because we can simply take the list of artwork in the Selected Artwork state minus the current workflow’s artwork and then add the current workflow’s artwork back in, and presto! we’ve got our new order.

From a practical standpoint, that’s it. Changing the order of the items in a list simply requires us to pull the artwork from an existing list, chop it into artwork prior to the drop, the selected artwork, and artwork after the drop, to then reset the state.

You could add a step at this point in either workflow to save the new order to the database - I don’t do this, and instead let the user invoke another workflow to commit the change in order to the database - you saw the “Save Artwork” button above.

Not relevant to the process of saving the new order, I’ve taken one last step to make the dragging a bit more intuitive by creating a conditional formatting on the drop area so that when the drop area is dragged over, it’s heigh increases by the height of each row of my repeating group. This inserts a white space above the area a user is scrolling over to give a sense that there is space between the artworks where we will be placing the dragged artwork. This is how it is set up

This formatting does cause a little bit of unexpected jumping around when you drag a first item over the top of a second item, but I feel it’s worth it to get a more intuitive feel for the drop action. If someone can figure out a conditional that would prevent that jump, I’m all ears.

A more experienced developer may be able to consolidate workflow steps and do all of this more efficiently - again, I’m all ears for suggestions, but I hope this outline will prove helpful to you if you are struggling with reordering things stored as a list using drag and drop like I was.

2 Likes

@thecliff pointed out that I’ve inadvertently included an image twice and left out the image showing how I was setting the state Dropped Index - 1. Here is the correct image showing that step in the workflow.

1 Like

Instead of using an order field, would this work? This method uses 3 custom states and “rebuilds” it. I’ve found working with lists tricky without using plugins like ListShifter/Floppy (sp?).

Step 1: User Selects Artworks

  1. Create a repeating group listing all user-owned artworks.
  2. Add a custom state on the page (e.g., Selected_Artwork) of type Artwork (list).
  3. When a user clicks on an artwork to include, run a workflow:
  • Action: Set Selected_Artwork = Selected_Artwork :plus item Current cell's Artwork.
  1. After the user is done selecting, run a workflow (e.g., on “Save” button) to store Selected_Artwork into the Portfolio’s Featured Artwork field:
  • Action: Make changes to Portfolio: Featured Artwork = Selected_Artwork.At this point, the Portfolio’s Featured Artwork list is saved in the order the user selected.

Step 2: Set Up the Drag and Drop Interface

  1. Create a repeating group to display Portfolio’s Featured Artwork.
  2. Inside each cell:
  • Add a Drop Area (from the Draggable Elements plugin).
  • Inside that Drop Area, place a Drag/Drop Group containing the artwork’s image/text.
  1. This setup allows users to drag one artwork over another, triggering drop events.

Step 3: Handling the Drop Event to Reorder

When the user drops an artwork onto another cell’s drop area, you’ll run a workflow to reorder the Selected_Artwork list:

  1. Get the Drop Location Index:
  • Create a workflow triggered by the drop event.
  • First, store the “index before drop” in a custom state, say State_Dropped_Index-1.
    • Action: Set state State_Dropped_Index-1 = Drop Area’s current cell index - 1.
  1. Create Three Lists Using States:
  • Artwork Before Drop:
    Take Selected_Artwork up to State_Dropped_Index-1 (this gives everything before the new position), and remove the dragged artwork if it appears there.
  • The Dragged Artwork:
    This is the current workflow’s artwork.
  • Artwork After Drop:
    Take Selected_Artwork from the drop index to the end of the list, removing the dragged artwork if it’s there.Use custom states to hold these segments. For example:
  • State_Artwork_Before = Selected_Artwork:items until #State_Dropped_Index-1 :minus item Current Workflow’s Artwork :plus item Current Workflow’s Artwork
  • State_Artwork_After = Selected_Artwork:items from #Current Cell’s Index to end :minus item Current Workflow’s Artwork(You may adjust these exact expressions based on your indexing logic.)
  1. Rebuild the List in the New Order:
    After setting these states, merge them back into Selected_Artwork:
  • Selected_Artwork = State_Artwork_Before merged with State_Artwork_AfterNow Selected_Artwork reflects the newly ordered list.

Step 4: Handling the Last Position Drop

To allow dropping an artwork at the very end of the list:

  • Add an extra Drop Area after the last cell of the repeating group.
  • On drop into this final Drop Area:
    • Simply take Selected_Artwork :minus item Current Artwork :plus item Current Artwork to put the dragged artwork at the end.

Step 5: Saving the New Order

If desired, once the user is happy with the new order, they can click a “Save” button:

  • Action: Make changes to Portfolio: Featured Artwork = Selected_Artwork.

Thanks for posting this, Dave! I’ve been struggling to figure this out for the last few days and all of the options out there require an explicit order column, and doesnt work with things in a list. In any case, I’m going through this and I have two questions…

  1. I got stuck on creating the prior state because after selecting “state - Selected Artwork” I didn’t get an option for “:items until”. I set the type of that state up as number. I dont know what else would prevent that option from showing.
  2. Does this only work if the user creates the portfolio and then edits it? I would assume that creating it is how the “state - selected artwork” is first set, and then gets edited afterwords. I’m unclear on how I would pull the list from the list of things field, and then push that order into the state so i can then manipulate it afterwards.

I’m all ears… And thanks so much for posting this… sorely needed!

Glad this post is helping.

That state’s type is Artwork and it’s a list, just like the field in the Data Type where the artworks are being stored. Your state needs to match the type of objects it will be storing. If you set the state to the correct type and make it a list, you will then get the option for “items until #” and other list manipulation options.

1 Like

The states are getting set in workflows, and so, yes, I set the state when the user creates the portfolio. As the user selects artwork, each one gets addes to the state Selected Artwork, and then when they click the Save button, that state is used to set the Field in the Portfolio Data Type, Featured Artwork Field.

However, if the user returns to this page to edit the portfolio, the Select Artwork State is empty. If they go to reoder the the artwork, the drag and drop workflow is now populating that state again with the artwork as we go. The repeating group was generated from the Featured artwork field in the data type.

I hope that all make sense, but I’m happy to help clarify.

Right so all that makes sense. I made the states of the prior, after, and selected the list of things (and checked the list option), and set the state dropped as a number. That allowed me to set the workflow steps just as you did. I also set the state of the “selected” state to load the order from the list of field once the page loads. But its still not working for me.

The big thing that seems off (beyond it just not working) is that when I try and drag the thing (in my case, a movie title) it drags under the thing next to it, and just disappears entirely ( i moved goonies to the right and up, and then minority report to the bottom and down, and you can see how its disappearing) . I also setup some text to convey the values of the states and they are showing nothing. Check out some pics of the setup and the results… LMK what you think if you have a moment.




and here is the db setup

Ignore my previous comment - you did share the set state actions from your workflows. It would be helpful to see all the steps of your workflows that are triggered by the drop action so I can see the order of actions.

One issue I can see is that you have set up your Custom States on the repeating group. I set them on the page. It’s my understanding that you’ll only have access to the states within the element where it is set, so you won’t be able to display the content of your States outside of the repeating group if it’s set on the repeating group.

Help me understand that screenshot of your list of movies. Is that how it appears after you complete the drag, or are you showing it mid-drag? I think it’s after because we’re seeing the two moved movie posters out of alignment. That would seem to be an issue with formatting in your repeating group - do you have coniditionals set on the repeating group cells?

  1. Yes, the screenshot is after I complete the drag. Whenever I move the image outside of its original cell it just disappears and looks like its going under the cell next to it. If i swap the order of the drag area and the drag group (drag/drop group > drop area > image) then it works as I would expect although wherever I put the image it just stays there, and nothing gets swapped out. And everyone seems to get this to work without that so assume I’m doing something wrong that I’m just not aware of.
    The background on the setup here is that I have a lists page, that is showing multiple lists via the “RepeatingGroup List (Reusable)”. If a user clicks on the expanding icon associated to one of the lists, it sends a variable to the URL (w=1) along with the list id which causes “FloatingGroup List Order” to appear (via conditionals) which in turn surfaces the “RepeatingGroup List (Reusable)” element within it.
    If you look at the “RepeatingGroup List (Reusable)” you’ll see there are two repeating groups in there. The first option (static) is shown by default and is just a regular repeating group and is what is shown on the lists page. When w=1 is in the URL it hides the static and shows the draggable group. There are no conditionals on the image, just on the groups. I’ve attached the rest of the screenshots. I’m hoping there is something dumb i’m doing here that I’m just not aware of. (and thanks again for all of your help)
    ![Screenshot 2024-12-12 104236|413x395]
    (upload://JPs9jRFxZG9Sm0FOOrqno2fm4P.png)

oh, and you might have noticed that I changed where I set the states from the repeating group draggable to the top level element in that reusable element. Unfortunately, that didnt change any of the behaviors or state outputs.

This plugin does it with 1 workflow and no workarounds

i will check out that plugin. I tried the zeroqode one and unfortunately it didnt work on lists of things.

I’m slow in getting back to you. Just glancing at your setup, I can’t see anything that jumps out as a major issue, so it must be something in your basic setup of the repeating group, the states and workflows that isn’t passing the movies through correctly. I would just walk through each step and work to get it functioning correctly. You’re right to be trying to see the contents of your custom states - I would start there and keep tweaking until you are getting the info to pass through to your states, them move on to figure out how to save to your database. Let me know if I can help further. As I said in the original post, I’m not a wiz at this stuff, I just brute force with trial and error until I get it to work.

1 Like