I'm creating excel-like table using react. And there have some essential features.
- Support update feature for the cells including child row's cells.
- If head row's data can represents all of it's children's data and itself, it's cell will be merged into single cell and show in single cell.
- Support row expanding feature :: When user click row, it expand and show it's children's data which has same columns with parent. (Like each row represents some aggregation of data, and with clicking row, user can see sub-data.
- Should guarantee proper performance for more than 30000 rows with 100 columns including images.
- Should support filter & sort & search & hide column(s).
- Should provide data at single page (It means it need to be infinite-scroll, not pagenation)
- Should have sticky table header
- Should user can fix some of columns to left side for providing easier way to see data with horizontal scrolling.
I succeed on 1,2,3,4,5,6,7 (Most of them) by react-virtualized. But it become a problem when regarding '8'-Fixing column. I checked internet and found that react-virtualized is the only way to archive it.
Basic idea of this is quite simple. I use List
for rendering each row by user's scrolling(Virtualization), AutoSizer
and CellMeasurer(Cache)
for implementing dynamic height rows(Expanding rows). And least of codes for implementing TableHeader and cell updating, sort, filter features.
But it became a problem when I need to implement column fix
. react-virtualized
seems it dose not allow customization for it's feature (Seems really static for their functionalities.)
At first, I considered create two table and position it horizontally so that left table act like fixed column, right table is horizontally scrollable by sharing CellMeasurerCache for dynamic height row. But I found this article https://stackoverflow.com/questions/45682063/react-virtualized-share-cellmeasurercache-for-multiple-grids
which says that CellMeasurerCache is not sharable by more than one List.
Also I considered that using other components react-virtualized
support. But there are Pros and Cons for each components and I need to give up one of above requirements.
Can you provide me a idea for implementing all above requirements?
I want to share my code but it is quite big (About more than 1000lines for single table -- abstract table which is not hard coded for single purpose) If you want to see, I'll send you in anyway.
But I can provide basic HTML markups -- which is 8
is not implemented. and proven to be usable disregarding some bugs and errors.
This is not real HTML, I omit some of markups. (All data is not calculated at table, all of them are fetched from other servers.)
<div class="table">
<!--Head part-->
<div class="headers">
<div class="header" style="display: sticky; top: 0">
<div class="upper">Name</div>
<div class="bottom">
<button class="sort" style="background-image: url(sort_asc.png)"></button>
<button class="filter" style="background-image: url(btn_filter.png)"></button>
</div>
</div>
<div class="header" style="display: sticky; top: 0">
<div class="upper">Price</div>
<div class="bottom">
<button class="sort" style="background-image: url(sort_asc.png)"></button>
<button class="filter" style="background-image: url(btn_filter.png)"></button>
</div>
</div>
<div class="header" style="display: sticky; top: 0">
<div class="upper">Gross</div>
<div class="bottom">
<button class="sort" style="background-image: url(sort_asc.png)"></button>
<button class="filter" style="background-image: url(btn_filter.png)"></button>
</div>
</div>
</div>
<!--Content part-->
<div class="row"/> <!-- This is expanded row -->
<div class="column" style="display:flex;flex-direction:column; height:120px;"/>
<div class="headCell" style="height:120px">ChicagoCompany</div> <!-- This is merged cell -->
<div>
<div class="column" style="display:flex;flex-direction:column; height:120px;"/>
<div class="headCell" style="height:40px">215</div> <!-- Display average value of child -->
<div class="cell" style="height:40px">230</div>
<div class="cell" style="height:40px">200</div>
<div>
<div class="column" style="display:flex;flex-direction:column; height:120px;"/>
<div class="headCell"style="height:120px">440</div> <!-- This is merged cell -->
<div>
</div>
<div class="row"/> <!-- This is not expanded row -->
<div class="column" style="display:flex;flex-direction:columnheight:40px"/>
<div class="headCell"style="height:40px">Seattle Corp</div> <!-- This is merged cell -->
<div>
<div class="column" style="display:flex;flex-direction:columnheight:40px"/>
<div class="headCell"style="height:40px">130</div> <!-- Display average value of child -->
<div>
<div class="column" style="display:flex;flex-direction:columnheight:40px"/>
<div class="headCell"style="height:40px">440</div> <!-- This is merged cell -->
<div>
</div>
</div>
What I considered above about append two table horizontally is like above
<div class="tableSet"><div class="fixedTable">...</div><div class="flexibleTable">...</div></div>
(Put two "table" together horizontally)
I tried to set sticky to all class <column
>, but it dose not work as I expected. (It is not the same-level properties as you know.)
I think I can bypass restriction on CellMeaurerCache
so that it can be shared in both table. But I have no idea for that. Can you give me a advice?
Is there any way to bypass restriction and implement all requirements? Or Is there any library or component or way
to achieve it's goal even if it need to be re-build from the scratch?
Yes. It looks like that I want to Excel on webpage.