Our blazing fast Grid component built with pure JavaScript


Post by saurabhdesai »

Hi team Bryntum,

I am trying to implement Server side sorting. Initially when the grid loads i had to show the indicator if the data sent rom the server is sorted by Particular property.So I have given sortAscending as true in column definition on server and performing on

 const sortWay = data.columns.map((ele) => {
    if (ele.hasOwnProperty("sortAscending")) {
      return {
        field: ele.field,
        ascending: ele.sortAscending,
        fn: (recordA, recordB) => {
          
return 1; }, }; } else { return { fn: (recordA, recordB) => { return 1; }, }; } });

sortAscending is the property sent from the server whose value is boolean.

this sortWay array i am assigning to sorters property of store and also i have given custom sorting function to show data as it has came from server and not do the sorting on client side.

Initially this function is gettong called while loading but as i am trying to sort on basis of any column it is not getting called and doing sorting on client side.

Also I tried giving sortParamName but still doing sorting on client side.

  store: {
      sorters: sortWay,
      // sortParamName: "sort",
      // syncDataOnLoad: false,
      // autoLoad: false,
      tree: true,

  listeners: {
    sort: async function (value) {
      console.log("value sorters");
      console.log(value.sorters);

      const sortDirection =
        value.sorters[0].ascending === true ? "asc" : "desc";
      const sortField = value.sorters[0].field;

      const rpt_sort_by = sortField + "/" + sortDirection;
      const response = await authAxios.post(
        "/rpt.SaveCustomization.do?_src=report",
        {
          rpt_sort_by,
          p_rpt_id: id,
        }
      );
      doRefresh(new Date().getTime());
      //server call
    },
  },
},


Above is the store we are using in config.

Can you please guide me that how should i write sorters so that my custom function gets called whenever I do sorting or how should I do to achieve the same?


Post by Animal »

The store just a config object. For the grid to know that it needs to instantiate an AjaxStore when it receives an object, that object needs to contain a readUrl

Screenshot 2022-11-08 at 14.38.38.png
Screenshot 2022-11-08 at 14.38.38.png (208.01 KiB) Viewed 830 times

Post by saurabhdesai »

I am not using readUrl i wanted the control to be with me rather than readUrl . So I am calling in useEffect, fetching data, and providing that data in data props of BryntumGridComponent.

I am asking how I can write those sorters so the custom function gets called every time we sort so that client-side sorting is disabled.


Post by Animal »

I thought you weer trying to implement server side sorting?

That means the data arrives fro the server and gets injected into the client in the correct order, and you do not do sorting in the client. I'm confused by what you are doing.


Post by saurabhdesai »

Yes, we are not sorting on the client side.

The way we are currently implementing it is as sort happens the sort listener gets fired and we post data of sort on the server and then the grid is being refreshed so the row data fetching call is happening again and to restrict sorting on the client side we have written a custom sort function which will just show the value in the order it has arrived. Initially, that function of sorters is getting called but it is not getting called after that when we perform any sorting operation and as a result, the sorting happens on the client.

I hope this clears up your confusion. Please help me with the solution.


Post by Animal »

I do not understand.


Post by saurabhdesai »

Hi,
Let me rephrase the issue for you.

Requirement:

  • While implementing the Bryntum Grid we need to provide the functionality of Sorting.
    The server will always return the correct sorted data and we just need to display these records.
    We want to prevent the Grid to sort the records fetched from server.

Our implementation is as follows:

  • We receive the initial sorting information when the grid is loaded. Now, to display the correct sort direction of the column based on the data received from the server we are using the "sorters" property in the "store".
  • If the user clicks on any column to sort, we are using the "sort" listener and inside this listener, we post the sort information of the column to the server.
  • After a successful request, we re-render the grid to fetch the new sorted records from the server.
  • Since we had clicked on the column to sort it, the Grid itself sorts the records on the client which we do not want to happen.
  • To prevent this, we have assigned a "sortable" function to every column and this function always returns 1 to prevent the client-side sorting. Although this function is executed, it does not prevent the grid to sort the records on it's own.

As can be seen in the screen recording, when we sort the ID column in descending order, the last row which has an empty ID comes at the top. But the server is sending this record in the last position.

The sortable function definition as used in the app:

    const column = {
      ...
      sortable(a, b) {
        return 1;
      },
      ...
    };

Properties related to sorting in the config:

  const config = {
    multiSort: true,

store: {
  sorters: [{"id", "asc"}, ...],
  syncDataOnLoad: false,
  autoLoad: false,

  listeners: {
    sort: async function (value) {
      console.log(value.sorters);
      }
  }
  }

NOTE: We cannot disable the sorting feature of the Bryntum Grid because we are using it to show the correct sort direction and handle the click action.
Also, we are not even using the readUrl in the store.

How should we achieve the above functionality?

Attachments
bryntum-grid--sorting-issue.mov
(8.9 MiB) Downloaded 51 times

Post by alex.l »

If you want to have remote sorting, you don't need to provide local sorters. All you need is to set readUrl that means it is AjaxStore and data will be requested by this URL; and provide sortParamName which means store won't make sorting locally and will request data from the server every time you clicked on column header or do any other action to initiate sorting. all required information about sorting with be sent to server side using parameter defined in sortParamName.
If you provided local methods, it means it is not remote sorting, it is local sorting, since sorters are defined and were called.

https://bryntum.com/docs/grid/api/Core/data/AjaxStore#config-sortParamName
https://bryntum.com/docs/grid/api/Core/data/AjaxStore#config-readUrl

Here is an example how it should be configured and how it works. https://bryntum.com/examples/grid/paged/ Please review the source code and JSON that server sent and get.

All the best,
Alex


Post by saurabhdesai »

As I have told you earlier, we are not using the readUrl property of the ajax Store. We are fetching data and assigning the fetched Data to data props of the Bryntum Grid Component .

We don't want to use readUrl because we want the entire control to be in our hand rather than giving it to readUrl.

So in that, case how can I achieve the solution of the above problem ?


Post by alex.l »

So, this is local sorting then.

Try to use return 0 as a result of sortable

      sortable(a, b) {
        return 1;
      },

It works in my sample. Be aware that I change behaviour only for Name column click, but sorted it by id instead of name, to emulate custom sorting

FYI we have summary feature here https://bryntum.com/docs/scheduler-pro/api/Grid/feature/Summary

const data =  DataGenerator.generateData(50);

let direction = 1;

window.sortData = (direction) => {
        const sortedData = [...data].sort((a, b) => {
            if (direction == 1) {
                return a.id > b.id ? 1 : -1;
            } else {
                return a.id < b.id ? 1 : -1;
            }
        })

    grid.store.data = sortedData;
}


new Grid({

appendTo : 'container',

features : {
    group : false
},

// Headers will ripple on tap in Material theme
ripple : {
    delegate : '.b-grid-header'
},

columns : [
    {
        text   : 'Name',
        field  : 'name',
        flex   : 2,
        editor : {
            type     : 'textfield',
            required : true
        },
        sortable() {
            return 0;
        }
    }, {
        text  : 'Age',
        field : 'age',
        width : 100,
        type  : 'number'
    }, {
        text  : 'City',
        field : 'city',
        flex  : 1
    }, {
        text  : 'Food',
        field : 'food',
        flex  : 1
    }, {
        text     : 'Color (not sortable)',
        field    : 'color',
        flex     : 1,
        sortable : false,
        renderer({ cellElement, value }) {
            // renderer that sets text color = text
            cellElement.style.color = value;
            return value;
        }
    }
],

store : {
    data : data,
    syncDataOnLoad : false,
    listeners: {
        sort() {
            if (direction == 1) {
                direction = -1;
            } else {
                direction = 1;
            }
            sortData(direction);
        }
    }
}
});

All the best,
Alex


Post Reply