-1

I've created a reusable table in React. My problem is on the display of the data from the other page. I need to get the value for it to be displayed in <TableCell>

Pls see this code sandbox link

CLICK HERE

return (
    <Paper className={classes.root}>
      <TableContainer className={classes.container}>
        <Table stickyHeader aria-label="sticky table">
          <TableHead>
            <TableRow>
              {tableHeaders.map((header, index) => (
                <TableCell key={index}>{header}</TableCell>
              ))}
            </TableRow>
          </TableHead>
          <TableBody>
            {data.map(data => (
              <TableRow key={data.id}>
                {tableBodies.map(body => (
                  <TableCell key={body}>{`data.${body}`}</TableCell>
                ))}
              </TableRow>
            ))}
          </TableBody>
        </Table>
      </TableContainer>
    </Paper>
  );
NearHuscarl
  • 66,950
  • 18
  • 261
  • 230
Joseph
  • 7,042
  • 23
  • 83
  • 181
  • The same question is answered [here](https://stackoverflow.com/questions/33913737/inserting-the-iframe-into-react-component) – Omar Sheashaa Jul 14 '20 at 04:45
  • You can't pass a string of keys or define an React component as a string. You also can't use template literals (backticks) to display data. You should extract the data / components you want to display in the parent file and pass those down – Yoshi Jul 14 '20 at 05:21

5 Answers5

0

This is my solution for you, it worked based on your project codesandbox.

// tableList.js
import React from "react";
import { makeStyles } from "@material-ui/core/styles";
import Paper from "@material-ui/core/Paper";
import Table from "@material-ui/core/Table";
import TableBody from "@material-ui/core/TableBody";
import TableCell from "@material-ui/core/TableCell";
import TableContainer from "@material-ui/core/TableContainer";
import TableHead from "@material-ui/core/TableHead";
import TableRow from "@material-ui/core/TableRow";

const useStyles = makeStyles({
  root: {
    width: "100%"
  },
  container: {
    maxHeight: 440
  }
});

export default function StickyHeadTable({ data, tableHeaders, tableBodies }) {
  const classes = useStyles();

  const getProperty = (obj, prop) => {
    var parts = prop.split('.');

    if (Array.isArray(parts)) {
        var last = parts.pop(),
        l = parts.length,
        i = 1,
        current = parts[0];

        while((obj = obj[current]) && i < l) {
            current = parts[i];
            i++;
        }

        if(obj) {
            return obj[last];
        }
    } else {
        throw 'parts is not valid array';
    }
  }

  return (
    <Paper className={classes.root}>
      <TableContainer className={classes.container}>
        <Table stickyHeader aria-label="sticky table">
          <TableHead>
            <TableRow>
              {tableHeaders.map((header, index) => (
                <TableCell key={index}>{header}</TableCell>
              ))}
            </TableRow>
          </TableHead>
          <TableBody>
            {data.map(data => (
              <TableRow key={data.id}>
                {tableBodies.map(body => (
                  // <TableCell key={body}>{body}</TableCell>
                    (typeof body === "string"
                      ? <TableCell key={body}>{getProperty(data, body)}</TableCell>
                      : <TableCell key={body}>{body}</TableCell>
                    )
                ))}
              </TableRow>
            ))}
          </TableBody>
        </Table>
      </TableContainer>
    </Paper>
  );
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

// demo.js
import React from "react";
import VisibilityIcon from '@material-ui/icons/Visibility';
import Button from '@material-ui/core/Button';
import { Link } from 'react-router-dom'
import TableList from "./tableList";

const data = [
  {
    id: 23,
    order: {
      owner: {
        id: 5,
        user: {
          id: 4,
          first_name: "John",
          last_name: "Doe"
        }
      }
    },
    application_date: "2020-07-06"
  },
  {
    id: 24,
    order: {
      owner: {
        id: 5,
        user: {
          id: 4,
          first_name: "Jane",
          last_name: "Doe"
        }
      }
    },
    application_date: "2020-07-06"
  }
];

const tableHeaders = ["First Name", "Last Name", "Options"];


const tableBodies = [
  `order.owner.user.first_name`,
  `order.owner.user.last_name`,
  <Button
  // component={Link}
  variant="contained"
  type="button"
  size="small"
  className={"button-classes"}
  startIcon={<VisibilityIcon />}
  />
]
export default function StickyHeadTable() {
  return (
    <TableList
      data={data}
      tableHeaders={tableHeaders}
      tableBodies={tableBodies}
    />
  );
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

enter image description here

  • Unfortunately, this only works on the `orders` object. How about when i want to display on the level of `id`? – Joseph Jul 14 '20 at 07:47
0

I added this function getProperty(param1: [], param2: string//'items.attributes.name'), this works with any array. you just need to pass it the structure you want it to show. for example: 'products.name', 'items.attributes.name'

const getProperty = (obj, prop) => {
    var parts = prop.split('.');

    if (Array.isArray(parts)) {
        var last = parts.pop(),
        l = parts.length,
        i = 1,
        current = parts[0];

        while((obj = obj[current]) && i < l) {
            current = parts[i];
            i++;
        }

        if(obj) {
            return obj[last];
        }
    } else {
        throw 'parts is not valid array';
    }
  }

This is my solution for you, it worked based on your project codesandbox
0

To use Link, you must define your routes. you can create your routes here. Example: I created a file App.js to define the routes

// app.js
import React, { Component } from "react";
import { BrowserRouter, Switch, Route } from "react-router-dom";
import Demo from './demo';

const LoginForm = () => <></>;
const SearchComponent = () => <></>;

class App extends Component {
  render() {
    return (
      <React.Fragment>
        <BrowserRouter>
          <div>
            <Route path="/search" component={SearchComponent} />
            <Route path="/loginform" component={LoginForm} />
            <Route path="/" component={Demo}/>
          </div>
        </BrowserRouter>
      </React.Fragment>
    );
  }
}

export default App;
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

could pass button link attributes as an object

    // demo.js
  const tableBodies = [
      `order.owner.user.first_name`,
      `order.owner.user.last_name`,
     {
        base: '/user',
        icon: <VisibilityIcon />
     }
   ]

I defined a function return a custom ButtonLink() button link can you pass the props after call it

import React from "react";
import { makeStyles } from "@material-ui/core/styles";
import Paper from "@material-ui/core/Paper";
import Table from "@material-ui/core/Table";
import TableBody from "@material-ui/core/TableBody";
import TableCell from "@material-ui/core/TableCell";
import TableContainer from "@material-ui/core/TableContainer";
import TableHead from "@material-ui/core/TableHead";
import TableRow from "@material-ui/core/TableRow";
import { Link } from 'react-router-dom'
import Button from '@material-ui/core/Button';
import VisibilityIcon from '@material-ui/icons/Visibility';

const useStyles = makeStyles({
  root: {
    width: "100%"
  },
  container: {
    maxHeight: 440
  }
});

export default function StickyHeadTable({ data, tableHeaders, tableBodies }) {
  const classes = useStyles();

  const getProperty = (obj, prop) => {
    var parts = prop.split('.');

    if (Array.isArray(parts)) {
        var last = parts.pop(),
        l = parts.length,
        i = 1,
        current = parts[0];

        while((obj = obj[current]) && i < l) {
            current = parts[i];
            i++;
        }

        if(obj) {
            return obj[last];
        }
    } else {
        throw 'parts is not valid array';
    }
  }

  const ButtonLink = (prop) => {
    return (
      <Button
        component={Link}
        to={prop.link}
        variant="contained"
        type="button"
        size="small"
        className={"button-classes"}
        startIcon={prop.icon}
        />
      )
  }
  //<ButtonLink link="/mani"/>
  return (
    <Paper className={classes.root}>
      <TableContainer className={classes.container}>
        <Table stickyHeader aria-label="sticky table">
          <TableHead>
            <TableRow>
              {tableHeaders.map((header, index) => (
                <TableCell key={index}>{header}</TableCell>
              ))}
            </TableRow>
          </TableHead>
          <TableBody>
            {data.map(data => (
              <TableRow key={data.id}>
                {tableBodies.map(body => (
                    (typeof body === "string"
                      ? <TableCell key={body}>{getProperty(data, body)}</TableCell>
                      : <TableCell key={body}><ButtonLink 
                        link={body.base}
                        icon={body.icon}
                        /></TableCell>
                    )
                ))}
              </TableRow>
            ))}
          </TableBody>
        </Table>
      </TableContainer>
    </Paper>
  );
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

// index.js
import React from 'react';
import ReactDOM from 'react-dom';
import Demo from './demo';
import App from './app';

//ReactDOM.render(<Demo />, document.querySelector('#root'));
ReactDOM.render(<App />, document.querySelector('#root'));
0

Here is my solution:

Add react-jsx-parser library.

yarn add react-jsx-parser

Then in your code:

import React from "react";
import { makeStyles } from "@material-ui/core/styles";
import Paper from "@material-ui/core/Paper";
import Table from "@material-ui/core/Table";
import { Button, Link } from "@material-ui/core";
import VisibilityIcon from "@material-ui/icons/Visibility";
import TableBody from "@material-ui/core/TableBody";
import TableCell from "@material-ui/core/TableCell";
import TableContainer from "@material-ui/core/TableContainer";
import TableHead from "@material-ui/core/TableHead";
import TableRow from "@material-ui/core/TableRow";
import JsxParser from "react-jsx-parser";

const useStyles = makeStyles({
  root: {
    width: "100%",
  },
  container: {
    maxHeight: 440,
  },
});

export default function StickyHeadTable({ data, tableHeaders, tableBodies }) {
  const classes = useStyles();

  return (
    <Paper className={classes.root}>
      <TableContainer className={classes.container}>
        <Table stickyHeader aria-label="sticky table">
          <TableHead>
            <TableRow>
              {tableHeaders.map((header, index) => (
                <TableCell key={index}>{header}</TableCell>
              ))}
            </TableRow>
          </TableHead>
          <TableBody>
            {data.map((data) => (
              <TableRow key={data.id}>
                {tableBodies.map((body, index) => (
                  <TableCell>
                    {index !== 2 ? (
                      eval(`data.${body}`)
                    ) : (
                      <JsxParser
                        components={{ Button, Link, VisibilityIcon }}
                        jsx={body}
                      />
                    )}
                  </TableCell>
                ))}
              </TableRow>
            ))}
          </TableBody>
        </Table>
      </TableContainer>
    </Paper>
  );
}

You can find additional documentation Here for adding bindings etc

Muhammad Ali
  • 683
  • 4
  • 9
0
  • I modified just two parts of the functions to use.

const getProperty = (obj, prop) => {
    var parts = prop.split('.');

    if (Array.isArray(parts)) {
      var last = parts.length > 1 ? parts.pop() : parts;
      var l = parts.length,
        i = 1,
        current = parts[0];

      while ((obj = obj[current]) && i < l) {
        current = parts[i];
        i++;
      }

      if (typeof obj === 'object') {
        return obj[last];
      }
       return obj
    } else {
      throw 'parts is not valid array';
    }
  }

and this section is not necessary to modify

enter image description here