Hello
I’m not sure if this solution has been posted before (my apologies if I missed it!), but I just wanted to write a short guide on how to reorder a repeating group using custom states incase anyone was looking for it as well. This can be useful if you want to allow the User to upload a list of things, files, or images, change the order, and then save the list in that exact order to a list field (without needing to use any “Make Changes to a List of Things” actions for every item in the repeating group).
Preview:
Editor:
On this page, there are two repeating groups which display a list of Tasks, and a list of files (images):
(I set the second repeating group as as a list of files incase your app’s images are being uploaded through the Multifileuploader plugin)
In this example, each “Board” Thing has a list of Tasks:
Each “Task” Thing contains “Title” and “Order” fields (though the Order field is not used at all in this example):
Every User has a new Board Thing created for them on page load (if they don’t already have one), which is set as the value of their “Board” field. This is just for the example as well so multiple people aren’t reordering the same list of Tasks:
When the page is loaded, the “ListofTasks” custom state value (type: Task, list: yes) on the Group Board element is set to be the Current User’s Board’s Tasks. Here is the custom state:
And here is the action which changes the custom state’s value to the Current User’s Board’s Tasks:
This “ListofTasks” custom state is used as the data source of the Repeating Group of Tasks:
Within each of the Task repeating group cells are 5 elements:
-
The “Hidden Input (Task) Current cell’s Index -1” element which is always equal to the Current cell’s index minus 1. This is hidden and underneath the other elements in the cell. We need to have this value for the drag/drop custom state actions:
-
The “Drop Area Task” element which expands the height and width of the entire cell:
It has this conditional statement which causes it to turn blue when another Group is dragged over the top of it:
-
The “Drag/Drop Group Task” element which takes up the full width of the cell, but leaves some space at the top so the sliver of blue is shown when a group is dragged over the cell:
As seen here in preview mode:
The “Drag/Drop Group Task” element has this conditional which changes its color if it is being dragged:
-
A text element containing the title of the Task:
-
A text element containing the row number of the cell (using Current cell’s index):
There may be a simpler way to set this up, but I have two workflows on the page which detect whether the Task that was just dropped was moved upwards or downwards from its previous position. For example, if we have a simple list of Tasks in this order (1,2,3,4):
Then we decide to move 3 to the second cell, in order to make the order (1,3,2,4), the workflow below occurs:
This workflow’s conditional states “When DropArea Task has a group dropped on it *only when: Repeating Group Tasks list of Tasks: items until Current cell’s index doesn’t contain the Current Workflow Task”. This condition is true in this example because the Current cell’s index value is 2, meaning that the Repeating Group Tasks list of Tasks items until 2 doesn’t contain Task 3. In this case, Bubble knows the Current User is moving a cell upwards, and we need to insert Task 3 between Task 1 and Task 2:
In order to do this there are two custom states on the Group Board element called “NewTasksBefore” (type: Task, list: yes) and “NewTasksAfter” (type: Task, list: yes):
First we need to store the value of the items that we need “above” (i.e., before) Task 3, followed by Task 3 itself. Since we just moved Task 3 into the second cell (making the order 1, 3, 2, 4), we want this custom state value to equal the Task 1 (the Task(s) above Task 3) and Task 3 itself. This is accomplished using this expression:
It looks probably overly complicated, but this is the only way I could get it to work at the moment (if anyone knows of a more simple way, please let me know! )
Here’s what the expression means:
Group Board's ListofTasks:items until #HiddenInput (Task) Current Cell Index - 1's value
Since Task 3 was just dropped into cell number 2, the Hidden Input value of that cell is currently 1 (since 2 - 1 = 1). This makes the expression “Group Board’s ListofTasks:items until #1” which returns Task 1. Now we just need to add Task 3 beneath Task 1.
:plus item Current Workflow Task
This part of the expression makes sure that Task 3 is after the Task 1 element. In summary, the value of the NewTasksBefore custom state becomes a list of two Tasks: Task 1, Task 3
Now we need to save Tasks 2 and 4 underneath Task 1 and Task 3. To do this, the second action sets this NewTasksAfter custom state (type: Task, list: yes) to be:
Here’s what the expression means:
Group Board's ListofTasks:items from #Current cell's index
Since the 3 was just dropped into the second cell, this expression is “Group Board’s List of Tasks:items from 2”, which returns Task 2, 3, and 4.
:minus item Current Workflow Task
We don’t want Task 3 in this custom state since it’s already; we only need the Tasks that go after Task 3: Task 2 and Task 4. We can remove Task 3 from this expression using :minus item.
Then, we just need to combine the two custom states (NewTasksBefore and NewTasksAfter) to become the new “ListofTasks” custom state in order to be displayed in the new, correct order in the Repeating Group of Tasks element. To do this we can combine the custom state values from Step 1 and Step 2 using the :merged with operator:
Now that we have the workflow setup for when a Task is moved upwards, we need a slightly different second action which occurs when a Task is moved downwards. For example, let’s say our list is back in the Order of 1,2,3,4:
If we moved Task 1 into the 3rd cell, to make the order 2, 1, 3, 4, this action occurs:
This workflow’s conditional states “When DropArea Task has a group dropped on it *only when: Repeating Group Tasks list of Tasks: items until Current cell’s index contains the Current Workflow Task”. This condition is true in this example because the “Current cell’s index value is 3”, meaning that the Repeating Group Tasks list of Tasks items until 3 contains the first cell Task (Task 1) of the repeating group. In this case, Bubble knows the Current User is moving a cell downwards, and we need to insert the Task 1 between Task 2 and Task 3.
In order to do this, we can first modify the “NewTasksBefore” custom state (type: Task, list: yes):
Here’s what the expression means:
Group Board's ListofTasks:items until #Hidden Input (Task) Current Cell Index - 1's value
Since the 1st Task was just dropped into the 3rd cell, this expression becomes Group Board’s ListofTasks:items until #2 (the Hidden Input’s value is 2 since 3 - 1 = 2). This expression returns the first two Tasks in the list: Task 1, Task 2
:minus item Current Workflow Task
We don’t want Task 1 to remain as the first item in the list, so we can remove it from the first expression using :minusitem
:plus item Current Workflow Task
Then we can add Task 1 back into the list, reordering it to be after Task 2 by using :plus item. It probably looks confusing, but we’re just subtracting Task 1 from the first part of the expression and adding it as the last item in the “NewTasksBefore” custom state.
Next, we need to update the “NewTasksAfter” custom state:
Here’s what the only when condition means:
Group Board's ListofTasks:items from #Current cell's index
Since Task 1 was just dropped into the 3rd cell of the repeating group, between Task 2 and Task 3, this expression becomes Group Board’s List of Tasks: items from #3 (since the current cell’s index is 3). This expression returns the 3rd and 4th Tasks making the NewTasksAfter custom state value be: Task 3, Task 4
Similar to the other workflow, we just need to combine the NewTasksBefore and NewTasksAfter custom states to be the value of the ListofTasks custom state using :merged by:
In this example, the order is saved when the Current User clicks the “Save” button by using the “set list”:
However, if you need to continuously save the value of the reordered list, you can have this Make Changes to a Board action within the Drag/Drop workflows.
And that should work! The image example works in the same way (all of the workflows and data types are just of the “file” type instead of “Task”). Please feel free to let me know if you have any questions! (or suggestions!)