Giter VIP home page Giter VIP logo

Comments (12)

inovua-admin avatar inovua-admin commented on May 29, 2024

Thanks for raising this.
You could try to use setItemAt or setItemPropertyAt to update the dataSource - since onEditComplete has the info you need to do the update. Please let us know how this goes - and if you have any issue, it would help to have a code sample to better understand what you are trying to do. Thanks

from reactdatagrid.

offirgolan avatar offirgolan commented on May 29, 2024

setItemAt would work for single edits which is great but there are still some other concerns that would be solved if the data source was truly controlled:

  1. External changes to the data (e.g. apollo cache updates, websocket events, etc)
  2. Needing to share the entire data set with multiple tables, graphs, etc.

You could potentially add a setItems method but that would still not be very ideal since we would constantly need to keep the internal data source in sync with the other one (e.g. apollo cache).

Alternatively you can support an object like dataSource which has the following structure:

{
  data: [],
  getData: () => []
}

This would be an additive change to the API without needing a major version bump.

from reactdatagrid.

inovua-admin avatar inovua-admin commented on May 29, 2024

Not sure I fully follow your proposal - can you clarify please?
You're suggesting we add an API method to retrieve the currently loaded dataSource? Something like https://reactdatagrid.io/docs/api-reference#method-getItemAt but to retrieve the whole data the grid stores internally?
Or are you proposing the dataSource prop accepts a different shape or returns a different object when it's a function?

from reactdatagrid.

offirgolan avatar offirgolan commented on May 29, 2024

Im proposing something like the following:

const columns = [...];

const App = () => {
  const [data, setData] = useState([]);
  const [count, setCount] = useState(0);
  const [loading, setLoading] = useState(false);

  const dataSource = useMemo(() => ({
    data,
    count,
    loadData: ({ skip, sortInfo, limit }) => {
  return fetch(DATASET_URL + '?skip=' + skip + '&limit=' + limit + '&sortInfo='+JSON.stringify(sortInfo))
    .then(response => {
      const totalCount = response.headers.get('X-Total-Count');
      response.json().then((data) => {
        setData(prevData => [...prevData, ...data]);
        setCount(parseInt(totalCount));
      });
    })
}
  }), [data, count])

  return (
    <div>
      <h3>Live pagination example - infinite loading, 50 per page</h3>
      <ReactDataGrid
        idProperty="id"
        style={gridStyle}
        columns={columns}
        pagination
        livePagination
        dataSource={dataSource}
        onLoadingChange={setLoading}
      />
    </div>
  );
}

This is just a proposal, I'm sure there are gonna be some other edge cases but doing something like that gives us full control of the data.

from reactdatagrid.

offirgolan avatar offirgolan commented on May 29, 2024

Hi, following up on this since I was able to get this sort of working via bi-directional syncing the internal data source to local state. Unfortunately, the only way to do that is via onLoadingChange.

const dataSource: TypeDataSource = async ({ skip, limit }) => {
  return {
    data: await fetchMockData({ skip, limit }),
    count: 1000
  };
};

const SyncedDataSource = () => {
  const [data, setData] = useState<any[]>([]);
  const [count, setCount] = useState<number>(0);
  const [loading, setLoading] = useState(false);
  const [
    gridRef,
    setGridRef
  ] = useState<MutableRefObject<TypeComputedProps | null> | null>(null);

  useEffect(() => {
    if (gridRef?.current && !isEqual(data, gridRef.current.data)) {
      gridRef.current.setOriginalData(data);
    }
  }, [gridRef, data]);

  return (
    <>
      <Box padding="space1" display="flex" alignItems="center" gap="space1">
        <SecondaryButton
          onClick={() => {
            setData((prevData) => prevData.slice(1, prevData.length));
          }}
        >
          Delete First Row (External)
        </SecondaryButton>
        <SecondaryButton
          onClick={() => {
            setData((prevData) => {
              const [first, ...rest] = prevData;

              return [{ ...first, title: uniqueId('Edit ') }, ...rest];
            });
          }}
        >
          Edit First Row (External)
        </SecondaryButton>
        <SecondaryButton
          onClick={() => {
            gridRef?.current?.setOriginalData([]);
            gridRef?.current?.setSkip?.(0);
          }}
        >
          Reset
        </SecondaryButton>
        <Box flex={1}>
          <Text align="right" bold>
            Showing {data.length} out of {count} Records
          </Text>
        </Box>
      </Box>
      <ReactDataGrid
        onReady={setGridRef}
        columns={columns}
        dataSource={dataSource}
        loading={loading}
        onLoadingChange={(loading: boolean) => {
          if (gridRef?.current && !loading) {
            setData(gridRef.current.data);
            setCount(gridRef.current.count);
          }

          setLoading(loading);
        }}
        pagination
        livePagination
      />
    </>
  );
};

I think this solution is OK but depending on the onLoadChange callback for data synchronization isn't very intuitive. Another possible solution (if you don't want to go the controlled data source way in my comment above), adding an onDataSourceChange callback would be a good enough interim solution.

<ReactDataGrid
  onReady={setGridRef}
  columns={columns}
  dataSource={dataSource}
  loading={loading}
  onLoadingChange={setLoading}
  onDataSourceChange={({ data, count }) => {
    setData(data);
    setCount(count);
  }}
  pagination
  livePagination
/>

from reactdatagrid.

inovua-admin avatar inovua-admin commented on May 29, 2024

Glad to hear you managed to find a solution!
I think an even better solution would be to just pass the current data array to the dataSource prop.
So besides of having access to skip, limit, etc, you will also have access to data

const dataSource = ({skip, limit, data }) => {
 return fetch(...).json().then(newData => {
    console.log('full data will be', [...data, ...newData])
    return newData
 })
}

<DataGrid dataSource={dataSource} />

from reactdatagrid.

offirgolan avatar offirgolan commented on May 29, 2024

I like that idea as well. I do have 1 question:

If I load 3 pages and data has 60 records in it. If I re-sort the table, data should be an empty array then correct?

from reactdatagrid.

inovua-admin avatar inovua-admin commented on May 29, 2024

Yes, sorting should trigger a full reload of the datasource, so it will reset skip to 0.
Additionally, we have scrollTopOnSort=true, which is what you want most of the time

from reactdatagrid.

offirgolan avatar offirgolan commented on May 29, 2024

Thinking more about this, your proposed solution wouldn't solve the case where the data was manipulated via setItemAt or setItemPropertyAt. Something like onDataSourceChange would better solve this use case.

from reactdatagrid.

inovua-admin avatar inovua-admin commented on May 29, 2024

with v4.0.23 we added the currentData property (array) to the object that is being passed in to the dataSource function

from reactdatagrid.

inovua-admin avatar inovua-admin commented on May 29, 2024

the currentData array does include the items changed via setItemAt and setItemPropertyAt

from reactdatagrid.

future-mine avatar future-mine commented on May 29, 2024

So pagination is working?
I am using community version.

  const dataSource = async ({ skip, limit }) => {
    const searchCriteria = {
      page: skip / limit + 1,
      pageSize: limit
    }
    const data = await apiClient.post(
      "Right/GetPagedRecords",
      searchCriteria
    )
    const result = {
      data: data.data,
      count: data.totalRecords
    };
    console.log('result=================', result)
    return result
  };

This is dataSource
image

The count is 22 but it shows 10.
Now sure what is happening.

from reactdatagrid.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.