4545
4646showtable (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
100142end
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)
119159end
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