Refreshing Repeating Group Data w/o Refreshing Page

I think this matter deserves its own topic: Like many, I am making a native app and using show/hide groups to emulate pages. I cannot refresh the page, without having the user have to log-in again…so, I need to refresh the data (derived via API) inside a repeating group without refreshing the page.

In the “page” in question (i.e. the group the reveals the RG in the native app), I have a repeating group that pulls items from an API-accessable database (i.e. inventory items) and lists them in the RG. If a user wants to request an item in a repeating group cell, they hit the “request” button inside the cell and the list is then updated to show only inventory that the user hasn’t requested. This would work absolutely fine if I wasn’t building a native mobile app, but because I am designing a native mobile app, I cannot refresh the page and currently I am attempting to use “display list” unsuccessfully:


Oddly, the workflow works great the first time it is run, but ONLY once. Subsequently, when I hit the button on another item listed in the repeating group…it doesn’t ‘refresh’ at all, although it does successfully update my database via API (which I can clearly see by refreshing the page). No matter what item I hit from here on, the repeating group doesn’t refresh but the database being accessed via API is in fact updated via POST every time. @mishav has suggested a possible cause may be that ‘workflow actions attempting to overwrite the data source again, but with the same definition they’ve already overwritten it with, so from a reactive point of view, nothing has changed so a refresh is not needed.’

After working at this for days, I have tried using a counter under User in Bubble’s database (adding +1 to the “user_counter” each time the query is made. Using custom states, this allows me to switch between two different workflows (use one workflow when “user_counter” is an even number, and use the other workflow when user_counter is an odd number)…each one making the query to my database service. Alas, it still does not refresh the data!

I saw that @natedogg has a free ticker tutorial on Codeless Academy which repopulates info in a repeating group, but I’m not sure that his news is actually updated until the user logs out and back in again. Mirroring the same technique, I’ve also made it so that my repeating group makes the API call with constantly changing search parameters (I used the “until # Current User’s request_counter” so that the parameters of the call are always changing)…still nothing. Does anyone have a successful workaround for this?

Up to this point, the only workaround I have found is to create a new Thing labeled “inventory” with a field type for each item (i.e. “item1”, “item2”, “item3”, “item4”, “item5”, etc. etc etc up to “item100”). I then use a workflow to run the API query and update items each time the user loads the “inventory page” (i.e. the shape containing the inventory elements). It works…but it is definitely a hack.

This seems extremely inefficient, so I’m hoping we can come up with a better solution as a community.

1 Like

Data Structure
The names of each field (columns) in the data type (table) suggests that they should instead be entries (rows), for example:

Thing: Inventory
field: ItemName
field: QtyInStock

Refreshing
Why do you think this is enabling the refresh of the repeating group (RG), i.e. triggering the rerun of the API query? How is the inventory linked in with the RG?

Great that you have found a workaround!

Check out the tutorial that recreates the yelp app. It sounds like it so

You can also initiate a search in the workflow and put the result in the rg without refreshing.

Think of every workflow as a potential refresh.

I just replicated the structure of this app (which calls on Bubble’s internal storage (i.e. Things") instead of calling a third party API…herein lies the issue. Searching a Bubble Thing does work, but since my data is coming from an external service…I have to import the information into a Thing first, and then use the RG to draw from that newly created Thing (lets call it “Inventory List”). The current issue with this approach is that the import stores all of the inventory into item#1 of the Bubble Thing “Invetory List”.

Example From My App: my third party database lists three books as separate item #s (item#1=“Great Gatsby”, item#2=“Hitchhikers Guide To Galaxy”, item#3=“Tao Te Ching”), but when imported via the workflow action “create a thing”… Bubble stores all the books in item#1 of the thing “Inventory List” (i.e. Inventory List’s item#1 =“Great Gatsyby, Hitchikers Guide To Galaxy, Tao Te Ching”…item#2=[empty]…item#3=[empty]). There is no way to split up all of the books into separate item #s inside of a Bubble Thing.

Attempting to work within this limitation, I am now working on building a repeating group that will display a number of cells equivalent to the number of commas inside of “Inventory List” Thing’s item#1 (i.e. the Bubble Thing that imported my book list from the 3’rd party Database). I’ll have to use some kind of mathematical function (ex. a counter starting at a number equal to the # of commas inside Invetory List’s item#1) to display hidden fields until the counter reaches zero…when the counter reaches zero, the RG will have no more cells. Inside each of the cells of that RG, I can then have a visible text box that utilizes ‘dynamic data’ to display text from an API call to item#X of my 3’rd party DB (i.e. ‘X’ being the counter’s current #) to display all of the books in seperate cells of the RG. Instead of making one API call to display the RG data…there are now as many API calls as there are cells inside of the RG (each cell makes an API call to display dynmic data inside of the visible text box)…the problem is that my third party service only allows 10 api calls per second, which effectively makes this solution useless.

I hope this description makes sense (let me know if not and I’ll revise it). There has to be an effective solution to using a third party DB (like Google Sheets), importing it into a Bubble Thing, and having a constantly up-to-date RG inside of the Bubble App. Any ideas?

Hey @supernaturally, I have another clue …

Using the DB Connector Plugin, I was able to have two workflow actions to load the entire query result as a list of records into a custom state.

Then a repeating group using the custom state as a data source.

Then reloading from the external database was just a matter of running the workflow actions again.

(@victoria-williams might be interested in this technique. )

I’ll see if the concept can be applied to an API data source.

Edit: using random.org as a data source, it only reloaded from the API if I altered the value of one of the parameters to the API - in this case, inside the JSON body.

The good news is, putting in a dummy parameter that is not used by the API works fine, and tricks Bubble into resending the request if the parameter is different to the previous request.

Edit2: Even gooder news, altering the parameter is enough to reload from the API even if it is directly to the repeating group’s data source (without needing to store into a custom state).

3 Likes

I ended up using a custom state, as you suggested. This was my process:

  • Create a user field called “counter” that is increased by 1 every time the “request” button is hit
  • Then, I created two workflows to determine whether the counter is odd or even (this allows me to switch between two workflows so that I can make two separate requests to the API)
  • I changed the Repeating Group data to be set to “custom state = state_success”.
  • Under each of the two workflows (the one that determines if counter is an odd # or the one that determines if the counter # is even), I inserted a condition that would query the counter number.
  • Because the counter number changes each time, the API call is different under each workflow
  • After setting the custom state to a different under each workflow user the counter, I choose to “display list” in order to refresh the RG with the updated inventory.

and…SUCCESS! Well done @mishav!!!

I’m thinking that I may not even need two different custom states (probably can just query the API using the counter in one shot), but for now I will keep both workflows (for odd and even #s) as it will probably be useful as I progress through building this app. Thanks again, incredible community collaboration going on here!

EDIT: Wow, all I had to do was incorporate the user counter into the API call when setting the data source to the original API call through API Connector…much, much easier. It looks like the parameters have to be changed every single time with a dummy mechanism, as @mishav pointed out. Very happy about making progress here.

5 Likes

Nicely done, @supernaturally. : )

Because it just needs changing each time, a boolean yes/no would be sufficient instead of a counter.

To flip the value, set it’s new value to: element's state is no

To put into the API call: element's state :formatted as text, put whichever text values for yes or no.

On the other hand, the counter probably looks neater on the API call. Choices, choices : )

Edit: I challenge you to work out how to use a number value 0 or 1 and flip it in one workflow action. Hint, once you start entering a number into the editor, it won’t let you use any expressions, and you have to start over with a new workflow action.

1 Like

@supernaturally I have the same problem although in my case im not storing anything in the database. I’m populating a repeating group with a GET through the API connector. And then using the drag-and-drop element to reorder with a POST call via the API the repeating group but it doesn’t matter what I do as a conclusion to that process the repeating group will not refresh. It will only display the re-ordered group correctly on an entire page refresh. As you come across the solution when there isn’t actually anything to reorder in the database and this is done purely on API calls?

Can you explain how the POST call is affecting the RG data source?

I’ve got GET calls, in a workflow action, to refresh by adding a header containing current date/time milliseconds.

I’m unclear as to how this was resolved. I’m having similar issue. I’m calling the SQL Connector to populate a dropdown when the page loads. Based on the selection of the dropdown, a Repeating Group (RG) is filled through another SQL Connector. The user can then click a delete record button within the RG. I would like the RG to refresh (calling the SQL Connector query to reload the records now that one record has been deleted), but can’t seem to get a workflow to make this happen.

The refresh happens when Bubble sees that the query with its parameters has changed.

Try adding a parameter to the query, retrieving the value from a custom state or a group. Then on the workflow action, set the value to current time extract unix milliseconds, which ensures that the parameter is now different.

You may be able to get it to work without passing the parameter into the query itself. If it does need to be sent, try structuring the query so that the parameter is harmless.

@mishav, I added a parameter to the Query parameter list (bubble), and added it as an optional parameter to my stored proc.

I also added the current time extract unix milliseconds to the call

But it still does not refresh the RG.

Am I still missing something?

Nearly there … the current date/time gives a snapshot of the time, and doesn’t auto refresh. You can see this if you put it in a text field on the page.

You want to pass it a value that gets set by a workflow action, so a custom state or a group’s value.

@mishav, Still no luck. I must be missing something. I created a workflow state that gets set to the unix milli time. I am setting it in the workflow that deletes a line in the RG that I am needing to refresh.

I must still not be putting things in the right place or something. Spent many hours playing with this.

Ah, if you’re setting the RG data source from a workflow action, you won’t need to store the current date/time, just pass it, as it will be dynamic from an action step.

Some things to try …

  • Check in the server logs for the query parameters used, and for when the query was sent.
  • Check in the debugger, step through the workflow actions and look at the query parameters and results.
  • For the RG to refresh from a workflow action, you may need the RG data source to be empty and only set it from workflow actions.

@mishav, that did it, thanks! I removed the RG data source and only set it in workflows. I did need to keep the Unix milli parameter. But works now. Thanks you so much. Was ready to scrap all this out of frustration.

If I may add one more issue that I can’t figure out, that is somewhat related…

I have a dropdown that loads a data set (open timesheets) from the SQL connector. It displays the date and hours from the records it returns to the dropdown. I then populate the RG we have been discussing with records from another sql connector query. This works (and refreshes - thanks to your help) fine. BUT, I would like to requery the SQL connector (via workflow is fine) to repopulate the dropdown (open timesheets) when the user adds or deletes a line in the RG. However, I want to keep the selection the user picked in the dropdown as the selected item in the dropdown (and hence the RG that feeds off it’s value). I could save the state, but not sure what to do with it.

1 Like

Great you got the refresh happening!

This might work …

Set the “default value” to a custom state. At the time of refresh, set the selection into the custom state, then reset the dropdown, for example by enclosing it in a group and reset the group.

Unable to make this work. I like the idea of saving and resetting to a state, but don’t have the option to save the index and end up recreating the dropdown value selected in a second behind the scenes field, which I then can save to a state. But the Default does not let me set that state as a default (it comes up red).

Still in need of a solution. There should be some easy way to accomplish this.

Would this work … I used a group’s value instead of a custom state, a state could work the same.

app editor
app runtime