Remote Fetch with group and sort

Hello,

In Angular application:

- Fetch is done externally - filtering, pagination, multisorting is passed to external system

- I want to implement multi-grouping:
a)  initial grouping is set in grid.groupSettings.columns

b) Problem arise when user can drag&drop columns to the group area (multiple grouping)

I wanted to do it in 'simple' way - and just pass to the Backend grouped columns in sort array (so grouppable columns should be sorted first in proper order) - and returned to Angular Grid in simple manner (results + count) - then grid syncfusion displays proper groups on current page - problems I struggle are:

1) Can I somehow display the total count of group (not in current page, but general) - somehow extend the return as result, conut and countPerGroup?


Tried to find solution in Documentation&Forum, but without any luck.


Please advice and best regards


7 Replies

RO RolJan June 24, 2024 07:25 PM UTC

Additionally I've found a bug:
Steps:
1) Group Column - Ship City

2) Group Column - Ship Name

3) Order by  Customer Id

On this point it's OK (sort array is in above order - 1 -> 2 -> 3)

Then change sorting on any grouped column - and you will see that CustomerId sorting order changed to 2 - and just sorted to 3 (in grid.sortSettings.columns also, not just UI)

https://stackblitz.com/edit/github-7gmi8l?file=src%2Fapp.component.ts,tsconfig.json,package.json



RO RolJan June 27, 2024 11:46 PM UTC

If comes to the bug above - it is causing other issues in application if comes to support multiple sorting&groupping
I debugged the code and seems that  sortModule.updateModel() - does not taking into account grouped columns when multistort is applied



JS Johnson Soundararajan S Syncfusion Team July 1, 2024 11:10 AM UTC

Hi RolJan,

Query 1 : "Display the total grouped record count for each grouped columns"
 

We understand that you want to display the total count of each group in the returned data, and also include the result, count, and countpergroup?
 

Please provide the following details to help us assist you better:


  1. Could you please clarify whether you are using the DataManager for backend grouping functionality, or you have implemented your own custom solution?
  2. Please share your complete grid rendering code along with the associated event, which will help us to understand the databinding used in your sample?


The above-requested details will be very helpful for us to validate the reported query at our end and provide the solution as early as possible.

Query 2 : "Sorting order is changed"

We have reviewed your query and provided sample, and the sorting order is updated based on the recently clicked columns.


We have created a sample that includes a sort comparer based on your specifications. The functionality is working as expected. The newly sorted column order is determined by the columns that were previously sorted.

Please refer to the below sample for more information.

Sample : Syncfusion-content - Ej2 Angular Docs (forked) - StackBlitz

Please provide the following details to help us assist you better:
 

  1. Kindly provide us with a detailed explanation of the specific issue you are currently experiencing.
  2. Please share your complete grid rendering code along with the associated event, which will help us understand which custom sorting algorithm you are using in your sample.
  3. Could you please provide a video demonstration to help illustrate this problem? It will help us better understand the problem you are reporting.


The above-requested details will be very helpful for us to validate the reported query at our end and provide the solution as early as possible.


Regards,

Johnson Soundararajan S



RO RolJan August 21, 2024 03:27 PM UTC

Hello,


Regarding 1st point:
Backed is actually a WASM application running in Browser that fetches data in very custom way, but the bottom line of binding that in Grid is following:

export class TableResults {
  count: number;
  result: RowData[];
}
export class TableDataService extends Subject<TableResults> {
public getData(dataRequest: DataRequest): Observable<TableResults>

{
// Here it's calling a service that fetches data from WASM - it does not really matter how - the return object is mapped to:
 map((val) => ({
        count: val.total,
        result: val.rows,
// Here I want to save somewhere groupsCount object/map/array?
      }))
}
}



Then in component
    this.observableData$ = this.tableDataService;

And in Html
    [dataSource]="observableData$ | async"


So all of the actions (filtering, sorting, groupping etc.) is done elsewhere - they are paginated and returned only for current page.

For Groupping I would like following behavior:
On BE - 
a) Group results, count per Group, and paginate
On FE - map somehow the groupCount to Grid - so event if X rows of Group is shown - we can see total Group Count




AR Aishwarya Rameshbabu Syncfusion Team August 22, 2024 03:25 PM UTC

Hi RolJan


After reviewing your query and the provided code example, we observed that you are using observables for data binding in the Grid with WASM as the backend. Additionally, you are managing the Grid's data actions, such as filtering, sorting, and grouping, within your service. For grouping, you need to display the total group count instead of the count per page. This can be achieved by setting the property  groupSettings.disablePageWiseAggregates to true. We have created a basic sample based on your requirements. Please refer to the sample, code example, and screenshot below.


App.component.html

  <ejs-grid

    #grid

    [dataSource]="data | async"

    allowPaging="true"

    [editSettings]="editSettings"

    [toolbar]="toolbar"

    [pageSettings]="pageOptions"

    allowSorting="true"

    allowGrouping="true"

    [groupSettings]="groupOptions"

    (created)="created()"

    (dataStateChange)="dataStateChange($event)"

  >

App.component.ts

  public ngOnInit(): void {

    this.editSettings = {

      allowAdding: true,

      allowEditing: true,

      allowDeleting: true,

      mode: 'Batch',

    };

    this.pageOptions = { pageSize: 10, pageCount: 4 };

 

    this.groupOptions = {

      disablePageWiseAggregates: true,

      columns: ['ShipName'],

    };

  }

 

Order.service.ts

 public execute(state: any): void {

    this.getData(state).subscribe((x) => super.next(x));

  }

  protected getData(

    state: DataStateChangeEventArgs

  ): Observable<DataStateChangeEventArgs> {

    let pageQuery = `$skip=${state.skip}&$top=${state.take}`;

    let sortQuery: string = '';

    let filterQuery: String = '';

    this.gridState = state;

// To handle sorting

    if ((state.sorted || []).length) {

      sortQuery =

        `&$orderby=` +

        state.sorted

          .map((obj: Sorts) => {

            return obj.direction === 'descending'

              ? `${obj.name} desc`

              : obj.name;

          })

          .reverse()

          .join(',');

    }

    if (state.where) {

      pageQuery = '';

    }

    return this.http

      .get(

        `${this.BASE_URL}?${pageQuery}${sortQuery}${filterQuery}&$count=true`

      )

      .pipe(map((response: any) => response.json()))

      .pipe(

        map((response: any) => {

          return state.dataSource === undefined

            ? <DataResult>{

                result: this.getResult(response),

                count: parseInt(response['@odata.count'], 10),

              }

            : response['value'];

        })

      )

      .pipe(map((data: any) => data));

  }

  public getResult(response) {

    //  group the column based on the condition

    if (

      this.gridState.group != undefined &&

      (this.gridState.action == undefined ||

        this.gridState.action.rows != undefined)

    ) {

      var json = response['value'];

      this.gridState.group.forEach((element) => {

        // 'DataUtil.group' groups the input data based on the field name

        json = DataUtil.group(json, element);

      });

      return json;

    } else {

      return response['value'];

    }

  }



Sample: T7amew (forked) - StackBlitz


If we misunderstood your requirement, please explain your exact requirement in detail along with providing all the requested information in our previous update.



Regards

Aishwarya R



RO RolJan September 19, 2024 06:52 PM UTC

Thank you for the reply, but the problem in your suggestion is that the response contains all of the data - and in my case  we paginate the data on WASM side (BE) - so it returns only paginated data (so only current page)


My question is -  how I can make it display groupped&paginated results with the infromation from BE about group count (so if on page 1 there 10 rows from one group, but there is >10 items it this group, I expect to see that group size instead of 10)


Best regards,

RJ



AR Aishwarya Rameshbabu Syncfusion Team September 22, 2024 04:13 AM UTC

Hi RolJan,


Based on the provided information, we have observed that you are currently returning only the records for the current page. You wanted to display the group count based on the total records instead of current page records. When the 'disablePageWiseAggregates' option is enabled in the Grid, two requests are made during the grouping action: one to retrieve the grouped data and another to obtain aggregate details and the total item count. This process has already been documented, and we kindly request you to refer to the documentation link provided below. Without returning the entire page record, it is challenging to determine the total group count accurately. Therefore, we recommend handling the server-side request to return the page-wise count appropriately. In the shared example, we have skipped the pageQuery for the second request sent upon grouping when 'disablePageWiseAggregates' is set to true. This will display the group count based on the total records. Please refer to the screenshot and code example below for more detailed information.


Arguments received in the server side for the first request:


Arguments received in the server side for the second request:


Skipping the page query for the second request in server side:



Order.service.ts

 

  protected getData(

    state: DataStateChangeEventArgs

  ): Observable<DataStateChangeEventArgs> {

    debugger;

    let pageQuery = `$skip=${state.skip}&$top=${state.take}`;

    let sortQuery: string = '';

    let filterQuery: String = '';

    this.gridState = state;

    if ((state.sorted || []).length) {

      sortQuery =

        `&$orderby=` +

        state.sorted

          .map((obj: Sorts) => {

            return obj.direction === 'descending'

              ? `${obj.name} desc`

              : obj.name;

          })

          .reverse()

          .join(',');

    }

    if (state.where) {

      pageQuery = '';

    }

    return this.http

      .get(

        `${this.BASE_URL}?${pageQuery}${sortQuery}${filterQuery}&$count=true`

      )

      .pipe(map((response: any) => response.json()))

      .pipe(

        map((response: any) => {

          return state.dataSource === undefined

            ? <DataResult>{

                result: this.getResult(response),

                count: parseInt(response['@odata.count'], 10),

              }

            : response['value'];

        })

      )

      .pipe(map((data: any) => data));

  }

 


Sample: T7amew (forked) - StackBlitz


Documentation Link: group-with-paging



Regards

Aishwarya R


Loader.
Up arrow icon