KiwiCoder
KiwiCoder

Reputation: 1534

How to generically create table cell and rows with an array of objects

Currently I am struggling with iterating over an object containing an array with objects. (and nested ones) I am trying to create a generic Table Component in React so it can be used by many views.

What did I setup?

tableData.map((prop, key) => {
  return (
    <TableRow key={key}>
      <TableCell className={classes.tableCell} key={key}>
        {prop.number}
      </TableCell>
      <TableCell className={classes.tableCell} key={key}>
        {prop.TableType.max_occupancy}
      </TableCell>
      <TableCell className={classes.tableCell} key={key}>
        {prop.price}
      </TableCell>
      <TableCell className={classes.tableCell} key={key}>
        {prop.TableType.description}
      </TableCell>
      <TableCell className={classes.tableCell} key={key}>
        <Button fullWidth color="primary">
          Remove
        </Button>
      </TableCell>
    </TableRow>
  );
})

The problem that I am facing right now?

I can not create the content above in a dynamic way. I am encountering several issues like for example:

What would I like to achieve?

I would like to achieve something that is generic and can be used in a wide range of scenarios and does not clash with other pages where this component is being used.

In the end it should look something like this in a visual way:

enter image description here

What data do I have?

[
    {
        "id": 1,
        "number": 1,
        "status": true,
        "price": 12,
        "table_type_id": 1,
        "venue_id": 1,
        "TableType": {
            "id": 1,
            "description": "Small Table",
            "max_occupancy": 3
        }
    },
    {
        "id": 2,
        "number": 2,
        "status": true,
        "price": 2,
        "table_type_id": 2,
        "venue_id": 1,
        "TableType": {
            "id": 2,
            "description": "Medium Table",
            "max_occupancy": 6
        }
    }
]

The Codesandbox directory with the full project: https://codesandbox.io/embed/lwzz4j9mz?autoresize=1&eslint=1 The fill we are talking about is located at the Components/Table/Table.jsx. (I have added some dummy data in the comments that needs to be parsed to Table rows and cells)

Properties that needs be used in the view:

Hopefully someone can come up with a smart idea to help me out with this issue! Cheers for all the help and hopefully we can fix this together.

Upvotes: 0

Views: 108

Answers (1)

Shyam Babu
Shyam Babu

Reputation: 1079

You should probably use an external library to get this done. But if you want to go for an in house approach this would be one way to go about it.

To the component, send the data and the header.The header should also specify how the data should be parsed to receive it's value.

var defaultTemaplate = '<TableRow><TableCell style={{ textAlign: "center" }}>Woooops! You haven\'t applied any tables for this venue yet. To start renting out tables you should add at least 3 tables tothe app. Just press the button above to start imediately.</TableCell></TableRow>'
var tableHead = [{
    title: 'number',
    type: 'data',
    path: 'number'
  },
  {
    title: 'TableType',
    type: 'data',
    path: 'TableType.description'
  },
  {
    title: 'Edit/delete',
    type: 'template',
    templateString: '<button></button>'
  }
] //for all columns
var tableData = [{
    "id": 1,
    "number": 1,
    "status": true,
    "price": 12,
    "table_type_id": 1,
    "venue_id": 1,
    "TableType": {
      "id": 1,
      "description": "Small Table",
      "max_occupancy": 3
    }
  },
  {
    "id": 2,
    "number": 2,
    "status": true,
    "price": 2,
    "table_type_id": 2,
    "venue_id": 1,
    "TableType": {
      "id": 2,
      "description": "Medium Table",
      "max_occupancy": 6
    }
  }
]
console.log(genRows(tableData))

function getTableCells(data) {
  return tableHead.map((opts) => {
    if (opts.type === 'data') {
      return `<TableCell className={classes.tableCell}>${_.at(data, opts.path)}</TableCell>`
    }
    if (opts.type === 'template') {
      return opts.templateString
    }
  })
}

function genRows(tableData) {
  if (tableData.length < 0) return defaultTemaplate;
  return tableData.map((rowData) => `<TableRow>${getTableCells(rowData)}</TableRow>`)
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.10/lodash.js"></script>

This is just an example to demonstrate one approach you could take, not full fledged code and can defenetly be improved.

Upvotes: 1

Related Questions