如何在Grommet DataTable中处理数组类型数据?
在Grommet DataTable中实现数组类型单元格的展开折叠功能
问题背景
我有如下结构的数组类型数据:
{ customer: [ 'BANANA', 'Banana', 'banana', 'republic of banana' ], somethingelse: ['ABC','123','DEF'] }
在常规Grommet Table中,我可以把数组的首个元素作为单元格标题,再添加展开箭头展示数组的其余元素,但不清楚如何在Grommet DataTable的单元格层面实现这个效果。
常规Grommet Table的实现代码
<TableCell scope="row" pad={{ left: '2px', right: '3px' }}> <TextInput name="tags" size="xsmall" /> </TableCell> </TableRow> {searchResults.length > 0 && searchResults.map((searchResult, index) => ( <TableRow key={index}> <TableCell> <Box direction="row"> <Text size="xsmall">{searchResult.customer[0]}</Text> {searchResult.customer.length > 1 && ( <Button plain hoverIndicator={false} icon={ isExpanded[index] ? ( <FormDown size="18px" /> ) : ( <FormNext size="18px" /> ) } onClick={() => toggleOpen(index)} /> )} </Box> <Box> {isExpanded[index] && listElements(searchResult.customer)} </Box> </TableCell>
当前DataTable的代码(待改造)
return ( <Form value={formData} onSubmit={onSubmit} onChange={onChange}> ... <DataTable fill border={{ body: 'bottom' }} paginate columns={columns} data={searchResults} select={select} onClickRow={(e) => console.log(e.datum)} onSelect={() => {}} step={8} rowDetails={(row) => { // 我可使用rowDetails展开显示部分数据,但如何实现1. 将数组的[0]元素作为标题;2. 应用到行/表格的所有单元格。 for (const cell in row) { // if (cell.length > 1) { // return listElements(cell); // } console.log(cell); } }} ... /> ... </Form> );
解决方案
要在Grommet DataTable中实现该功能,需要通过自定义列渲染器控制单元格内容,同时维护每行的展开状态:
1. 维护展开状态
在组件内部添加状态记录每行的展开情况:
const [expandedRows, setExpandedRows] = useState({}); const toggleExpand = (rowId) => { setExpandedRows(prev => ({ ...prev, [rowId]: !prev[rowId] })); };
2. 配置自定义列
在columns配置中,为包含数组的字段指定render函数,实现首元素展示+展开箭头的逻辑:
const columns = [ { property: 'customer', header: 'Customer', render: ({ customer, index }) => ( <Box> <Box direction="row" align="center" gap="small"> <Text size="xsmall">{customer[0]}</Text> {customer.length > 1 && ( <Button plain hoverIndicator={false} icon={expandedRows[index] ? <FormDown size="18px" /> : <FormNext size="18px" />} onClick={() => toggleExpand(index)} /> )} </Box> {expandedRows[index] && ( <Box margin={{ top: 'small' }}> {customer.slice(1).map((item, idx) => ( <Text key={idx} size="xsmall" margin={{ left: 'medium' }}>{item}</Text> ))} </Box> )} </Box> ) }, { property: 'somethingelse', header: 'Something Else', render: ({ somethingelse, index }) => ( <Box> <Box direction="row" align="center" gap="small"> <Text size="xsmall">{somethingelse[0]}</Text> {somethingelse.length > 1 && ( <Button plain hoverIndicator={false} icon={expandedRows[index] ? <FormDown size="18px" /> : <FormNext size="18px" />} onClick={() => toggleExpand(index)} /> )} </Box> {expandedRows[index] && ( <Box margin={{ top: 'small' }}> {somethingelse.slice(1).map((item, idx) => ( <Text key={idx} size="xsmall" margin={{ left: 'medium' }}>{item}</Text> ))} </Box> )} </Box> ) } ];
3. 更新DataTable组件
去掉rowDetails,直接使用配置好的columns即可:
<DataTable fill border={{ body: 'bottom' }} paginate columns={columns} data={searchResults.map((item, idx) => ({ ...item, index: idx }))} // 给每行添加index用于追踪展开状态 select={select} onClickRow={(e) => console.log(e.datum)} onSelect={() => {}} step={8} />
补充说明
- 若数据本身有唯一ID,可替换
index作为展开状态的绑定键,避免分页或数据更新导致的状态混乱。 - 如需实现单元格级别的独立展开(不同字段各自控制展开),可将
expandedRows的键设计为${rowId}-${property}的形式。
内容的提问来源于stack exchange,提问作者zlobul
相关产品推荐
相关产品推荐

