Mendes
Mendes

Reputation: 18451

ReactJs fixed-data-table: data.getObjectAt is not a function

I´m trying to build a JSON configurable data table using the Facebook´s fixed-data-table. I´ve come to my first code as:

import React, { Component } from 'react';
import PropTypes from 'prop-types';

import { Icon } from 'semantic-ui-react';

import { Table, Column, Cell } from 'fixed-data-table';

const DateCell = ({rowIndex, data, col, ...props}) => (
  <Cell {...props}>
    {data.getObjectAt(rowIndex)[col].toLocaleString()}
  </Cell>
);

const LinkCell = ({rowIndex, data, col, ...props}) => (
  <Cell {...props}>
    <a href="#">{data.getObjectAt(rowIndex)[col]}</a>
  </Cell>
);

const TextCell = ({rowIndex, data, col, ...props}) => (
  <Cell {...props}>
    {data.getObjectAt(rowIndex)[col]}
  </Cell>
);

const NumericCell = ({rowIndex, data, col, ...props}) => (
  <Cell {...props}>
    {data.getObjectAt(rowIndex)[col]}
  </Cell>
);

const BooleanCell = ({rowIndex, data, col, ...props}) => (
  
  <Cell {...props}>
    {data.getObjectAt(rowIndex)[col] ? <Icon name='checkmark' color='green' /> : <Icon name='remove' color='red' />}
  </Cell>
);


class DataTable extends Component {
    state = {
      schema: this.props.schema,
      data: this.props.data,
    }

  getCells = (schema, data) => {

        let columns = [];

        schema.columns.map((column, index) => {

            let cell = (<TextCell></TextCell>);
            let key = column.field + index;

            if (column.type === 'string') {

              cell = (<TextCell 
                          data={this.state.data} 
                          col={column.field}
                        />);
            }

            if (column.type === 'integer') {

              cell = (<NumericCell 
                          data={this.state.data} 
                          col={column.field}
                        />);
            }


            if (column.type === 'boolean') {

              cell = (<BooleanCell 
                          data={this.state.data} 
                          col={column.field}
                        />);
            }


            let col = (<Column 
                          header={column.title}
                          cell={cell}
                          width={100}
                       />);

            columns.push(col);

            return;
          });

      return columns;
    }




  render() {

    let schema = {
      "columns": [
          {
            "title": "Name",
            "field": "name",
            "type": "string",
          },
          {
            "title": "EIN",
            "field": "ein",
            "type": "string",
          },
          {
            "title": "Active",
            "field": "isactive",
            "type": "boolean",
          }
        ],
        "edit": true,
        "delete": true,
        "sort": true
    };

    let data = [
    {
      name: 'Test1',
      ein: '1234',
      isactive: true
    },
    {
      name: 'Test2',
      ein: '123',
      isactive: true
    },
    {
      name: 'Test3',
      ein: '12345',
      isactive: true
    },
    ];

    let columns = this.getCells(schema, data);


    return (
      <Table
        rowHeight={50}
        schemaHeight={50}
        maxHeight={100}
        width={1000}
        height={500}
        rowsCount={data.length}
        {...this.props}>

        {columns}

      </Table>
    );
  }
}

export default DataTable;

When running I´m getting the following error:

TypeError: data.getObjectAt is not a function
TextCell
D:\\WORKSPACE\test\src\components\shared\DataTable.js:42
  39 | 
  40 | const TextCell = ({rowIndex, data, col, ...props}) => (
  41 |   <Cell {...props}>
**> 42 |     {data.getObjectAt(rowIndex)[col]}**
  43 |   </Cell>
  44 | );
  45 | 

I´ve tried different JSON structures with no luck. The data and schema are loaded accordingly.

Upvotes: 2

Views: 517

Answers (1)

This literally takes some time to wrap ones mind around initially.

I will describe it using references to code in 'fixed-data-table-2'.

The data list when used in the table is wrapped in an object that consist of the data list and a data list filter array. Your list data will only show up if you have wrapped it as a DataListWrapper object along with a filter array where every entry of the filter array is a boolean specifying if the corresponding list row will be visible (true) or hidden (false).

See the class BuildObjectDataListStore. There is a method 'getObjectAt' in there which when called retrieves list row columns based on the input variable name. For example

var {my_id} = list.getObjectAt(44);

means that if the list row at index 44 contains a column named 'my_id' then the value of that column will end up in your my_id variable. This works only with 'underscore' as delimiter in column names, so any lists made up of columns such as "my-id" must be converted to "my_id" before use in 'fixed-data-table'. There exists a neat conversion table procedure in BuildObjectDataListStore for that.

Here is how you wrap a plain list array 'myList' into an object that fixed-data-table' can render:

this.dataList = new BuildObjectDataListStore(myList);

Then this object is wrapped into an object along with a filter array:

this.filteredDataList = new DataListWrapper(this.filter, this.dataList);

And there you have it; DataListWrapper is a recognized list format that 'fixed-data-table' can render.

Nowadays people use 'fixed-data-table-2' which enjoys continued support by Schrödinger, Inc. The earlier 'fixed-data-table' is abandoned as a public component.

Evolving from the foundations of fixed-data-table, the power of fixed-data-table-2 is at least twofold;

  • Can cope with thousands of lines of list data without bogging down on scrolling and other responsiveness.
  • The principle of cell renderers means any row column can be made to render anything that HTML5 offers (text, image, video, etc).

So for some applications this list component can be spot on. A drawback can be the initial learning curve of the mentioned wrapping principles and column renderer methods.

Upvotes: 2

Related Questions