javascript - 如何使用 API 返回的多个字段构建表列?
问题描述
我需要预处理来自 API 的数据。原始数据采用以下格式:
我想动态构建一个表,其中的列应该使用字段task_name
和saved_answers
. 请注意,saved_answers
可能包含不同的子字段,具体取决于task_name
. 换句话说,并不saved_answers
总是包含value21
、value22
和。value23
value24
下面我展示一个表格的例子。
============================================================================================================
| user_id | task11-value21 | task11-value22 | task11-value23 | task11-value24 | task13-valueMu...
============================================================================================================
| 111 | 1 | 1 | 1 | 1 | 5
...
到目前为止,我只能从 API 检索数据并在表中显示特定列。我将非常感谢任何帮助。谢谢。
import React, { useEffect } from 'react'
import { makeStyles } from '@material-ui/core/styles';
import Grid from '@material-ui/core/Grid';
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 Paper from '@material-ui/core/Paper';
import axios from 'axios'
import config from '../../config/config.json';
const useStyles = makeStyles((theme) => ({
root: {
width: '100%',
},
heading: {
fontSize: theme.typography.pxToRem(18),
fontWeight: theme.typography.fontWeightBold,
},
content: {
fontSize: theme.typography.pxToRem(14),
fontWeight: theme.typography.fontWeightRegular,
textAlign: "left",
marginTop: theme.spacing.unit*3,
marginLeft: theme.spacing.unit*3,
marginRight: theme.spacing.unit*3
},
table: {
minWidth: 650,
},
tableheader: {
fontWeight: theme.typography.fontWeightBold,
color: "#ffffff",
background: "#3f51b5"
}
}));
export function Main() {
const [groupKey,setGroupKey] = React.useState([]);
const classes = useStyles();
const options = {
'headers': {
'Authorization': `Bearer ${localStorage.getItem('accessToken')}`
}
}
useEffect(() => {
axios.get(config.api.url + '/api/test', options)
.then( (groups) => {
setGroupKey(groups);
console.log(groups);
})
.catch( (error) => {
console.log(error);
})
}, []);
return (
<div className={classes.root}>
<Grid container spacing={3}>
<Grid item xs={12} className={classes.content}>
<TableContainer component={Paper}>
<Table className={classes.table}>
<TableHead>
<TableRow>
<TableCell className={classes.tableheader}>Group</TableCell>
<TableCell className={classes.tableheader} colSpan={3}>Task name</TableCell>
</TableRow>
</TableHead>
<TableBody>
{groupKey.map( (row, index) => (
<TableRow key={index} selected="false">
<TableCell>{row.user_id}</TableCell>
<TableCell>{row.task_name}</TableCell>
</TableRow>))}
</TableBody>
</Table>
</TableContainer>
</Grid>
</Grid>
</div>
)
}
更新:
import '../../App.css';
import React, { useEffect } from 'react'
import PropTypes from 'prop-types';
import { makeStyles, useTheme } from '@material-ui/core/styles';
import Grid from '@material-ui/core/Grid';
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 TablePagination from '@material-ui/core/TablePagination';
import TableFooter from '@material-ui/core/TableFooter';
import IconButton from '@material-ui/core/IconButton';
import FirstPageIcon from '@material-ui/icons/FirstPage';
import KeyboardArrowLeft from '@material-ui/icons/KeyboardArrowLeft';
import KeyboardArrowRight from '@material-ui/icons/KeyboardArrowRight';
import LastPageIcon from '@material-ui/icons/LastPage';
import Paper from '@material-ui/core/Paper';
import axios from 'axios'
import config from '../../config/config.json';
const useStyles = makeStyles((theme) => ({
root: {
width: '100%',
},
heading: {
fontSize: theme.typography.pxToRem(18),
fontWeight: theme.typography.fontWeightBold,
},
content: {
fontSize: theme.typography.pxToRem(14),
fontWeight: theme.typography.fontWeightRegular,
textAlign: "left",
marginTop: theme.spacing.unit*3,
marginLeft: theme.spacing.unit*3,
marginRight: theme.spacing.unit*3
},
table: {
minWidth: 650,
},
tableheader: {
fontWeight: theme.typography.fontWeightBold,
color: "#ffffff",
background: "#3f51b5"
},
tableCell: {
color: "#000000",
background: "#ffffff"
},
button: {
fontSize: "12px",
minWidth: 100
},
}));
function TablePaginationActions(props) {
const classes = useStyles();
const theme = useTheme();
const { count, page, rowsPerPage, onChangePage } = props;
const handleFirstPageButtonClick = (event) => {
onChangePage(event, 0);
};
const handleBackButtonClick = (event) => {
onChangePage(event, page - 1);
};
const handleNextButtonClick = (event) => {
onChangePage(event, page + 1);
};
const handleLastPageButtonClick = (event) => {
onChangePage(event, Math.max(0, Math.ceil(count / rowsPerPage) - 1));
};
return (
<div className={classes.root}>
<IconButton
onClick={handleFirstPageButtonClick}
disabled={page === 0}
aria-label="first page"
>
{theme.direction === 'rtl' ? <LastPageIcon /> : <FirstPageIcon />}
</IconButton>
<IconButton onClick={handleBackButtonClick} disabled={page === 0} aria-label="previous page">
{theme.direction === 'rtl' ? <KeyboardArrowRight /> : <KeyboardArrowLeft />}
</IconButton>
<IconButton
onClick={handleNextButtonClick}
disabled={page >= Math.ceil(count / rowsPerPage) - 1}
aria-label="next page"
>
{theme.direction === 'rtl' ? <KeyboardArrowLeft /> : <KeyboardArrowRight />}
</IconButton>
<IconButton
onClick={handleLastPageButtonClick}
disabled={page >= Math.ceil(count / rowsPerPage) - 1}
aria-label="last page"
>
{theme.direction === 'rtl' ? <FirstPageIcon /> : <LastPageIcon />}
</IconButton>
</div>
);
}
function getGridHeader(config) {
const gridHeader = ["user_id"];
console.log(config);
const savedAnswers = Object.keys(JSON.parse(config.saved_answers));
savedAnswers.map(savedAnswer => {
gridHeader.push(`${config.task_name}-${savedAnswer}`)
});
return gridHeader;
}
function getGridData(config) {
const gridData = [config.user_id];
const savedAnswers = JSON.parse(config.saved_answers);
Object.keys(savedAnswers).map( savedAnswer => {
gridData.push(savedAnswers[savedAnswer]);
});
return gridData;
}
TablePaginationActions.propTypes = {
count: PropTypes.number.isRequired,
onChangePage: PropTypes.func.isRequired,
page: PropTypes.number.isRequired,
rowsPerPage: PropTypes.number.isRequired,
};
export function Main() {
const [groupKey,setGroupKey] = React.useState([]);
const [page, setPage] = React.useState(0);
const [rowsPerPage, setRowsPerPage] = React.useState(5);
const emptyRows = rowsPerPage - Math.min(rowsPerPage, groupKey.length - page * rowsPerPage);
const gridHeader = getGridHeader(groupKey);
const gridData = getGridData(groupKey);
const handleChangePage = (event, newPage) => {
setPage(newPage);
};
const handleChangeRowsPerPage = (event) => {
setRowsPerPage(parseInt(event.target.value, 10));
setPage(0);
};
const classes = useStyles();
const options = {
'headers': {
'Authorization': `Bearer ${localStorage.getItem('accessToken')}`
}
}
useEffect(() => {
axios.get(config.api.url + '/api/test', options)
.then( (groups) => {
setGroupKey(groups.data.subtask);
})
.catch( (error) => {
console.log(error);
})
}, []);
return (
<div className={classes.root}>
<Grid container spacing={3}>
<Grid item xs={12} className={classes.content}>
<TableContainer component={Paper}>
<Table className={classes.table}>
<TableHead>
<TableRow className={classes.tableheader}>
{gridHeader.map( (headerTitle, index) => (
<TableCell key={index}>{headerTitle}</TableCell>
))}
</TableRow>
</TableHead>
<TableBody>
{(rowsPerPage > 0
? gridData.slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage)
: gridData
).map((cellValue, index) => (
<TableRow key={index} selected="false">
<TableCell className={classes.tableCell}component="th" scope="row">{cellValue}</TableCell>
</TableRow>
))}
{emptyRows > 0 && (
<TableRow style={{ height: 53 * emptyRows }}>
<TableCell colSpan={6} />
</TableRow>
)}
</TableBody>
<TableFooter>
<TableRow>
<TablePagination
rowsPerPageOptions={[5, 10, 25, { label: 'All', value: -1 }]}
colSpan={3}
count={groupKey.length}
rowsPerPage={rowsPerPage}
page={page}
SelectProps={{
inputProps: { 'aria-label': 'groups per page' },
native: true,
}}
onChangePage={handleChangePage}
onChangeRowsPerPage={handleChangeRowsPerPage}
ActionsComponent={TablePaginationActions}
/>
</TableRow>
</TableFooter>
</Table>
</TableContainer>
</Grid>
</Grid>
</div>
)
}
解决方案
所以,算法如下:
- 从原始数据生成标头数组
- 根据 user_id 为表体数据生成数组
我希望你能做到。
使用这两个数组,您可以迭代并创建数据表,例如:
import React from 'react';
import { makeStyles } from '@material-ui/core/styles';
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 Paper from '@material-ui/core/Paper';
const useStyles = makeStyles({
table: {
minWidth: 650,
},
});
function generateRandomSavedAnswer(rowIndex, maxNumberOfSavedAnswers) {
//const numberOfSavedAnswers = Math.floor(Math.random()*maxNumberOfSavedAnswers);
const savedAnswers = {};
for(let i=0; i<maxNumberOfSavedAnswers; i++) {
savedAnswers[`value${rowIndex}${i}`] = rowIndex+i;
}
return savedAnswers;
}
function generateGridRawData() {
let gridData = [];
for(let i=0; i<10; i++) {
gridData.push({
saved: true,
saved_answers: JSON.stringify(generateRandomSavedAnswer(10, 5)),
submited: true,
task_name: 'task12',
user_id: Math.floor(Math.random()*3),
__v: 0,
_id: Math.round(Math.sin(i*0.01)*100)
});
}
return gridData;
}
function getGridHeader(config) {
const gridHeader = ["user_id"];
const savedAnswers = Object.keys(JSON.parse(config.saved_answers));
savedAnswers.map(savedAnswer => {
gridHeader.push(`${config.task_name}-${savedAnswer}`)
});
return gridHeader;
}
function getGridData(config) {
const gridData = [config.user_id];
const savedAnswers = JSON.parse(config.saved_answers);
Object.keys(savedAnswers).map( savedAnswer => {
gridData.push(savedAnswers[savedAnswer]);
});
return gridData;
}
export default function SimpleTable() {
const classes = useStyles();
const gridRawData = generateGridRawData();
const gridHeader = getGridHeader(gridRawData[0]);
const gridData = getGridData(gridRawData[0]);
return (
<TableContainer component={Paper}>
<Table className={classes.table} aria-label="simple table">
<TableHead>
<TableRow>
{gridHeader.map( (headerTitle, index) => (
<TableCell key={index}>{headerTitle}</TableCell>
))}
</TableRow>
</TableHead>
<TableBody>
<TableRow>
{gridData.map( (cellValue, index) => (
<TableCell key={index}>{cellValue}</TableCell>
))}
</TableRow>
</TableBody>
</Table>
</TableContainer>
);
}
推荐阅读
- excel - 后期绑定编译错误:在 Excel VBA 中未定义引用 Outlook 邮件项的用户定义类型
- php - CaBundle open_basedir 限制
- java - 我正在尝试在 exoplayer 中提取 youtube url。我想在日志中提取我的 sparsarray 值
- python - Installing mathplotlib gives "MemoryError"
- c# - 如何在 c# 代码中添加几个表?
- google-sheets - Only show a portion of a live Google sheet
- javascript - Java script pass function with arguments to another function
- java - 我正在创建 java api 来连接 kafka
- android - 离子构建失败
- c# - 如何获取不在同一类中的字符串的值?