List Shifter: Reverse, Rotate, Swap and ITERATE (Loop) Over Bubble Lists | Now Part of Floppy

Forgot to post this here: Here’s the video (well there’s two) I had promised, about how Bubble handles empty (null) values in Lists. I show how this effects native Bubble elements, plugins and SSAs. If you’ve ever experienced weirdness with list items seeming to disappear, this is one of the explanations. Also, Bubblers of any type might be interested in this for just general skill building:

I have the same problem.

I was hoping that the solution was to be to have a third workflow: triggered by the ListShifter Initialise/Updated event, which saves ListShifter’s Shifted List to the database. Unfortunately, it doesn’t get called after the Shift events.

I’m trying to achieve the following, where the options are Items and are stored in a Package’s Items (List of Items) field:

image

You’re missing something very basic: For this sort of use case, you don’t put ORIGINAL LIST in the RG, you put the SHIFTED List in the RG.

Thank you, but I know that!

image

Like @michael.dascal, this problem happens every second click. The first time, everything works correctly. The second time, the list momentarily updates, then reverts back what it was before the click. I’ll create a demo page.

What you’re probably doing is resetting List Shifter. If the results of your expression for List to Shift changes (that is if you somehow change the list that List Shifter is fed from [internally and at the outputs this is “Original List”], this causes List Shifter to run its update routine).

The other thing you might be doing is, of course, if you sequentially shift up or shift down the same INDEX by the same number of positions, you’ll just see the items swap back and forth with each other. Follow my video for a minute @michael.fielding :

1 Like

Thank you, @keith, I truly appreciate your thoughts on this. Alas, try it yourself, I’m pretty sure it’s not error between chair and keyboard (at least, on the end user side, it could be on the dev side!):

Here’s a demo.

I’m not on a paid plan so I don’t think I can invite you to edit the app?

Looking at the App Data tab in the editor, I’ve discovered that the first time a position is swapped, the database entry for the Items list DOESN’T change. However, what is displayed in the bottom RG in the demo - which should be the same as stored on the server - DOES change, and matches the ShiftedList shown in the top RG. At that point I’m pretty sure that the browser and actual database are now out of sync! This shows them out of sync (I did refresh the App Data view):

Here’s my theory: the save to database step, which is definitely trying to save ShiftedList, is being run before the server has received the updated ShiftedList, so it saves what is really still the original list. However, the browser’s representation of the Package, and its Items field, has meantime been correctly updated with the shifted list, so the bottom RG is correct (but now doesn’t match the server). Then, the second time the workflow runs, the list seen by the server save step is the ShiftedList after the first swap. The browser has made a second swap and both RGs update, but moments later the server - having this time detected an actual modification to the Items list for the Package - pushes an update to the browser. But the update is the ShiftedList as it was after the FIRST swap, so the ListShifter and both RGs revert back to the state after that first swap.

This little experiment seems to confirm this theory: I got them out of sync (swap positions just once), then went and changed the slug for the Package. Immediately, the front end updated, and brought the two RGs into sync with the database - changing the slug must send the browser a new record, including the current Items list.

If I’m right, the solution could be to have SHIFT Item Up/Down be able to pass a result to the next step (would that delay the save until the result was available on the server?), or to fire a Shift Completed event perhaps?

Just to confirm how I’ve set up the workflows:

If I’m right, the solution could be to have SHIFT Item Up/Down be able to pass a result to the next step

Plugins can’t do this because there’s no API to that in plugin builder unfortunately.

But I suspect what you’re doing is well, basically wrong. The idea is not to update the database each time you do something with item positions in List Shifter.

That way lies madness. When you’re DONE moving things around you might then commit the new item positions by replacing some list in the database with the Shifted List.

But if you have a simplified example whose editor you can share with me (pm) and I’ll take a look.

Yeah you are doing this wrong. The shift actions are designed just for what I was explaining in the video I sent you. And really only that.

These are “short running” but asynchronous actions. Your workflow reaches the next step before (or after) the previous step completes. We don’t know. And frankly, I don’t care (and neither does Bubble).

The swap (AKA SHIFT) action is so fast that there’s no reason for me to throw an event ba k to Bubble.

You don’t do this because YOU DON’T NEED TO DO THIS. Just have the user COMMIT their actions and THEN update the list.

If you disagree, go and write your own plugin.

Ouch. I’m sorry if I upset you somehow :open_mouth: I wasn’t blaming the #wonderful ListShifter and when I said there may be a error with the dev, I meant me, not you. My view is more that if I manage to get the browser and database out of sync, this is a Bubble shortcoming (TBH I’m finding more and more of them…)!

Your demo video is very generous, thank you. I’ve more or less implemented it the same way, but the thing is that your example doesn’t include 1) adding and deleting items or 2) saving the reordered list back to the database, and 3) I don’t have any Save button in my app so far and I don’t want the user to have to confirm when they’re done, I want it automatic.

I have now got something working reliably by using a custom state to hold the list. Add and Delete create/delete Items and add them into Package’s List (i.e. server side), and then I reload that list to the custom state to update the UI. OTOH, Move up and Move down change the custom state, then I schedule a workflow for 1s later which saves the custom state into Package’s List. This works reliably so far, but it’s a bit of a hack.

I think the cleanest option is probably a Swap and/or Move Up/Move Down SSA, by adding them to the equally #wonderful ListPopper And Friends. I’ve had a look at the code and the null replacement stuff looks funky… but I might be able to do it. Any tips? Or warnings against this approach?

So I did a proof of concept SWAP function on the server and it works. Only problem is the 1s delay before the UI updates! So I’m going to go with what I wrote above - client side for shifting, and server side for add/delete items.

FWIW, here is the code for server side swap that I used - this goes after ListPopper And Friends’ internal functions which are in all the other ListPopper SSAs:

currentList = getList(properties.data_source, null)

// store the values temporarily
// the -1 offset is because Bubble indices are 1-based, whereas JS is 0-based
item_1 = currentList[properties.item_1 - 1]
item_2 = currentList[properties.item_2 - 1]

// do the swap
currentList[properties.item_2 - 1] = item_1
currentList[properties.item_1 - 1] = item_2
                       
return { "shifted_list": currentList }

True for client side actions, but not server side, I think?

@keith tengo un problema similar pero investigando me aparece solo cuando el index 1 retrocede al index 0, luego de eso el plug in se desconfigura y empieza a errar, si retrocede o se pasa de la lista el plug funciona perfecto.

Que puede ser? , la configuración de la lista es la anteriormente descrita.

acompañó video para demostrar lo que me pasa

Saludos desde Chile y gracias por el aporte

Hi,

List shifter is giving me this error in the debugger. how can i solve this?

Hi there! I have been trying for a couple of days (for several weeks in total) to make a simple repeating group, have the ability to move items / reorder them and kinda sort them manually. It’s kind of a fundamental and basic feature of all apps and still, bubble don’t have it. Been using bubble for years and was never able to do it. I have seen this thread with the list shifter and it is way too complicated for me to even try but I was wondering if you sometime in near future would make a simple plugin to reorder my list of notes (see images)

I recently started using Bubble and was frustrated to not have a built-in function to move an element in a list. Was delighted to discover List-Shifter. Could now build a demo app that uses it and it works really well on the UI side. But to save the shifted list to the DB I needed to include a Button “Save” that assigns the shifted list to the thing that has the list of elements. That button works fine. But I would like to get rid of the button and rather have a workflow that automatically gets triggered each time the contents of the List-Shifter shifted list is updated. Is there such an event available in List-Shifter?

1 Like

Hello @keith and rest of the list shifter users, hoping I can get some guidance on a feature that I was hoping list shifter can do but has proven to be very difficult. I will explain below…

I have a RG that is meant to display a list of users. Every row in my RG contains a “+” symbol that will allow the user to select a user to add has seen in the image below -

My problem is the following - Upon selecting the “+” symbol the new row always gets added to the bottom of the RG. I am trying to get the new row of inputs to appear in the list position that is one position below the row that the “+” symbol was selected.

Furthermore if an input has text in it then the text present in that rows inputs should remain and stick to that row. This would mean if a row was shifted down the text in that rows inputs would also be shifted down.

Because these inputs are not linked to any “thing” in my database sorting becomes very difficult. I have tried to base the RG of numbers and then attempt to shift my list of numbers hoping that any inputs contained in that “numbers row” would also be shifted.

Any help on how to do this would be great. Thanks!

Hi @keith - how would one go about subtracting 1 list from a 2nd list? I know how to subtract a constant, but what if I wanted to do an iteration where each number in a list was subtracted by the corresponding number in the second list?:

For example:

List 1: 5, 7, 8, 10
List 2: 1, 2, 4, 9
Result: 4, 5, 4, 1

Dear @keith , I have studied much of this thread and watched your videos. I have a reasonable grasp of your wonderful plugin. I Have used it to iterate over a list of values to provide a grand total box - ace :slight_smile:

Next is to SORT a list based on a value computed by an external API. i.e my dB has a field ‘Quantity’ and the ‘Value’ is ‘Quantity x API price’.

See screenshots, I want to be able to sort this table by ‘Value’ (which is not in the dB).

But I can’t work out what to put in my SORT inspector… Could you (or someone) point me in the right direction?


In your case @martin10, you’ve got an Original List of different coins. So take that list and compute a list of values (let’s call it Values), where the Values are in the same order as the list of coins.

Now that Values list is what you use as your Sort By List.

One thing to note: Of course the Sort By List remains in its original order, so you’ll likely then want to display it as :sorted by… as well.

One way to do this more easily is to have a second List Shifter that holds your Value list. Then, when you sort the Coins and receive the SORT Complete event (remember to set the “Trigger Sort Complete” option), you can sort that Values list by itself (yes, the Sort By List can be a List Shifter’s Original List). Like so:

1 Like