Header text does not show when data source is an array of object + Column arrangement

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>

    )

}






10 Replies

PS Pavithra Subramaniyam Syncfusion Team January 11, 2022 02:26 PM UTC

Hi Mercede, 
 
Thanks for contacting Syncfusion support. 
 
From your query we suspect that the Grid columns are autogenerated regardless the props value. By default, rendering Grid column dynamically based on the component property will be working fine at our end. Please refer to the below sample link in which the column is rendered properly with assigned values. 
 
 
So could you please share the below details that will be helpful for us to provide a better solution as early as possible. 
 
  1. Ensure whether the props. Children have proper Grid child column element
  2. Share the Syncfusion package version
  3. Ensure whether the other column properties are assigned properly
 
Regards, 
Pavithra S 



ME Mercede January 13, 2022 05:46 AM UTC

  1. That's exactly How I'm using. I've put together an example on Stackblitz that you can look at and see what is it that I'm missing. Grid Example that has issues
  2. Package version : "@syncfusion/ej2-react-grids": "^19.4.40"
  3. Yes and I rechecked the code. Now that is available, you can see it uses TS object names rather than the provided names


ME Mercede replied to Pavithra Subramaniyam January 14, 2022 03:42 AM UTC

Hi there, 

DId you get a chance to have a look at the code at stackblitz



RS Rajapandiyan Settu Syncfusion Team January 14, 2022 10:34 AM UTC

Hi Mercede, 
 
Thanks for your update. 
 
In your sample, the column settings are not properly bind to the GridComponent. So, the columns are generated based on the dataSource. Bind the columns in below way to resolve this issue, 
 
 
[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>(propsDataGridPropsType<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={[ToolbarResizeReorderColumnChooser]} /> 
      </GridComponent> 
      <Pagination count={pages} /> 
    </div> 
  ); 
} 
 
 
 
 
Please let us know if you have any concerns. 
 
Regards, 
Rajapandiyan S 



ME Mercede replied to Rajapandiyan Settu January 15, 2022 09:38 AM UTC

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



JC Joseph Christ Nithin Issack Syncfusion Team January 17, 2022 05:00 PM UTC

Hi Mercede, 

  Greetings from Syncfusion support. 

  Currently we are validating your query, we will provide further details on or before 19th January 2022. We appreciate your patience until then. 

Regards, 
Joseph I. 



JC Joseph Christ Nithin Issack Syncfusion Team January 18, 2022 03:47 PM UTC

Hi Mercede, 

   Thanks for your patience. 

Query 1: 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? 

  In your sample we can see that you have bind column properties externally . instead we suggest you to use the below solution, where we have bind the columns directly to the grid using props as you have mentioned.   

Please refer the below code example: 

      <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={[ToolbarResizeReorderColumnChooser]} /> 
      </GridComponent> 




Query 2: 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. 

You can get the new sequence of columns after rearranging the columns using the `columnDrop` event where you can get the columns using the `grid.columnModel` property of the EJ2 Grid. 

Please refer the below code example: 

<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)} 
      > 




Please get back to us for further details. 

Regards, 
Joseph I.     



ME Mercede replied to Joseph Christ Nithin Issack January 20, 2022 04:17 AM UTC

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". 

sync1.png

As you can see, the Id is not at index 0 but now at 1. however If further rearrange:

sync2.png

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




JC Joseph Christ Nithin Issack Syncfusion Team January 20, 2022 04:41 PM UTC

Hi Mercede, 

  Thanks for your update. 

  Query 1: 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. 

     By default in EJ2 Grid, we cannot render the columns using the `ColumnDirective` tag outside the grid component. It is designed that it will be recogonised only if it is rendered inside the `ColumnsDirective` inside the `GridComponent`. Otherwise, if it is rendered outside the GridComponent the EJ2 Base will not be able to identify the correct structure of the child component while compiling in EJ2 Component instances. 

Query2: columnDrop event does give info about columns "were arranged before the drop happened". 

    On validating the provided sample we were also able to reproduce the issue from our side. We need some more time for further validation. We will provide further details on or before  24th January 2022. We appreciate your patience until then. 

Please get back to us for further details. 

Regards, 
Joseph I. 



JC Joseph Christ Nithin Issack Syncfusion Team January 24, 2022 12:01 PM UTC

Hi Mercede, 

  Thanks for your patience. 

   Query: columnDrop event does give info about columns "were arranged before the drop happened". 
 
    This is because the `columnDrop` event triggers immediately the column is released, at this time the columns will not be rearranged. Instead we suggest you to use the `actionComplete` event which triggers after the drop action is completed. 

  Please refer the below code example: 

 <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)} 
      > 
   

Please get back to us for further details. 

Regards, 
Joseph I 


Loader.
Up arrow icon