inovua / reactdatagrid

Empower Your Data with the best React Data Grid there is
https://reactdatagrid.io
Other
3.45k stars 57 forks source link

The server side sorting with remote data source doesn't work. #209

Open AlexanderSokolov1 opened 2 years ago

AlexanderSokolov1 commented 2 years ago

Relevant code or config (reproduced on Remote Sorting example: https://reactdatagrid.io/docs/sorting#controlled-and-uncontrolled-sorting)

import React, { useState, useCallback } from 'react'

import ReactDataGrid from '@inovua/reactdatagrid-enterprise'
import '@inovua/reactdatagrid-enterprise/index.css'

import DATASET_URL from './DATASET_URL'

const gridStyle = { minHeight: 550, marginTop: 10 };

const defaultColumns = [
  { name: 'id', header: 'Id', defaultVisible: false, type: 'number', maxWidth: 40 },
  { name: 'firstName', header: 'First Name', defaultFlex: 2 },
  { name: 'lastName', header: 'Last Name', defaultFlex: 2 },
  { name: 'email', header: 'Email', defaultFlex: 3 }
];

// custom sorting by id
const sort = (d) => {
  var a = d.sort(function (x,y) {return x.id - y.id});
  return a;
};

let tempResult = [];

const App = () => {
  const [columns] = useState(defaultColumns);
  const [sortInfo, setSortInfo] = useState([]);

  const loadData = useCallback(({ skip, limit, sortInfo }) => {
      return fetch(DATASET_URL + '?limit=' + limit)
        .then(response => {
          const totalCount = response.headers.get('X-Total-Count');
          return response.json().then(data => {
            tempResult = sort(data); // emulate some tricky sort on server side
            return { data: tempResult, count: totalCount * 1 };
          })
        });
    }, [sortInfo])

  return (
    <div>
      <h3>Sort with remote data</h3>
      <h4>Please sort by the First Name column</h4>
      <div style={{ height: 80 }}>Should be: {tempResult.map(d => d.firstName).toString()}.</div>

      <ReactDataGrid
        idProperty="id"
        skip={0}
        limit={10}
        style={gridStyle}
        columns={columns}
        dataSource={loadData}
        onSortInfoChange={setSortInfo}
        allowUnsort={false}
      />
    </div>
  )
}

export default () => <App />

What you did: I'm trying to sort data on server side and display it with ReactDataGrid. What happened: The data sorted in controlled mode (by ReactDataGrid instead of server order).

Reproduction repository: see the code snippet above.

Problem description: The server side sorting with remote data source doesn't work.

Suggested solution: Avoid controlled sorting in case of remote data source.

msanli220 commented 2 years ago

When i use server-side sorting i use this function for onSortInfoChange. it worked for me. Hope it helps

    function onOrderChange(value) {
        if ( props.filterParams && !Lodash.isEmpty(value?.name) ) {
            props.filterParams({order: `${value.name} ${value.dir === 1 ? 'asc' : 'desc'}`})
        } else {
            props.filterParams({order: ""});
        }
    }
AlexanderSokolov1 commented 2 years ago

@msanli220, thanks for the response! I didn't find any sorting related improvements/fixes/functionality in the code snippet you provided. Could you share a full example?

Is props.filterParams a function that filter/sort your datasource and updates the dataSource prop of the Grid manually? Does it return Promise of GridDataSource?

Seems I need a way to somehow disable the automatic sorting of the data grid and force it to use my own order (which the server returned), even if it is sorted by a column that is not in the columnset. As you can see from my example, I always sort the data by the Id column but the grid sort it by its columns ignoring remote source order.

Real life problem: I have a date-like column that can displayed in any date format (even a custom one) and it cannot be sorted as a string or a date field. My server knows the real date and can sort it in the correct order. It then creates a view model with a "friendly" date column and returns it to the client side. But the data grid is automatically sort date column (breaking the order that the server returned).

msanli220 commented 2 years ago

@msanli220, thanks for the response! I didn't find any sorting related improvements/fixes/functionality in the code snippet you provided. Could you share a full example?

Is props.filterParams a function that filter/sort your datasource and updates the dataSource prop of the Grid manually? Does it return Promise of GridDataSource?

Seems I need a way to somehow disable the automatic sorting of the data grid and force it to use my own order (which the server returned), even if it is sorted by a column that is not in the columnset. As you can see from my example, I always sort the data by the Id column but the grid sort it by its columns ignoring remote source order.

Real life problem: I have a date-like column that can displayed in any date format (even a custom one) and it cannot be sorted as a string or a date field. My server knows the real date and can sort it in the correct order. It then creates a view model with a "friendly" date column and returns it to the client side. But the data grid is automatically sort date column (breaking the order that the server returned).

you can check my repo link . It has only a reactdatagrid example with server-side rendering.

I use filterParams when any filter value change i update the filter in reducer and send to the server-side.

AlexanderSokolov1 commented 2 years ago

@msanli220 thanks for the repository you provide. Now it's clear. But as I can see from the code, you use array as a DataSource property. So you manually control the datasource of the grid by taking filtering and sorting on your own. In my case I use a remote data source by providing a function that returns Promise: image The documentation says that it's enough for remote sorting on server side: https://reactdatagrid.io/docs/sorting#remote-sorting But seems that the grid ignores the order that the server provides.

msanli220 commented 2 years ago

@AlexanderSokolov1 since i didnt share the backend api i used static source for column part to show the remote filtering mode. Did you add remoteFilter = {true} inside the ReactDataGrid component ? i guess it disables the client-side filters and you can do remote sorting or ordering.

AlexanderSokolov1 commented 2 years ago

@msanli220, yes, I did. I also have a remoteSort={true}.

I wasn't able to provide jsFiddle for this as I didn't get how to simply add the @inovua/reactdatagrid-community package via cdn or unpkg since the repository has no minified bundle (or I just didn't find it). But you can play with my example via this page: https://reactdatagrid.io/docs/sorting#remote-sorting. Just expand the Remote sorting example and copy-paste the code I provided. The remoteSort and remoteFilter have no effect.

msanli220 commented 2 years ago

@AlexanderSokolov1 Oh now i found something hope it helps. I append an injectformatter function to the column part and returned and empty arrow function for sorting( it returns nothing for client side sorting).

 function injectFormatters () {

        return props.columns?.map ( item => {

              return { ...item, sort:()=>{}};

        });
    }

function buildColumns() {
        return [
            ...buildIdColumn(),
            ...injectFormatters(),
        ]
    }
return(<ReactDataGrid
               idProperty="Id"
               columns={buildColumns()}
              dataSource={props.dataSource || []}
              ..... />);
AlexanderSokolov1 commented 2 years ago

@msanli220, yep the workaround works like a charm. Looks like we have to manually set column.sort to an empty function to achieve the server side sorting. Thank you so much for your time and help!

Hope the inovua team will take a look at this issue and provide an elegant solution for a remote data source.