Skip to content

Commit 14e6c37

Browse files
committed
infinite scrolling for big tables
with more than 10k rows
1 parent 779a0ac commit 14e6c37

File tree

2 files changed

+84
-16
lines changed

2 files changed

+84
-16
lines changed

REQUIRE

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,4 @@ Tables
55
JSON
66
TableTraits
77
IteratorInterfaceExtensions
8+
Observables

src/TableView.jl

Lines changed: 83 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
module TableView
22
using Tables, TableTraits, IteratorInterfaceExtensions
33
using WebIO, JSExpr, JSON, Dates
4+
using Observables: @map
45

56
function showtable(x; dark = false)
67
if Tables.istable(typeof(x))
@@ -13,6 +14,11 @@ function showtable(x; dark = false)
1314
end
1415

1516
function _showtable(table, dark)
17+
length(Tables.rows(table)) > 10_000 ? _showtable_async(table, dark) :
18+
_showtable_sync(table, dark)
19+
end
20+
21+
function _showtable_sync(table, dark)
1622
schema = Tables.schema(table)
1723
names = schema.names
1824
types = schema.types
@@ -37,7 +43,7 @@ function _showtable(table, dark)
3743
:enableSorting => true,
3844
:enableFilter => true,
3945
:enableColResize => true,
40-
:multiSortKey => "ctrl"
46+
:multiSortKey => "ctrl",
4147
)
4248

4349
handler = @js function (agGrid)
@@ -54,27 +60,88 @@ function _showtable(table, dark)
5460
w
5561
end
5662

63+
64+
function _showtable_async(table, dark)
65+
schema = Tables.schema(table)
66+
names = schema.names
67+
types = schema.types
68+
rows = Tables.rows(table)
69+
70+
w = Scope(imports=["https://unpkg.com/ag-grid-community/dist/ag-grid-community.min.noStyle.js",
71+
"https://unpkg.com/ag-grid-community/dist/styles/ag-grid.css",
72+
"https://unpkg.com/ag-grid-community/dist/styles/ag-theme-balham$(dark ? "-dark" : "").css",])
73+
74+
coldefs = [(
75+
headerName = n,
76+
headerTooltip = types[i],
77+
field = n,
78+
type = types[i] <: Union{Missing, T where T <: Number} ? "numericColumn" : nothing,
79+
filter = types[i] <: Union{Missing, T where T <: Dates.Date} ? "agDateColumnFilter" :
80+
types[i] <: Union{Missing, T where T <: Number} ? "agNumberColumnFilter" : nothing
81+
) for (i, n) in enumerate(names)]
82+
83+
rowinds = Observable(w, "startrow", [1, 100, ""])
84+
requestedrows = Observable(w, "requestedrows", "[]")
85+
on(rowinds) do x
86+
requestedrows[] = table2json(rows, names, types, requested = x[1:2])
87+
end
88+
89+
onjs(requestedrows, @js function (val)
90+
$rowinds[][2](JSON.parse(val))
91+
end)
92+
93+
options = Dict(
94+
:columnDefs => coldefs,
95+
# :enableSorting => true,
96+
# :enableFilter => true,
97+
:enableColResize => true,
98+
:multiSortKey => "ctrl",
99+
:rowModelType => "infinite",
100+
:datasource => Dict(
101+
"getRows" =>
102+
@js function (rowParams)
103+
$rowinds[] = [rowParams.startRow, rowParams.endRow, rowParams.successCallback]
104+
end
105+
)
106+
)
107+
108+
handler = @js function (agGrid)
109+
gridOptions = $options
110+
# gridOptions.rowData = JSON.parse(gridOptions.rowData)
111+
this.table = @new agGrid.Grid(this.dom.querySelector("#grid"), gridOptions)
112+
gridOptions.columnApi.autoSizeColumns($names)
113+
end
114+
onimport(w, handler)
115+
w.dom = dom"div#grid"(className = "ag-theme-balham$(dark ? "-dark" : "")",
116+
style=Dict(:width => "100%",
117+
"min-width" => "400px",
118+
:height => "800px"))
119+
w
120+
end
121+
57122
# directly write JSON instead of allocating temporary dicts etc
58-
function table2json(rows, names, types)
123+
function table2json(rows, names, types; requested = nothing)
59124
io = IOBuffer()
60125
print(io, '[')
61-
for row in rows
62-
print(io, '{')
63-
i = 1
64-
for col in Tables.eachcolumn(row)
65-
JSON.print(io, names[i])
66-
i += 1
67-
print(io, ':')
68-
if col isa Number
69-
JSON.print(io, col)
70-
else
71-
JSON.print(io, sprint(print, col))
126+
for (i, row) in enumerate(rows)
127+
if requested == nothing || first(requested) <= i <= last(requested)
128+
print(io, '{')
129+
i = 1
130+
for col in Tables.eachcolumn(row)
131+
JSON.print(io, names[i])
132+
i += 1
133+
print(io, ':')
134+
if col isa Number
135+
JSON.print(io, col)
136+
else
137+
JSON.print(io, sprint(print, col))
138+
end
139+
print(io, ',')
72140
end
141+
skip(io, -1)
142+
print(io, '}')
73143
print(io, ',')
74144
end
75-
skip(io, -1)
76-
print(io, '}')
77-
print(io, ',')
78145
end
79146
skip(io, -1)
80147
print(io, ']')

0 commit comments

Comments
 (0)