KendoReact Grid filter and sort does not work after grouping data

131 views Asked by At

After grouping data, the KendoReact Grid filter and sort functions do not work.

Interestingly, if I skip the data grouping step and simply present the ungrouped data, the filter and sort functions work flawlessly.

My goal is to find a solution that enables me to filter and sort grouped data within the KendoReact Grid effectively. Despite extensive searches on the KendoReact website and documentation, I haven't been able to find any relevant source code examples or documentation that address this particular issue.

The Customer.tsx component file returns the grid component.

import { filterBy, groupBy, process } from "@progress/kendo-data-query";
import { Grid, GridColumn, getSelectedState } from "@progress/kendo-react-grid";
import { useCallback, useState } from "react";
import { ColumnMenu } from "./ColumnMenu";
import { setExpandedState, setGroupIds, setSelectedState } from "@progress/kendo-react-data-tools";

const customers = [
    { Id: 1, Name: "data1", Family: "Pack", MobileNumber: "0223366554" },
    { Id: 2, Name: "data2", Family: "Pack", MobileNumber: "0223366554" },
    { Id: 3, Name: "data", Family: "Mi", MobileNumber: "0223366554" },
    { Id: 4, Name: "data", Family: "Help", MobileNumber: "0223366554" },
    { Id: 5, Name: "test", Family: "Friend", MobileNumber: "0223366554" },
    { Id: 6, Name: "test", Family: "Friend", MobileNumber: "0223366554" },
];

const DATA_ITEM_KEY = "Id";
const SELECTED_FIELD = "selected";

const initialGroup: any[] | (() => any[]) = [];
const processWithGroups = (data: any, group: any) => {
    const newDataState = groupBy(data, group);
    setGroupIds({
        data: newDataState,
        group: group,
    });
    return newDataState;
};

const initialState: any = {
    take: 20,
    skip: 0
}

const Customer = () => {
    const [dataState, setDataState] = useState(initialState);
    const [customerSelectedState, setCustomerSelectedState] = useState<any>({});
    const [group, setGroup] = useState(initialGroup);
    
    const [resultState, setResultState] = useState(
        processWithGroups(customers, initialGroup)
    );
    const [collapsedState, setCollapsedState] = useState([]);
    const onGroupChange = useCallback((event: any) => {
        const newDataState = processWithGroups(customers, event.group);
        setGroup(event.group);
        setResultState(newDataState);
    }, []);
    const onExpandChange = useCallback(
        (event: any) => {
        const item = event.dataItem;
        if (item.groupId) {
            const newCollapsedIds: any = !event.value
            ? [...collapsedState, item.groupId]
            : collapsedState.filter((groupId) => groupId !== item.groupId);
            setCollapsedState(newCollapsedIds);
        }
        },
        [collapsedState]
    );

    const onSelectionChange = (event: any) => {
        const newSelectedState = getSelectedState({
            event,
            selectedState: customerSelectedState,
            dataItemKey: DATA_ITEM_KEY,
        });
        setCustomerSelectedState(newSelectedState);
    };

    const onDataStateChange = useCallback(
        (event: any) => {
            setDataState(event.dataState);
        }, [dataState]);

    const expandeedData = setExpandedState({
        data: resultState,
        collapsedIds: collapsedState,
    });

    const selectedData = setSelectedState({
        data: expandeedData,
        selectedState: customerSelectedState,
        dataItemKey: DATA_ITEM_KEY,
        selectedField: SELECTED_FIELD
    });

    const result = process(selectedData, dataState);

    return (
        <Grid dataItemKey={DATA_ITEM_KEY}
              data={result}
              {...dataState}
              selectedField={SELECTED_FIELD}
              selectable={{
                enabled: true,
                drag: false,
                cell: false,
                mode: "single",
              }}
              sortable={true}
              onGroupChange={onGroupChange}
              group={group}
              onExpandChange={onExpandChange}
              expandField="expanded"
              onSelectionChange={onSelectionChange}
              onDataStateChange={onDataStateChange}
              >
            <GridColumn title="Id" field="Id" width="300" columnMenu={ColumnMenu}/>
            <GridColumn title="Name" field="Name" width="300" columnMenu={ColumnMenu}/>
            <GridColumn title="Family" field="Family" width="300" columnMenu={ColumnMenu}/>
            <GridColumn title="Mobile Number" field="MobileNumber" width="300" columnMenu={ColumnMenu}/>
        </Grid>
    );
}

export default Customer;

The ColumnMenu.tsx component file returns a column menu, including features like filtering and sorting.

import { GridColumnMenuSort, GridColumnMenuFilter, GridColumnMenuGroup } from '@progress/kendo-react-grid';
export const ColumnMenu = (props: any) => {
  return <div>
        <GridColumnMenuSort {...props} />
        <GridColumnMenuFilter {...props} />
        <GridColumnMenuGroup {...props} />
      </div>;
};

I know result = process(selectedData, dataState) doesn't work correctly. so, what should I do?

1

There are 1 answers

0
MostafaNA On BEST ANSWER

After searching for and testing solutions, I found this link related to my problem, and I was able to solve my problem with it.