45
45
46
46
showtable (table:: AbstractMatrix ; kwargs... ) = showtable (Tables. table (table); kwargs... )
47
47
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 )
49
62
rows = Tables. rows (table)
50
63
tablelength = Base. IteratorSize (rows) == Base. HasLength () ? length (rows) : nothing
51
64
@@ -76,15 +89,43 @@ function showtable(table; dark = false, height = :auto, width = "100%")
76
89
names = schema. names
77
90
types = schema. types
78
91
end
92
+
93
+ async = tablelength === nothing || tablelength > 10_000
94
+
79
95
w = Scope (imports = ag_grid_imports)
80
96
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
+
81
119
coldefs = [(
82
120
headerName = n,
121
+ editable = cell_changed != = nothing ,
83
122
headerTooltip = types[i],
84
123
field = n,
124
+ sortable = ! async,
125
+ resizable = true ,
85
126
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
88
129
) for (i, n) in enumerate (names)]
89
130
90
131
id = string (" grid-" , string (uuid1 ())[1 : 8 ])
@@ -93,19 +134,18 @@ function showtable(table; dark = false, height = :auto, width = "100%")
93
134
" height" => to_css_size (height)),
94
135
id = id)
95
136
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)
98
140
99
141
w
100
142
end
101
143
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 )
103
145
options = Dict (
146
+ :onCellValueChanged => onCellValueChanged,
104
147
:rowData => JSONText (table2json (rows, names, types)),
105
148
:columnDefs => coldefs,
106
- :enableSorting => true ,
107
- :enableFilter => true ,
108
- :enableColResize => true ,
109
149
:multiSortKey => " ctrl" ,
110
150
)
111
151
@@ -119,7 +159,7 @@ function _showtable_sync!(w, names, types, rows, coldefs, tablelength, dark, id)
119
159
end
120
160
121
161
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 )
123
163
rowparams = Observable (w, " rowparams" , Dict (" startRow" => 1 ,
124
164
" endRow" => 100 ,
125
165
" successCallback" => @js v -> nothing ))
@@ -133,15 +173,11 @@ function _showtable_async!(w, names, types, rows, coldefs, tablelength, dark, id
133
173
end )
134
174
135
175
options = Dict (
176
+ :onCellValueChanged => onCellValueChanged,
136
177
: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 ,
141
178
:maxConcurrentDatasourceRequests => 1 ,
142
179
:cacheBlockSize => 1000 ,
143
180
:maxBlocksInCache => 100 ,
144
- :enableColResize => true ,
145
181
:multiSortKey => " ctrl" ,
146
182
:rowModelType => " infinite" ,
147
183
:datasource => Dict (
0 commit comments