Skip to content

Commit 7cadb53

Browse files
committed
add edit callback
1 parent 86a9799 commit 7cadb53

File tree

1 file changed

+51
-15
lines changed

1 file changed

+51
-15
lines changed

src/TableView.jl

Lines changed: 51 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,20 @@ end
4545

4646
showtable(table::AbstractMatrix; kwargs...) = showtable(Tables.table(table); kwargs...)
4747

48-
function showtable(table; dark = false, height = :auto, width = "100%")
48+
"""
49+
showtable(table; dark = false, height = :auto, width = "100%", cell_changed = nothing)
50+
51+
Return a `WebIO.Scope` that displays the provided `table`.
52+
53+
Optional arguments:
54+
- `dark`: Switch to a dark theme.
55+
- `height`/`width`: CSS attributes specifying the output height and with.
56+
- `cell_changed`: Either `nothing` or a function that takes a single argument with the fields
57+
`"new"`, `"old"`, `"row"`, and `"col"`. This function is called whenever the
58+
user edits a table field. Note that all values will be strings, so you need to
59+
do the necessary conversions yourself.
60+
"""
61+
function showtable(table; dark = false, height = :auto, width = "100%", cell_changed = nothing)
4962
rows = Tables.rows(table)
5063
tablelength = Base.IteratorSize(rows) == Base.HasLength() ? length(rows) : nothing
5164

@@ -76,15 +89,43 @@ function showtable(table; dark = false, height = :auto, width = "100%")
7689
names = schema.names
7790
types = schema.types
7891
end
92+
93+
async = tablelength === nothing || tablelength > 10_000
94+
7995
w = Scope(imports = ag_grid_imports)
8096

97+
onCellValueChanged = @js function () end
98+
if cell_changed != nothing
99+
onedit = Observable(w, "onedit", Dict{Any,Any}(
100+
"row" => 0,
101+
"col" => 0,
102+
"old" => 0,
103+
"new" => 0
104+
))
105+
on(onedit) do x
106+
cell_changed(x)
107+
end
108+
109+
onCellValueChanged = @js function (ev)
110+
$onedit[] = Dict(
111+
"row" => ev.rowIndex,
112+
"col" => ev.colDef.headerName,
113+
"old" => ev.oldValue,
114+
"new" => ev.newValue
115+
)
116+
end
117+
end
118+
81119
coldefs = [(
82120
headerName = n,
121+
editable = cell_changed !== nothing,
83122
headerTooltip = types[i],
84123
field = n,
124+
sortable = !async,
125+
resizable = true,
85126
type = types[i] <: Union{Missing, T where T <: Number} ? "numericColumn" : nothing,
86-
filter = types[i] <: Union{Missing, T where T <: Dates.Date} ? "agDateColumnFilter" :
87-
types[i] <: Union{Missing, T where T <: Number} ? "agNumberColumnFilter" : nothing
127+
filter = async ? false : types[i] <: Union{Missing, T where T <: Dates.Date} ? "agDateColumnFilter" :
128+
types[i] <: Union{Missing, T where T <: Number} ? "agNumberColumnFilter" : false
88129
) for (i, n) in enumerate(names)]
89130

90131
id = string("grid-", string(uuid1())[1:8])
@@ -93,19 +134,18 @@ function showtable(table; dark = false, height = :auto, width = "100%")
93134
"height" => to_css_size(height)),
94135
id = id)
95136

96-
tablelength === nothing || tablelength > 10_000 ? _showtable_async!(w, names, types, rows, coldefs, tablelength, dark, id) :
97-
_showtable_sync!(w, names, types, rows, coldefs, tablelength, dark, id)
137+
showfun = async ? _showtable_async! : _showtable_sync!
138+
139+
showfun(w, names, types, rows, coldefs, tablelength, dark, id, onCellValueChanged)
98140

99141
w
100142
end
101143

102-
function _showtable_sync!(w, names, types, rows, coldefs, tablelength, dark, id)
144+
function _showtable_sync!(w, names, types, rows, coldefs, tablelength, dark, id, onCellValueChanged)
103145
options = Dict(
146+
:onCellValueChanged => onCellValueChanged,
104147
:rowData => JSONText(table2json(rows, names, types)),
105148
:columnDefs => coldefs,
106-
:enableSorting => true,
107-
:enableFilter => true,
108-
:enableColResize => true,
109149
:multiSortKey => "ctrl",
110150
)
111151

@@ -119,7 +159,7 @@ function _showtable_sync!(w, names, types, rows, coldefs, tablelength, dark, id)
119159
end
120160

121161

122-
function _showtable_async!(w, names, types, rows, coldefs, tablelength, dark, id)
162+
function _showtable_async!(w, names, types, rows, coldefs, tablelength, dark, id, onCellValueChanged)
123163
rowparams = Observable(w, "rowparams", Dict("startRow" => 1,
124164
"endRow" => 100,
125165
"successCallback" => @js v -> nothing))
@@ -133,15 +173,11 @@ function _showtable_async!(w, names, types, rows, coldefs, tablelength, dark, id
133173
end)
134174

135175
options = Dict(
176+
:onCellValueChanged => onCellValueChanged,
136177
:columnDefs => coldefs,
137-
# can't sort or filter asynchronously loaded data without backend support,
138-
# which we don't have yet
139-
:enableSorting => false,
140-
:enableFilter => false,
141178
:maxConcurrentDatasourceRequests => 1,
142179
:cacheBlockSize => 1000,
143180
:maxBlocksInCache => 100,
144-
:enableColResize => true,
145181
:multiSortKey => "ctrl",
146182
:rowModelType => "infinite",
147183
:datasource => Dict(

0 commit comments

Comments
 (0)