Pass a <GridColumn /> from one component to another

1 Answer 463 Views
Grid
David
Top achievements
Rank 1
Iron
Iron
Veteran
David asked on 22 Sep 2021, 02:27 AM

Hi,

I have a reusable component that contains a grid but I would like to be able to pass additional <GridColumn /> definitions from consuming components to the reusable component. I'm not sure of the correct way to do this in Typescript. The best way I've come up with so far is to define props for column(s) before and after the fixed content as follows:

preColumns?: React.ReactNode | undefined;
postColumns?: React.ReactNode | undefined;

however in order for this to work properly the consuming component has to pass an array of <GridColumn /> and set a key on each of them e.g.

postColumns={[
    <GridColumn key="information" title="Information" width={160} cell={cellHelper.getInformationCell} />,
    <GridColumn key="lastUpdatedBy" field="lastUpdatedBy" title="Updated By" width={200} />,
    <GridColumn key="lastUpdatedDatetime" field="lastUpdatedDatetime" title="Updated Date" width={250} format={GlobalHelpers.DatetimeFormatForKendo} />,
]}

The disadvantage of this is having to define a key and also that I can't specify a prop for a single column only. Is there a recommended approach in order to achieve this?

Kind regards,

David

1 Answer, 1 is accepted

Sort by
0
Stefan
Telerik team
answered on 22 Sep 2021, 06:55 AM

Hello, David,

To ensure that we have the full picture, please share an example of this or at least the full conde of how the GridColumn is passed from one component and then used in the other.

In general, if there will be columns passed between components we can suggest keeping the columns in an array with options and passing the columns like objects. Similar to how we have this example setup:

https://www.telerik.com/kendo-react-ui/components/grid/columns/column-menu/#toc-custom-components

Regards,
Stefan
Progress Telerik

Virtual Classroom, the free self-paced technical training that gets you up to speed with Telerik and Kendo UI products quickly just got a fresh new look + new and improved content including a brand new Blazor course! Check it out at https://learn.telerik.com/.

David
Top achievements
Rank 1
Iron
Iron
Veteran
commented on 22 Sep 2021, 07:20 AM | edited

Hi Stefan,

Here is a modified example of the reusable component:

// framework
import { useEffect, useState } from "react";
// redux
import { ICustomEntityViewModel } from "./CustomEntityViewModel";
// kendo
import { Grid, GridColumn } from "@progress/kendo-react-grid";

export default function CustomEntityGrid(props: {
    entities: Array<ICustomEntityViewModel>;    
    preColumns?: React.ReactNode | undefined;
    postColumns?: React.ReactNode | undefined;    
}): React.ReactElement {
    // entity state
    const [gridEntities, setGridEntities] = useState<Array<ICustomEntityViewModel>>(props.entities);

    useEffect(() => {
        setGridEntities(props.entities);
    }, [props.entities]);    
    
    return (
        <Grid resizable navigatable data={gridEntities}>            
            {props.preColumns}
            <GridColumn field="entityField1" title="Field 1" />
            <GridColumn field="entityField2" title="Field 2" />
            <GridColumn field="entityField3" title="Field 3" />
            ...
            {props.postColumns}
        </Grid>
    );
}

And this is how it would be consumed:

<CustomEntityGrid
    entities={vm.entities}    
    preColumns={[
        <GridColumn key="entityField4" field="entityField4" title="Field 4" />,
        <GridColumn key="entityField6" field="entityField6" title="Field 6" cell={getField6Cell} />,
    ]}
    postColumns={[
        <GridColumn key="entityField5" field="entityField5" title="Field 5" cell={getField5Cell} />,
        <GridColumn key="entityField7" field="entityField7" title="Field 7" />,
    ]}
/>
I have also discovered defining a single GridColumn as a prop on a component using a type of React.Element<GridColumnProps> appears to work.
Stefan
Telerik team
commented on 22 Sep 2021, 08:51 AM

Hello, David,

Thank you for the extra details.

I made an example that uses a similar approach and it is working as expected:

https://stackblitz.com/edit/react-8odgo6?file=app/main.tsx

The specific is that the preColumns are an array of columns and we use array spread to set them in the Grid.

David
Top achievements
Rank 1
Iron
Iron
Veteran
commented on 29 Sep 2021, 02:19 AM

Thanks Stefan,

Your approach doesn't resolve the issues with my approach (which also works fine):

  1. I am using Typescript, I was asking what Type I should use on the props of the reusable component that takes in columns as props. It appears as if both React.ReactNode and Array<React.ReactElement<GridColumnProps>> works.
  2. If you don't specify keys on the GridColumn arrays passed in to the reusable component you get the following console warning:
Warning: Each child in a list should have a unique "key" prop.

Check the render method of `App`. See https://reactjs.org/link/warning-keys for more information.
    at KendoReactGridColumn
    at App
This can be seen even in the stackblitz example you posted above. I was looking for guidance on how best to pass multiple GridColumns as props from one component to another. I can't easily pass them as objects either as some have custom cell components. It looks like my best option is to pass them as React.ReactNode and add keys to the GridColumns in the consuming component.
Stefan
Telerik team
commented on 29 Sep 2021, 04:51 AM

Hello, David,

If there is an approach that works well in the application I can recommend keep using it. There is no single way to handle this case, this is why this is done based on the real application setup and requirements.

As a side note, the Grid columns can have a collection of other columns as children (for multi-column headers) the type we use is:

GridColumnProps[] | ReactElement[]

Tags
Grid
Asked by
David
Top achievements
Rank 1
Iron
Iron
Veteran
Answers by
Stefan
Telerik team
Share this question
or