FLOPPY: Plugin for localStorage, sessionStorage, IndexedDB storage, List Creation/Manipulation, Iteration, and More! Now with even more video docs!

Good to know! I understand that I might be trying something here that was not the main goal of floppy but would it be possible to not remove the keys if the value is empty and to have “easy” ways of checking whether or not the key and/or value is present/empty? If this is possible we might use floppy with indexeddb to use it as a offline db for a lot of use cases. I can imagen that someone has workflows that need to run when the value is empty for instance. Or like me the need to run something like “add key” in case the key is not there yet but needed in the app.

BTW, I really love the fact that you put much attention to details into floppy. Thought about many handy options and everything has documentation attached to it. You can see the love you put into it!

Ok, lots of testing and trying I think I have found the “issue” of not being able to trust the expression box outcome in my workflow steps

@keith not sure if you can do anything about it but if you can, this might be handy!

I had a workflow setup that would run when floppy is initialized. In the workflow I want to compare values and keys. I can run the expression but still it was not respecting the expression. Also, on some pages it did work just fine, on others it did not. When it worked it was not always consistent. Meaning that sometimes the workflow runs when it should not or vice versa.

Today I started testing with adding a pause before the other workflow steps would run. In some cases, 5 ms was enough, in others it needed 50ms. Sometimes it needed 100+ms. It depends on the pieces that the page needs to load I think. Perhaps when floppy is initialized it needs some processing time to populate the keys and values in RAM?

So the solution in my case, have to do some more testing but looks really promissing, is adding 500ms pause before the other workflow steps will run.

Just curious as to your setup, as i rarely have sync issues with Floppies.

For Floppy values that you use as conditionals, do you use the values stored in their RAM or values in Storage?

Thanks so much for the work on this @keith . Sorry if this is explained somwhere – I’ve looked but can’t find it.
I"m trying to do the basic sort on a field’s subfield list but I want to filter before counting.
My RG is Users. Users have a list of userMilestones. I want to sort on the userMilestones whose Due Date is < current date.
Why doesn’t this work:
image
Thanks
Fred

Hey @prograds, well the issue checker will tell you. This field accepts a list of numbers. So your expression must not resolve to a list of numbers yet.

Looking at the error from the issue checker will tell you what the expression currently resolves to.

Floppy does not have an action for sorting by other types at present. However, you can use List Shifter to sort some list by some other list (of number, text, or date type).

Somewhere I may have a video showing that, although I may not. Here’s a relevant post though:

Also, this post has a link to another post that includes a link to a 3rd party video about List Shifter’s SORT action;

Hope this helps!

Thanks @keith. I was trying List Shifter and then came over to Floppy hoping it’d be easier.
That expression does in fact spit out the accurate number when I use it to display the number of overdue milestones in the RG. See the red Milestone’s Overdue area? That comes from
image

When I use the inspector I get a count of the total userMilestones.

Are you sure that Floppy is capable of evaluating that expression: the RG’s list of Users: each item’s userMilestones:count ???

The userMilestones is definitely a list field on the User type.

Thanks so much for your help.

Well, you’re kind of going in circles here. If you are not counting fields in some list that has the field you want to sort on, you’ll probably need to run Count/Sort twice: first to get the actual list of counts from the “other” list (not sorting) and store it somewhere. Then you’ll have to run Count/Sort again using the result you obtain in the first run as the custom count.

Also, @prograds, if you haven’t seen my video on this feature (wherein I describe the reason for the behavior you see), please go watch this;

2 Likes

I use Keys found in storage. I do not see a RAM option for this in the list so I guess it is my only option. If not let me know and I will test that as well.

Also, my case might be a bit more specific. Presenting a value from a floppy will work fine even when the delay is 100ms or more. But if you need to run a workflow on initialization you need to have access to the values at once or else the workflow will not run or will run when it should not.

I *think* your situation is similar to what I found myself the other day. The solution to my problem was to move away from floppy is initialized to do when.... So it looks like something like this:

Do everything when (it’s looong condition, let me break it down in parts):

  • page url… // detects if this reusable is even visible on the screen (yes, I wish Bubble had a better way, but…)
  • FloppyA is initialized
  • FloppyB is initialized
  • FloppyC is initialized
  • FloppyA RAM List count of items > 0
  • FloppyB RAM List count of items > 0
  • FloppyC RAM List count of items > 0

The count of items parts of the expression ensures that the Floppy has some value before it even starts calculating because my calculations use portions of each Floppy’s RAM List.


* - yes, you probably don’t need initialized in the conditions since the count of items conditions probably “contains” the initialized ones.


I believe this is Dante’s definition of Javascript’s inferno.

1 Like

I do want to point out that it’s good practice to use values in a Floppy’s RAM state for workflows. @keith did point this out in one of his videos.

Hmm I don’t see why you would need to check if a key exists versus if that key has a value (or not). I have something similar setup and all i do is check if a key has value(s).

I’ve been using Floppy since release and I’ve come to rely on it’s features alot. Even more so now with ListShifter migrated over. One thing I’ve come to realize is I tend to overcomplicate things because of it.

For example, I would store data in storage and then create complex workflows to keep that data in sync. When it was actually easier to just create a new DB type to store an index and keep that index updated in the backend.

For me using Floppy is to achieve either faster client side workflows (UX) or to save on WU. Sometimes not using storage is a better option.

As a note i recommend using Floppy expression watchers as triggers.

1 Like

Is there a way to know which item was dragged?

Also, the Floppy A Removed RAM List Via User Drag/Drop is not firing for me, Floppy version 1.9.56
Neither is the Floppy A Updated RAM List Values Via User Drag/Drop (Any Change) when an item is removed.

Thanks for sharing! In my case this would not work as want to check if a value is stored local and if not, run the workflow.

I am testing how much I can off load to Floppy, meaning I need less DB calls, better performance and possible offline capabilities. In order to use data from floppy in critical workflows, I need to make sure the data is there to begin with. And since the app cannot control what the user does with, in essence the user owned browser DB, I want to figure out how to make it still robust in an event they the user deletes or empties browser data.

So I setup keys and values in indexeddb and try to figure out how to make it so robust that I can use indexeddb as the main source to look at when running workflows.

Doesn’t matter, in both cases the expression will run because if the data is not loaded into floppy the key does not exist and the value is empty.

I understand if you use floppy for more “simple” storage needs my issue is not a problem. I just like the plugin so much that I try how far I can stretch it and how much I can offload to local storage.

@keith Just wanted to check on this. Really want to use this plugin!

Related to this reply to @app11: To be clear, the browser storage interface returns null (in Bubble, “empty”) if you attempt to read a key that doesn’t exist. So an empty/null key is the same thing as a key that does not exist. So, Floppy cleans up a key (removes the key) if you set it to an empty value. These are the same thing and so that’s why Floppy does that for you.

However, there is one subtlety: We can “see” what keys are in browser storage using Object.entries() and Floppy implements this. There’s an output for “Keys Found in Storage” which returns a list of key names (text values) that we see on whatever storage object you’re using (session, local, indexedDB). It is possible to have a key with a null value and, if such a key exists you would see its name in that list.

This feature (“Keys found in storage”) is primarily a programming/debugging tool intended for the Bubble programmer and not generally useful in any other way (at least, I can’t really imagine how this would be useful programmatically… it’s really just an easy way to see what keys are present without having to look at the application tab in devtools).

1 Like

Does the floppy RAM function the same as filtering a RG or state and using that as a data source? If I was trying to display a list of 10,000 items to a user which varies by user and user type as well as the data type, what would be the best way to Floppyize it?

Also, Is there a reason that you do not use the sorted or filtered at the end of a floppy list in your videos? It appears you reset the list each time a user action is made instead of adding on a :Filtered or :sort. What is the reasoning for this?

Hey @dbom009, I’m not sure I really understand your questions. A Bubble list is a Bubble list. Any list held in one of Floppy’s exposed states is just like any other Bubble list. You can of course refer to such a list and :filter or :sort it. (But just like any other Bubble list, such expressions don’t change the original list, they return to you a filtered or sorted version of that list.)

As for the first part of your question, Floppy can be used to store a list of Things in browser storage. If you assemble such a list and store it locally, this could potentially be used to reduce WU consumption if the results don’t need to be refreshed via a Search. But note that Things exist only in the context of the database and are not actually serializable except in the sense that we can get their Unique IDs (which for all intents and purposes are the Things in question).

So what this means is that if we were to store a list of Things (let’s say a list of Things [X, Y, Z]) using Floppy and then, on some other page load, Floppy retrieves it, what happens is that Things X, Y, and Z appear at Floppy’s List Values (Storage) output. They are rehydrated from their unique IDs into the Things themselves.

This of course involves a database action (the individual Things must be retrieved from the database to reconstitute them), but a Search is not being conducted, we already know which exact Things we want. Presumably, this is lower cost than Search (but by how much I am unsure). YMMV, as in all cases.

1 Like

@keith Thank you for getting back to me. I guess there isn’t really much out then then to speed up large database filtering. I just was wondering if :filtering a floppy list would be any or at all easier on the capacity of the application.

The application I am working on say has 5000 different products and some user types see some and other user types see others. They are then broken out in numerous statuses. My goal was that maybe saving the floppy list to local storage and filtering that list would prevent having to run the search on bubble’s end and hopefully reduce some capacity usage.

Hey @ankur1, at present when configured for repeating group drag/drop, Floppy does not expose specific events except when dragging finishes. So, it doesn’t expose which item is being dragged. What you do get is triggered events when drag/drop caused a state change in the RAM List (Added RAM List Via User Drag/Drop, Removed RAM List Via User Drag/Drop, Sorted RAM List Via User Drag/Drop).

The rationale is that there’s not much (if any) reason to need this because Floppy handles all of the details about dragging and dropping internally. That is:

  1. If the user (either intentionally or accidentally) starts dragging but then aborts without changing the RAM List, we don’t care. Nothing changed from our perspective.
  2. If the user moves an item from one RG to another RG group, the originating RAM List Floppy will get the “Removed RAM List” event, and the receiving RAM List Floppy will get the “Added RAM List” event. It’s unclear to me why we would need to know what item moved? (But explain your use case.) The interaction is over and both RAM Lists have been updated.
  3. If the user moves an item within a single RG, that Floppy gets the “Sorted RAM List Via User Drag/Drop” event. Again, why does it matter what item moved? The interaction is over and the RAM List has been updated.
  4. Floppy lets you style the “ghost” item as much as you want via CSS. (We can’t actually do this in Bubble itself as this DOM object doesn’t exist as far as Bubble is concerned.)

Now, if Bubble’s triggered events let us pass a value along with the event, I could see sending the item that moved with that event, but again I’m not sure why this would ever be necessary. (If I were to implement this, we’d need to have an output that presents the item that moved and I really hate that interface.)

Can you explain more why you need to know what item the user moved? (Keep in mind, if the drag/drop results in the list being sorted or changed, all the items moved! So…:man_shrugging:)

1 Like

Hi Keith,

I am working with a list of numbers and it works when I add lines, but when I add a line with the same values ​​it is not displayed

How can I show duplicate items in my repeating group?

Here are some screenshot’s
image

Hope you can help me out :slight_smile: