内表中的最后一行不会在固定数据表中展开
Posted
技术标签:
【中文标题】内表中的最后一行不会在固定数据表中展开【英文标题】:Last rows in inner table don't expand in Fixed Data Table 【发布时间】:2018-11-13 22:16:11 【问题描述】:我在 fixed-data-table-2 组件中使用expanded rows。我在内表上有 3 个级别:
如果我单击内表(第二个嵌套级别)中的折叠单元格,行不会展开并且最后一个嵌套表不会呈现。它发生在第一次单击父行后,但在第二次单击后呈现表格。
更奇怪的是,如果 a)我单击第二个表的前三行或 b)如果我在主(第一)表中展开第一行
如果不是主表的第一行被展开,第二个表的最后一行就会发生这种情况。
您可以在 this 和 this 录制中看到此行为。
codesandbox
CollapseCell.jsx
import React from 'react';
import Cell from 'fixed-data-table-2';
const StyleSheet, css = require('aphrodite');
export default class CollapseCell extends React.PureComponent
render()
const
data, rowIndex, columnKey, collapsedRows, callback, ...props
= this.props;
return (
<Cell ...props className=css(styles.collapseCell)>
<a onClick=evt => callback(rowIndex)>collapsedRows.has(rowIndex) ? '\u25BC' : '\u25BA'</a>
</Cell>
);
const styles = StyleSheet.create(
collapseCell:
cursor: 'pointer',
,
);
TestMeet.jsx
import React, Component from 'react';
import debounce from 'lodash/debounce';
import Table, Column, Cell from 'fixed-data-table-2';
import isEmpty from 'lodash/isEmpty';
import 'fixed-data-table-2/dist/fixed-data-table.min.css';
import CollapseCell from './CollapseCell.jsx';
import SecondInnerTable from './SecondInnerTable';
const StyleSheet, css = require('aphrodite');
export default class TestMeetView extends Component
static propTypes = ;
state =
tableData: [
start: '5/19',
end: '5/20',
host: 'DACA',
,
start: '6/15',
end: '6/15',
host: 'DACA',
,
start: '6/16',
end: '6/17',
host: 'DACA',
,
start: '7/15',
end: '7/16',
host: 'DACA',
,
start: '7/30',
end: '7/31',
host: 'DACA',
,
],
columnWidths:
start: 200,
end: 200,
host: 200,
action: 100,
,
tableContainerWidth: 0,
numOfExpRows: 0,
expChildRows: ,
collapsedRows: new Set(),
scrollToRow: null,
;
componentDidMount()
this.updateWidth();
this.updateWidth = debounce(this.updateWidth, 200);
window.addEventListener('resize', this.updateWidth);
componentWillUnmount()
window.removeEventListener('resize', this.updateWidth);
onTableColumnResizeEndCallback = (newColumnWidth, columnKey) =>
this.setState(( columnWidths ) => (
columnWidths:
...columnWidths,
[columnKey]: newColumnWidth,
,
));
;
updateWidth = () =>
if (this.tableContainer.offsetWidth === this.state.tableContainerWidth)
return;
if (
this.tableContainer &&
this.tableContainer.offsetWidth !== this.state.tableContainerWidth
)
const newTableContainerWidth = this.tableContainer.offsetWidth;
this.setState(
tableContainerWidth: newTableContainerWidth,
columnWidths:
start: newTableContainerWidth / 3,
end: newTableContainerWidth / 3,
host: newTableContainerWidth / 3,
,
);
;
handleCollapseClick = (rowIndex) =>
const collapsedRows = this.state;
const shallowCopyOfCollapsedRows = new Set([...collapsedRows]);
let scrollToRow = rowIndex;
if (shallowCopyOfCollapsedRows.has(rowIndex))
shallowCopyOfCollapsedRows.delete(rowIndex);
scrollToRow = null;
else
shallowCopyOfCollapsedRows.add(rowIndex);
let numOfExpRows = 0;
if (collapsedRows.size > 0)
numOfExpRows = collapsedRows.size;
let resetExpChildRow = -1;
if (collapsedRows.has(rowIndex))
numOfExpRows -= 1;
resetExpChildRow = rowIndex;
else
numOfExpRows += 1;
if (resetExpChildRow === -1)
this.setState(
numOfExpRows,
scrollToRow,
collapsedRows: shallowCopyOfCollapsedRows,
);
else
this.setState(
numOfExpRows,
scrollToRow,
collapsedRows: shallowCopyOfCollapsedRows,
expChildRows:
...this.state.expChildRows,
[rowIndex]: 0,
,
);
;
subRowHeightGetter = (index) =>
const numExpChildRows = this.state.expChildRows[index] ? this.state.expChildRows[index] : 0;
return this.state.collapsedRows.has(index) ? 242 * (numExpChildRows + 1) + 50 : 0;
;
rowExpandedGetter = ( rowIndex, width, height ) =>
if (!this.state.collapsedRows.has(rowIndex))
return null;
const style =
height,
width: width - 10,
;
return (
<div style=style>
<div className=css(styles.expandStyles)>
<SecondInnerTable
changeNumOfExpandedRows=this.setNumOfInnerExpandedRows
parentRowIndex=rowIndex
/>
</div>
</div>
);
;
setNumOfInnerExpandedRows = (numOfExpandedRows, rowIndex) =>
this.setState(
expChildRows:
...this.state.expChildRows,
[rowIndex]: numOfExpandedRows,
,
);
;
render()
let sumOfExpChildRows = 0;
if (!isEmpty(this.state.expChildRows))
sumOfExpChildRows = Object.values(this.state.expChildRows).reduce((a, b) => a + b);
return (
<div className="test-view">
<div className="container-fluid">
<div className="mb-5" ref=el => (this.tableContainer = el)>
<Table
scrollToRow=this.state.scrollToRow
rowsCount=this.state.tableData.length
rowHeight=40
headerHeight=40
width=this.state.tableContainerWidth
height=(this.state.numOfExpRows + sumOfExpChildRows + 1) * 242
subRowHeightGetter=this.subRowHeightGetter
rowExpanded=this.rowExpandedGetter
touchScrollEnabled
onColumnResizeEndCallback=this.onTableColumnResizeEndCallback
isColumnResizing=false
>
<Column
cell=<CollapseCell callback=this.handleCollapseClick collapsedRows=this.state.collapsedRows />
fixed
width=30
/>
<Column
columnKey="start"
header=<Cell>Start</Cell>
cell=props => <Cell ...props>this.state.tableData[props.rowIndex].start</Cell>
width=this.state.columnWidths.start
isResizable
/>
<Column
columnKey="end"
header=<Cell>End</Cell>
cell=props => <Cell ...props>this.state.tableData[props.rowIndex].end</Cell>
width=this.state.columnWidths.end
isResizable
/>
<Column
columnKey="host"
header=<Cell>Host</Cell>
cell=props => <Cell ...props>this.state.tableData[props.rowIndex].host</Cell>
width=this.state.columnWidths.host
isResizable
/>
</Table>
</div>
</div>
</div>
);
const styles = StyleSheet.create(
expandStyles:
height: '242px',
margin: '10px',
,
);
SecondInnerTable.jsx
import React, Component from 'react';
import Table, Column, Cell from 'fixed-data-table-2';
import debounce from 'lodash/debounce';
import 'fixed-data-table-2/dist/fixed-data-table.min.css';
import CollapseCell from './CollapseCell';
import ThirdInnerTable from './ThirdInnerTable';
const StyleSheet, css = require('aphrodite');
export default class SecondInnerTable extends Component
state =
tableData: [
dateOfSession: '5/19/18',
timeline: '4h00m/4h30m',
entries: '400/900',
,
dateOfSession: '5/19/18',
timeline: '4h00m/4h30m',
entries: '400/900',
,
dateOfSession: '5/19/18',
timeline: '4h00m/4h30m',
entries: '400/900',
,
dateOfSession: '5/19/18',
timeline: '4h00m/4h30m',
entries: '400/900',
,
dateOfSession: '5/19/18',
timeline: '4h00m/4h30m',
entries: '400/900',
,
],
tableColumns:
dateOfSession: label: 'Date of Session', width: 150 ,
timeline: label: 'Timeline', width: 150 ,
entries: label: 'Entries', width: 150 ,
,
tableContainerWidth: 0,
tableContainerHeight: 252,
collapsedRows: new Set(),
scrollToRow: null,
;
componentDidMount()
this.updateWidth();
this.updateWidth = debounce(this.updateWidth, 200);
window.addEventListener('resize', this.updateWidth);
componentWillUnmount()
window.removeEventListener('resize', this.updateWidth);
onSessionsTableColumnResizeEndCallback = (newColumnWidth, columnKey) =>
this.setState(( tableColumns ) => (
tableColumns:
...tableColumns,
[columnKey]: label: tableColumns[columnKey].label, width: newColumnWidth ,
,
));
;
updateWidth = () =>
if (this.tableContainer.offsetWidth === this.state.tableContainerWidth)
return;
if (
this.tableContainer &&
this.tableContainer.offsetWidth !== this.state.tableContainerWidth
)
const newTableContainerWidth = this.tableContainer.offsetWidth - 20;
const newColumnsWidth = newTableContainerWidth / 3;
this.setState(( tableColumns ) => (
tableContainerWidth: newTableContainerWidth,
tableColumns:
dateOfSession: label: tableColumns.dateOfSession.label, width: newColumnsWidth ,
timeline: label: tableColumns.timeline.label, width: newColumnsWidth ,
entries: label: tableColumns.entries.label, width: newColumnsWidth ,
,
));
;
handleCollapseClick = (rowIndex) =>
const collapsedRows = this.state;
const shallowCopyOfCollapsedRows = new Set([...collapsedRows]);
let scrollToRow = rowIndex;
if (shallowCopyOfCollapsedRows.has(rowIndex))
shallowCopyOfCollapsedRows.delete(rowIndex);
scrollToRow = null;
else
shallowCopyOfCollapsedRows.add(rowIndex);
let numOfExpRows = 0;
if (collapsedRows.size > 0)
numOfExpRows = collapsedRows.size;
if (collapsedRows.has(rowIndex))
numOfExpRows -= 1;
else
numOfExpRows += 1;
this.setState(
tableContainerHeight: 252 * (numOfExpRows + 1),
scrollToRow,
collapsedRows: shallowCopyOfCollapsedRows,
,
() =>
this.props.changeNumOfExpandedRows(numOfExpRows, this.props.parentRowIndex);
,
);
;
subRowHeightGetter = index => (this.state.collapsedRows.has(index) ? 272 : 0);
rowExpandedGetter = ( rowIndex, width, height ) =>
if (!this.state.collapsedRows.has(rowIndex))
return null;
const style =
height,
width: width - 10,
;
return (
<div style=style>
<div className=css(styles.expandStyles)>
<ThirdInnerTable parentRowIndex=rowIndex />
</div>
</div>
);
;
render()
return (
<div className="mb-2" ref=el => (this.tableContainer = el)>
<Table
scrollToRow=this.state.scrollToRow
rowsCount=this.state.tableData.length
rowHeight=40
headerHeight=50
width=this.state.tableContainerWidth
height=this.state.tableContainerHeight
subRowHeightGetter=this.subRowHeightGetter
rowExpanded=this.rowExpandedGetter
touchScrollEnabled
onColumnResizeEndCallback=this.onSessionsTableColumnResizeEndCallback
isColumnResizing=false
>
<Column
cell=<CollapseCell callback=this.handleCollapseClick collapsedRows=this.state.collapsedRows />
fixed
width=30
/>
Object.keys(this.state.tableColumns).map(key => (
<Column
key=key
columnKey=key
header=<Cell>this.state.tableColumns[key].label</Cell>
cell=props => <Cell ...props>this.state.tableData[props.rowIndex][key]</Cell>
width=this.state.tableColumns[key].width
isResizable
/>
))
</Table>
</div>
);
const styles = StyleSheet.create(
expandStyles:
height: '252px',
margin: '10px',
,
);
ThirdInnerTable.jsx
import React, Component from 'react';
import debounce from 'lodash/debounce';
import Table, Column, Cell from 'fixed-data-table-2';
import 'fixed-data-table-2/dist/fixed-data-table.min.css';
export default class ThirdInnerTable extends Component
state =
tableData: [
eventNumber: '1',
qualifyingTime: 'N/A',
selected: 'N/A',
,
eventNumber: '1',
qualifyingTime: 'N/A',
selected: 'N/A',
,
eventNumber: '1',
qualifyingTime: 'N/A',
selected: 'N/A',
,
eventNumber: '1',
qualifyingTime: 'N/A',
selected: 'N/A',
,
eventNumber: '1',
qualifyingTime: 'N/A',
selected: 'N/A',
,
],
tableColumns:
eventNumber: label: 'Event number', width: 150 ,
qualifyingTime: label: 'Qualifying time', width: 150 ,
selected: label: 'Selected?', width: 150 ,
,
tableContainerWidth: 0,
numOfColumns: 3,
;
componentDidMount()
this.updateWidth();
this.updateWidth = debounce(this.updateWidth, 200);
window.addEventListener('resize', this.updateWidth);
componentWillUnmount()
window.removeEventListener('resize', this.updateWidth);
onEventsTableColumnResizeEndCallback = (newColumnWidth, columnKey) =>
this.setState(( tableColumns ) => (
tableColumns:
...tableColumns,
[columnKey]: label: tableColumns[columnKey].label, width: newColumnWidth ,
,
));
;
updateWidth = () =>
if (this.tableContainer.offsetWidth === this.state.tableContainerWidth)
return;
if (
this.tableContainer &&
this.tableContainer.offsetWidth !== this.state.tableContainerWidth
)
const newTableContainerWidth = this.tableContainer.offsetWidth;
const columnWidth = newTableContainerWidth / 3;
this.setState(( tableColumns ) => (
tableContainerWidth: newTableContainerWidth,
tableColumns:
eventNumber: label: tableColumns.eventNumber.label, width: columnWidth ,
qualifyingTime: label: tableColumns.qualifyingTime.label, width: columnWidth ,
selected: label: tableColumns.selected.label, width: columnWidth ,
,
));
;
render()
return (
<div className="mb-5" ref=el => (this.tableContainer = el)>
<Table
rowsCount=this.state.tableData.length
rowHeight=40
headerHeight=50
width=this.state.tableContainerWidth
height=252
touchScrollEnabled
onColumnResizeEndCallback=this.onEventsTableColumnResizeEndCallback
isColumnResizing=false
>
Object.keys(this.state.tableColumns).slice(0, this.state.numOfColumns).map(key => (
<Column
key=key
columnKey=key
header=<Cell>this.state.tableColumns[key].label</Cell>
cell=props => <Cell ...props>this.state.tableData[props.rowIndex][key]</Cell>
width=this.state.tableColumns[key].width
isResizable
/>
))
</Table>
</div>
);
【问题讨论】:
一切正常 @udayakumar 检查this 和this 录音 是的,我看到了你的问题。第一次点击对我有用。您只需要准确地对准黑色箭头即可。关于渲染问题,我认为这与滚动的内部组件有关。整体滚动对我来说相当滞后 【参考方案1】:我已经更新了沙盒代码,请查看下面的链接,我认为它对你有用
Code Sandbox
或者
handleCollapseClick = rowIndex =>
const collapsedRows = this.state;
const shallowCopyOfCollapsedRows = new Set([...collapsedRows]);
let scrollToRow = rowIndex;
if (shallowCopyOfCollapsedRows.has(rowIndex))
shallowCopyOfCollapsedRows.delete(rowIndex);
scrollToRow = null;
else
shallowCopyOfCollapsedRows.add(rowIndex);
let numOfExpRows = 0;
if (collapsedRows.size > 0)
numOfExpRows = collapsedRows.size;
let resetExpChildRow = -1;
if (collapsedRows.has(rowIndex))
numOfExpRows -= 1;
resetExpChildRow = rowIndex;
else
numOfExpRows += 1;
if (resetExpChildRow === -1)
this.setState(
tableContainerHeight: 250 * numOfExpRows,
scrollToRow,
collapsedRows: shallowCopyOfCollapsedRows
);
else
this.setState(
numOfExpRows,
scrollToRow,
collapsedRows: shallowCopyOfCollapsedRows,
expChildRows:
...this.state.expChildRows,
[rowIndex]: 0
);
;
【讨论】:
谢谢,但是当我尝试您的示例时,我遇到了同样的问题。我用你的沙盒创建了一个recording,你可以在其中看到问题。 好的,我会检查的@Matt 谢谢,我检查了你的codesandox,但是内表(第二层)的高度有些奇怪。我创建了一个新的recording,您可以在其中看到它。行展开后,内表的水平滚动条不可见。如果您在内表中展开/关闭行,则内表的高度不正确。无论如何,我认为我们已经接近解决方案。我正在处理某事,无法检查您的代码,但我会尽快检查。 你现在可以检查一下吗? @马特 现在看起来好多了。感谢您的帮助,您的回答应该被奖励。【参考方案2】:我应该发表评论,但我没有所需的编号。的点。你解决了这个问题吗?因为我刚刚打开了你附加的链接,它工作正常
更新 您的代码工作正常。您的方法的问题是您的点击事件是在箭头上触发的,而不是在整个 div (或单元格)上触发的。因此,您需要准确无误,只需单击箭头即可展开您的行。如果您不想要这种行为,我建议您将点击事件放在 div(或单元格)上
这是一个工作视频,证明它工作正常: https://www.useloom.com/share/2c725f3fede942b09c661a765c72634e
我从您的视频中截取了屏幕截图,显示由于您没有点击箭头,这就是您的行没有展开的原因
【讨论】:
您使用的是哪种浏览器? 我用的是chrome浏览器 我不相信你没有这个问题...你认为你可以创建一个简短的.gif
录音并将其上传到imgur,比如this吗?
好吧,让我想想。我可能误解了你的问题
你可以在this和this录音中看到这个问题以上是关于内表中的最后一行不会在固定数据表中展开的主要内容,如果未能解决你的问题,请参考以下文章
ABAP中,用Ranges定义的内表,由于数据量大导致运行错误