Custom collection list loading indicator best practices

I've got a custom collectionlist that has a state as a source. I update the state using different sql queries depending on the value of a segmented control. This works. However.. the loading is a bit clunky. I use hidden with the value of !query1.isFetching || !query2.isFetching. I've got a gif image that is shown when the queries are fetching. But usually the gif disappears and the collectionview isn't instantly there yet. This can take up another second. Using an iPhone 12, which should be sufficient I would think.

What's a better alternative to make the custom collection list look like it's loading? I know the other lists have this blinking placeholder which does look nicer.

Hey @BobandBill!

Would you mind sharing more details about how you have your collection view set up? Screenshots would be nice!

Is the typical loading animation you're referring to this one?

That's what I'd expect from a collection so I'm curious if there are any clues as to why that isn't displaying for this one in particular :thinking:

Probably because the source is a transformer. And the transformer gets it’s data from a temporary state. The state is updated by a query. I do have that animation I think when I use just a query as the source.

Is there are way to activate the components loading state with js? That could be a solution.

I see, you might try using a JavaScript query instead. You can use await in your code to wait for query triggers. In your case, since you're potentially running two queries you might want something like the Promise.all API:

const queries = [query1.trigger(), query2.trigger()];
const queryResults = await Promise.all(queries);

Since your JavaScript query will wait until they're done before it finishes you'll get the loading animation during that time:

If you'd be open to sharing the exact code you're using for your transformer we might be able to give more specific syntax. But hopefully that gives you some ideas :thinking: Let me know if it raises any questions!

And then I can return queryResults and use this js query as the source? Or can I save it in a temp state and use the temp state as the source?

Got to alter lot. I guess using a temp state isn’t working because it only gets updated after the Promise is finished.

Perhaps it will work if I save the Promise in the temp state. :thinking: I don’t know what activates the loading state of the component. Any idea?

I would return the data you want from the JavaScript query and then pass that directly to the collection, that way it can pick up the loading state from the fact that the JS query is running.

Depending on how you have your logic set up you might want to put the conditional into the JS query as well. For instance, you could do something like

if(yourSegmentedControl.value === "Value 1"){
  return query1.trigger();
}else if(yourSegmentedControl.value === "Value 2"){
  return query2.trigger();
}else{
  return /* some default data */;
}

That way you're not triggering the other query unnecessarily.

Does that seem like it could?

The collection should show that it's loading so long as the JS query you're feeding to it is running, so you can have arbitrarily complex logic in it as well.

Thanks for the example. I’m going to try it out. Right now I have it in a temp state. When I click a button, I set a value to true in the temp state array so that I can display a different icon and disable the button. But if I use the js query as the source, it’s going to be tricky. I can’t simply update the query result without running the query again as far as I know. How would you save/update the state clientside (not in the db) of the individual collection list items? For example.. right now I have the button display a “plus” (+) icon. When clicked, I update the temp state where I saved the data from the query. It will change into a checked icon.(v)

Ahh I see, yea that can be tricky in certain cases and I know I personally have recommended them as a workaround a bunch. My first guess would be to have the query serve as the underlying data for your collection and then have an indexed temp state alongside it that can store icon states, for instance. It's also possible to rerun the JS query but not necessarily have it re-trigger the queries if you add in some additional logic. You can even have the JS query return the temp state value.

I think there are a number of different routes you could potentially take and it will ultimately depend on the full context of your specific app and how you've organized it logically. It sounds like you're doing so already but taking a step back and mapping out the app before you build is a really helpful step with Retool once you've gotten a feel for what's possible.