Grid sorting same direction when grid is loaded dynamically with ngIf

Hi, I am using Angular 9 and @syncfusion/ej2-angular-grids: ^18.3.52. I faced an issue where the sorting behaviour is unexpected.

When the grid is conditionally loaded, the sorting is always giving the same direction.

Example:

html:

<div *ngIf="isLoaded">
  <ejs-grid
    #grid
    (actionBegin)="actionBegin($event)"
    [allowSorting]="true"
  >
  </ejs-grid>
</div>

ts:

getData() {
    this.isLoaded = false; // if this is added, sorting doesn't work
    setTimeout(() => {
      this.httpService.dummyJsonAllProducts().subscribe(
        (data) => {
          this.products = data.products.map((item) => ({
            id: item.id,
            title: item.title,
            brand: item.brand,
            category: item.category,
            description: item.description,
            price: item.price,
            rating: item.rating
          }));
        },
        (error) => {},
        () => {
          this.isLoaded = true;
          this.data = this.products;
          this.initializeColumn();
        }
      );
    }, 3000);
  }


The issue comes from the binded event of ejs-grid actionBegin​:

  async actionBegin(args) {
    switch (args.requestType) {
      case 'sorting':
        console.log(`${args.columnName}: ${args.direction}`);
        this.getData();
        break;
      default:
        break;
    }
  }

Logs: (can be seen that it's always sorted as Ascending)

Image_1167_1731469164957


Note: I need to call the getData()​ method, which will retrieved a paginated data which is sorted from the previously before frontend received it.


Issue replicated in this repository:  Ronnie0820/angular9 


4 Replies 1 reply marked as answer

RK Ronald Koh November 13, 2024 05:52 AM UTC

Update:

I was able to make it work by replacing *ngIf ​with hidden​ instead. I guess the issue was caused by the html element was rebuild when using *ngIf​, so when the ejs-grid​ reappear, it's in its fresh state where no sorting is applied.

If that's the case, I believe binding the sortOptions​ of ejs-grid​ would also works. But for simplicity purpose, I will stick with using hidden​.


Marked as answer

DM Dineshnarasimman Muthu Syncfusion Team November 15, 2024 02:17 PM UTC

Hi ,


We noticed that you are retrieving data from the remote service and binding the data to the grid locally in the getData() method. We also noticed that you have called the getData() method in the actionBegin event when sorting action is trigger. We would like to tell you that when binding the data to the grid as local data, the grid itself will handle the grid actions such as sorting, filtering, grouping etc.,


We have attached sample for your reference.


Sample: https://stackblitz.com/edit/angular-rfyuez-umasvv?file=src%2Fapp.component.ts


Image:




If you expect to send request to API for each grid action. We suggest you to use remote data binding to bind the data in the grid. We have attached documentation regarding remote data binding for your reference.


Remote Data binding using Adaptors: 


In Syncfusion Grid, we have DataManager and different types of adaptors to bind the remote data to the grid and handled the grid actions like sorting, filtering, grouping etc. We have attached the documentation for your reference.


https://ej2.syncfusion.com/angular/documentation/grid/connecting-to-adaptors/url-adaptor


Remote Data Binding using Custom Data Binding Approach:


For Custom data Binding we need to bind the dataSource in result and count format. For every grid actions(such as Filter, Page, etc.,), we have triggered the dataStateChange event and, in that event arguments we have send the corresponding action details(like skip, take, filter field, value, sort direction, etc.,) based on that, you can perform the action in your service and return the data as a result and count object


https://ej2.syncfusion.com/angular/documentation/grid/data-binding/remote-data


Please get back to us for further assistance.


Regards,

Dineshnarasimman M



RK Ronald Koh November 18, 2024 08:25 AM UTC

hi,

Thanks for the reply.

First, I understand that binding the data to grid can make the sorting work. However, what I provide is just a dummy project. In real project, the actualy data return is sorted and paginated, so further sorting on the paginated and sorted data on the grid would be meaningless. In my case, I want to pass the sorting behaviour to my API so it return the sorted & paginated data, that's why I call getData()​ in actionBegin​.

Also, after briefly going through the documentation regarding data remote binding, I think it is not a viable option in my case because complex logic for sorting, paging and filtering is already handled on my backend side for now, and amending changes on the existing API will impact existing application.

Lastly, one issue I face is when I use hidden ​to resolve my sorting issue is that when the grid is initially displayed, it is blank, even though it has data loaded after inspecting. This issue was finally resolve by adding this.grid.refresh()​ after the boolean that is hiding the grid toggled, but I am unsure why refreshing the grid fix the issue

Image_8061_1731918266713




DM Dineshnarasimman Muthu Syncfusion Team November 22, 2024 02:35 PM UTC

Hi,


By reviewing your query, it seems you are rendering data from Server using API calls. Upon performing the grid action like sorting, pagination and filtering, you have handled your own custom logic in the server side and returning the data to the grid using the this.getData() method.


To handle the grid action like sorting, filtering, paging etc, by your own custom logic, in grid we have custom data binding approach.


In custom data binding,  you need to bind the response data(Grid data) returned from your server using this.getData(), as an object of result(JSON data source) and count(Total data count) properties and set it to the Grid’s dataSource property.


In the provide code information, you have called the this.getData() method in the ngOnInit() method and to perform sorting you have called the this.getData() method in the actionBegin event. We would like to tell you that calling the service in actionBegin event is not a proper way.


By binding the dataSource of grid in the result and count, the ‘dataStateChange’ event will be triggered with corresponding query for every Grid action performed like Paging, Sorting and Filtering. We would like to tell you that instead of calling the this.getData() in the actionBegin() event, call the this.getData() in the dataStateChange event based on the state from the dataStateChange event, perform the data operation in the server side and return the data in result and count format.


You can handled use your own customized code for the server side handling but return the data in result and count format. As the dataStateChange event triggers for every grid action, you can call the service and perform the operations based on the state.action.


Note: The `dataStateChange` event will not be triggered during the initial rendering. If you want the grid to display records, you can call the this.getData() in the ngOnInit.


Custom binding documentation: https://ej2.syncfusion.com/angular/documentation/grid/observables/#observables


For initial rendering:

   

   Here for initial rendering the skip and take values should be set manually and sent to the server.

 



Sorting:


  For performing the sorting the grid requires the details of columns to be sorted and the direction of the sort along with the paging details.




Filtering:

On performing a filtering action the `dataStateChange` event will be triggered and you can get the below referred arguments in the event. Using this you can handle the filter operation in your service.





Please let us know if you need any further assistance.


Regards,

Dineshnarasimman M


Loader.
Up arrow icon