Toolbox Plugin: Sort Repeating Group by Expression's Value

@mishav been using your Toolbox plugin a bunch, thanks much! One use case I can’t figure out.

I have a leaderboard page in my app (RG with leader’s name, leader’s score, sorted ideally by highest score first).

When user loads page, they should see stack ranked list of leaders. Simple, right? :slightly_smiling_face:

Here’s the issue: the “score” is not a stored field, rather it’s a text element that simply display’s an Expression’s value (integer), b/c I need to run some complex calculations to determine ultimate score. So, within the RG’s cell, I’ve dropped 4 Expression elements, each one running a math calculation referencing fields stored on the current cell’s Leader. Then, I have a 5th Expression in the cell that simply sums the values of the other 4 (Expression “Total Score”).

To display this “pseudo-score” for a Leader (“pseudo” b/c value isn’t stored in the db), I use a text element that just displays the “Expression Total Score’s value” for the given cell. The “total score” expression element is within the RG’s current cell, that’s the “rank” for the given leader that the user sees, but I can’t figure out how to sort my RG using this calculated value so that leader with the highest “pseudo-score” shows up at top of list. Nor can I access the Expression to run a workflow that would actually update a current cell’s Leader’s ACTUAL “score” field so that I can simply use the standard “sort RG by…” a stored number field descending.

Any best practice advice here?

1 Like

The usual best practice in Bubble is to precalculate and store the results, so the database search can do the sorting.

If this isn’t practical in your case, you can use List Item Expression to calculate a matching list of scores.

Then use an Expression to use javascript functions to sort the list of scores and return a list of the indices.

Then the display RG can use the list of indices as a source; and refer back to the original search result for the data for each index, and refer to the list of calculated scores for each index.

It can get a bit complex, let me know if you want some specific help for your app : )

would love some help, DM’ing you now!

I’m following this topic. I see that others have asked similar questions. Please share what you learn.

I was wondering @mishav, if it might be worth adding a dedicated built-in function for sorting to the toolbox, or perhaps even a new plugin to sort based on an expression/calculation (not necessarily JS)? Seems to come up as a request often - well, sort of often :slight_smile:

Yes, this would be ideal. For performance reasons, I’m doing some tricks w/ pre-merging data source for my repeating group, so using the list of indices as source will introduce more complexity and potentially regress the performance optimizations.

If I could simply target the value of the Expression within the current cell in the RG to update a field, that would solve it. Then, I could update the the current cell’s parent leader’s Score with the current cell’s expression’s value, and follow best practice for sorting by a stored field as @mishav recommended above.

Interesting idea, @louisadekoya . Something like …

[ data source || sorting expression ]
return the same list of source items in the desired order.

Can you help by listing a few scenarios that it would cover?

I’m not sure I entirely understand what you’re asking @mishav, but I’m thinking of scenarios such as:

  1. The one expressed here by @daniel3, i.e sorting a RG by a calculated field, bearing in mind that the calculation could involve multiple fields, possibly from multiple data types. For example, in one of my apps, I rate users based on activity, which is calculated as shown below. I do not store this rating but calculate it on the fly, as it changes all the time. It would be good to be able to sort a RG of users by this calculation.

Using your template, I think this would be something like:

[ users, tasks || search for each user’s tasks, sum up the activity points on the tasks, divide by the sum of expected points for the activities and express the whole things as a percentage]

  1. Someone else on the forum wanted to sort by the value of a progress bar calculation.

I hope these help. I guess the Bubble team might worry about the potential performance impact of something like this, so I guess that is something to consider, but it would be quite useful I think.

1 Like

It could work along these lines … thinking aloud …

For each item, build up a dataset for each user, i.e. “group by user”, add to the user’s totals.

When all items have been included, report back a list of the sorted totals.

One tricky part is bringing the data back into Bubble, as currently a plugin cannot return a list of objects such as [ { user: John, grand_total: 42 }, { user: Jane, grand_total: 43}, … ].

It could return two lists relating the two aspects of the sorted data; users [ John, Jane, … ] and totals [ 42, 43, … ].

The other tricky part is how to express the sort criteria.

A very layman’s view here, so take with a pinch of salt, but here’s a hack that I once considered but couldn’t quite figure out how to implement. Use 2 RGs. The first includes a JS expression to do the calculation for each row and stores the result in a variable. The second RG uses the first as a source but then sorts by the result variable. It’s probably still subject to the same issues you’ve highlighted but I thought I’d share anyway, in case it sparks something.

By the way, a group_by function would also be very useful - you can get around it by nesting RGs but it would be great to be able to more easily group by and display counts/averages etc.

Sorry, @daniel3, I hope this is not hijacking your thread. Hopefully we’re still on topic :slight_smile:

Thanks for referencing my question; I got a notification :+1:.

@mishav I’ve installed your plugin, but I have not even tried it. See, I am not yet knowledgeable enough in web programming to be able to use it. But I’m poking and prodding.

In the meantime, here’s a screenshot of what it looks like now.

I suspect that if I can’t do it on the fly as you guys are discussing here; there’s probably a hack-around. Create a calculated percentage field to those Fiberhood things and have it update with the new number anytime a new user signs up.

(but I haven’t yet discovered how to do that. I’m new to this world of Bubble and “visual programming”. Conceptually I understand what needs to be done. Mechanically, however,…)

Hi @rico.trevisan, would you send me a message with more details of your app? I’d like to see the RG source definition, and what you are adding to it from the cell to do the calculation.

Possibly a really simple approach might fit most needs … an element that spits out the same item list it is given, but in a sorted order, with the sort function using a value defined much the same way as the current List Item Expression.

@rico.trevisan Can you not simply sort the entire RG by whatever number field value you’re using in the progress bar? This would use standard Bubble functionality, so could be done today.

For example, if the RG is a list of Locations, I’m assuming the Location data type has a field of type=number (let’s call it “Construction Progress,” I don’t know Spanish/Portuguese :slightly_smiling_face:) that you’re using to indicate Progress Bar value, simply add a sort to the RG:

Search for Locations:sorted by Construction Progress descending

1 Like

Thanks!

@daniel3. Portuguese :grin:

That is exactly what I thought! But then my n00b mind almost blue-screened trying to figure out how to do it.
Here’s a short video of what it looks like.

Here’s the current math I do for the progress bar.


After I read an answer by Faye (link) I realized I could make things simpler by adding the User to the Fiberhood’s list of Users and then sorting by that. The next quest will be to figure out how to sort it by that and take into account the number in the NMI field.

In any case, here’s the math I am currently doing for the progress bar (which I have not yet updated since my latest discovery of adding the Users to the Fiberhood’s list of Users).

Thanks! I will send you a private message with more details, but let me share some of those details here to let the hive-mind check my thinking and call me out (please do!) when I’m overcomplicating things!

Here’s a link to the application.


It might be useful to give more context; to explain the problem I’m trying to solve.

Here is how the business works:

  1. Users register
  • We then create a Fiberhood (if there’s enough demand, technical feasibility, etc.)
  • Those active Fiberhoods then “compete” for our attention. And that’s where I would like this list of progress bars to help.
  • First Fiberhood to reach 100%, we build a fiber network there.

I have taken Faye’s answer and applied that to my case. So now, whenever a users registers, he gets immediately added to the Fiberhood’s list of Users.

That allows me to sort by the count of Fiberhood’s list of Users.

The next step is to take into account the NMI number. The NMI is the goal that the Fiberhood needs to reach before we build there.

Would it be best to have it calculated on the fly or not (aka have it saved in the Fiberhood Thing)?



_(Yes, this is the same model made famous by Google Fiber.)_

I think in this case, storing the (user count) / (NMI) as a field in the Fiberhood would make sense, because all the information for this is available when the Fiberhood record is updated.

It would need to be updated when a user is added or removed, or when the NMI is altered.

1 Like

A note on security …

This would not be such a good idea anyway, because the client page can be hacked by the user to update a different set of scores than the user community agrees with.

@louisadekoya for your example, sorting users by their task completion ratio. I think it would be more efficient to store the ratio for the user, so the page would not need to repeat the task searches each time a change happens.

If we still want to do it dynamically, then something like …
list of users; list of tasks;
for each user, calculate across tasks filtered by user.
return list of users sorted by calculated value.

Excellent, thanks!

I think I know how to do that when a new user is added. It would be part of the workflow that happens when the user clicks the button.

To the case when the user is removed or the NMI is altered, I am guessing I will have to update the admin page so that I can change these properties and the workflow that says that anytime those triggers happen, it recalculates the field.

Is there a way to have that workflow run in the background?
Why? Well, I am thinking of the moment when I add our existing user data to Bubble. Do I create a “update all percentage fields” in my admin page that runs that workflow?

Thanks, again! You got my brain churning with ideas which I will try out tonight!
:bear::hugs: (that’s a bearhug, obviously. :wink: )

Thanks @mishav. Are you saying this is already possible with the Toolbox plugin?

Not yet! Or rather, maybe yes with a bit of hacking … hmmm I’ll try something.

1 Like