Try to approach it from SQL perspective:
- by grouping you are able to get the keys, exactly, and some aggregate values
- by using original filter you used for group and extending it with group keys (original filter and group keys matches) you actually load the data for the given group.
This is how our grouping grid works in angular telerik kendo (they have a nice toOdataString impl. which I also extended: https://github.com/telerik/kendo-angular/issues/2102).
This approach ensures a fixed given amount of groups in the grid (total group or 1st level group).
PRO: you see all the groups (or at least N of them)
CONS: if you unfold a group you might end up with too many items; needs lot of extra code and additional calls with special odata queries;
See: http://www.reflection.sk/#portfolios, check screenshot: Universal Plans Services (UPS) Software Bundle (.NET & Angular with KendoUI)
If you take it from UI perspective:
Then the grouping is nothing more than a list of data with priority sort over the grouped field. This is the default kendo grouping grid aproach. So they just sort the data, get a page-size of it then the grouping UX items are added (virtual items in the grid).
This approach ensures that you got a fixed items in the grid, but when you collapse all items, you might have just 1 or even pageSize count of groups (depending if/how many items are in each of the groups). See it here: https://www.telerik.com/kendo-angular-ui/components/grid/grouping/ - actually you'd need paging to be turned off to see the difference.
With items up to a fixed count this approach is the fastest. Just one call per page, but the count of groups is not know in advance (if you collapse them, it might be just 1 or even N where N is pagesize).