I'm using the grid component whose data source is an array of objects with each property is displayed correct. however the property names of object are used as column names despite being explicitly mentioned explicitly.
import React, { useRef, useState } from 'react';
import {
GridComponent, ColumnsDirective, ColumnDirective, Inject,
Resize, Reorder, ColumnChooser,
RowSelectEventArgs,
Toolbar,
RecordDoubleClickEventArgs,
RecordClickEventArgs,
ColumnDragEventArgs,
ResizeArgs,
KeyboardEventArgs
} from '@syncfusion/ej2-react-grids';
import { Pagination } from '@mui/material'
import { ClickEventArgs } from '@syncfusion/ej2-react-buttons';
import { ItemModel } from '@syncfusion/ej2-navigations/src/toolbar/toolbar-model';
import { error, guard, trace } from '../../services/common';
type DataGridPropsType<T> = {
rows: T[],
count: number,
page: number,
size: number,
children?: any,
onSelect?: (data: T) => void,
onAdd?: () => void,
onEdit?: (arg: T) => void,
onDelete?: (arg: T) => void
}
function getToolbarOptions<T>(func: ()=>T, props: DataGridPropsType<T>): (string | ItemModel)[] {
// some code
return toolbarOptions
}
export function DataGrid<T>(props: DataGridPropsType<T>) {
const record = useRef({} as T)
const setCurrent = (arg: T)=> record.current = arg
const getCurrent = () => record.current
const grid = useRef({} as GridComponent | null)
const toolbarOptions = getToolbarOptions(getCurrent, props)
const mod = (props.count??10) % (props.size??10)
const pages = (props.count??10) / (props.size??10) + mod>0?1:0
return (
<>
<GridComponent dataSource={props.rows}
height="400"
gridLines='Both'
allowResizing={true} allowReordering={true} showColumnChooser={true} toolbar={toolbarOptions}
selectedRowIndex={0}
rowSelected={(args: RowSelectEventArgs) => {
const data = args.data as T
setCurrent(data)
props.onSelect?.(data)
}}
recordClick={(args: RecordClickEventArgs)=> {
const data = args.rowData as T
setCurrent(data)
props.onSelect?.(data)
}}
recordDoubleClick={ (args: RecordDoubleClickEventArgs)=>{
const data = args.rowData as T
setCurrent(data)
props.onEdit?.(data)
}}
columnDrop={(arg: ColumnDragEventArgs)=>{
}}
resizeStop={(arg:ResizeArgs)=>{
const col = arg.column
trace(`${col?.field} resized to ${col?.width}`)
}}
keyPressed={(args: KeyboardEventArgs)=>{
switch(args.code){
case 'Delete':
props.onDelete?.(getCurrent())
break
case 'Insert':
props.onAdd?.()
break
case 'Enter':
props.onEdit?.(getCurrent())
break
}
trace( `${args.code}`)
}}
ref={g => grid.current = g} >
<ColumnsDirective>
{props.children}
</ColumnsDirective>
<Inject services={[Toolbar, Resize, Reorder, ColumnChooser]} />
</GridComponent>
<Pagination count={pages} />
</>
)
}
type DataFieldPropsType = {
field: string,
title: string,
width?: number,
alignment?: 'Left' | 'Right' | 'Center' | 'Justify',
visible?: boolean,
order?: number
}
export function DataField(props: DataFieldPropsType) {
const {field, title, width, alignment, visible, order} = props
return (
<ColumnDirective
field={field}
headerTextAlign ='Left'
headerText={title}
allowReordering={true}
allowResizing={true}
width={width??100}
textAlign={alignment??'Left'}
visible={visible ?? false}
index={order}
>
</ColumnDirective>
)
}
|
[Hello.tsx]
function RenderData() {
var columns = [
{ field: 'id', title: 'Identity' },
{ field: 'fname', title: 'First Name' },
{ field: 'lname', title: 'Last Name' },
];
return (
<React.Fragment>
<DataGrid
rows={persons}
page={1}
size={10}
count={persons.length}
columns={columns}
></DataGrid>
</React.Fragment>
);
}
[Grid.tsx]
export function DataGrid<T>(props: DataGridPropsType<T>) {
---
for (var i = 0; i < props.columns.length; i++) {
GridColumns.push({
field: props.columns[i].field,
headerText: props.columns[i].title,
});
}
return (
<div>
<GridComponent
dataSource={props.rows}
columns={GridColumns}
---
>
<Inject services={[Toolbar, Resize, Reorder, ColumnChooser]} />
</GridComponent>
<Pagination count={pages} />
</div>
);
}
|
I saw your solution but you are using child component instead you are using props. is there a property in column that needs to be set to bind it to the grid?
I have one more question. unrelated though. When I rearrange columns using drag and Drop, is there a way to get the new indices or sequence of the columns? I did not find any property about that nor there was any event except drag and drop event
|
<GridComponent
dataSource={props.rows}
height="400"
gridLines="Both"
allowResizing={true}
allowReordering={true}
showColumnChooser={true}
selectedRowIndex={0}
ref={(g) => (grid.current = g)}
>
<ColumnsDirective>
{props.children.map((col: any) => (
<ColumnDirective
field={col.props.field}
width="100"
headerText={col.props.title}
allowReordering={true}
allowResizing={true}
/>
))}
</ColumnsDirective>
<Inject services={[Toolbar, Resize, Reorder, ColumnChooser]} />
</GridComponent>
|
|
<GridComponent
dataSource={props.rows}
height="400"
gridLines="Both"
allowResizing={true}
allowReordering={true}
showColumnChooser={true}
columnDrop={(args) => {
console.log(grid.current.columnModel);
}}
ref={(g) => (grid.current = g)}
>
|
Thanks for the reply. I came up with a similar solution but mine was to browse thru the children and render columns programatically. both the techniques show that columns JSX has an inability to reside outside GridComponent tag. I also frequently encountered this warning:
'ColumnsDirective' cannot be used as a JSX component. Its instance type 'ColumnsDirective' is not a valid JSX element.
Type 'ColumnsDirective' is missing the following properties from type 'ElementClass': render, context, setState, forceUpdate, and 3 more.
This warning is visible in StackBlitz. Not sure what it is referring to. perhaps this somehow points to the reason why Column and ColumnsDirective cannot exist outside GridComponent. Is the code available to look into how they are implemented?
About Column Rearrangement:
columnDrop event does give info about columns "were arranged before the drop happened".
As you can see, the Id is not at index 0 but now at 1. however If further rearrange:
Now is showing correctly that fname is column one. but for the middle column:
: Object
{removed code}
disableHtmlEncode: true
enableGroupByFormat: false
field: "id"
foreignKeyField: "id"
getEditTemplate: ƒ ()
getFilterTemplate: ƒ ()
index: 0
parserFn: ƒ ()
Which it clearly isn't. this info is for the previous state of the grid columns not the current. You can verify this in the provided solution i.e. https://stackblitz.com/edit/react-ts-kforeg?file=Grid.tsx
|
<GridComponent
dataSource={props.rows}
height="400"
gridLines="Both"
allowResizing={true}
allowReordering={true}
showColumnChooser={true}
//toolbar={toolbarOptions}
actionComplete={(args) => {
if (args.requestType == 'reorder') {
console.log(grid.current.columnModel);
}
}}
ref={(g) => (grid.current = g)}
> |