ag_grid_rs/
gridoptions.rs

1//! Types pertaining to defining and constructing a `Grid`.
2
3use std::{collections::HashMap, future::Future};
4
5use ag_grid_core::imports::log;
6use ag_grid_derive::FieldSetter;
7use js_sys::Function;
8use wasm_bindgen::{prelude::*, JsCast};
9use wasm_bindgen_futures::spawn_local;
10use web_sys::HtmlElement;
11
12pub use crate::shared::SortMethod;
13use crate::{
14    callbacks::{GetRowsParams, IGetRowsParams},
15    column::ColumnDef,
16    convert::ToJsValue,
17    grid::AgGrid,
18    types::OneOrMany,
19    Grid, ToJsValue as ToJsValueMacro,
20};
21/// An instance of an AG Grid [`GridOptions`].
22///
23/// With this struct, users can specify the initial options for their grid,
24/// before calling the [`GridOptions::build()`] method to receive an instance of
25/// [`Grid`]. The various options are fully customisable using the builder
26/// pattern, so you only need to specify what you need. The options mirror those
27/// used in the AG Grid library.
28///
29/// [`GridOptions`]: https://www.ag-grid.com/javascript-data-grid/grid-options/
30#[derive(FieldSetter, ToJsValueMacro)]
31#[js_value(skip_serializing_none)]
32pub struct GridOptions<T>
33where
34    T: ToJsValue,
35{
36    // Accessories
37    // TODO
38
39    // Clipboard
40    // TODO
41
42    // Column Definitions
43    /// Set the column definitions. Fields set here take precedence over those
44    /// set in `default_col_def`.
45    column_defs: Option<Vec<ColumnDef>>,
46    /// Set the default column definition. Fields set here have lower precedence
47    /// than fields set on a per-column basis in `column_defs`.
48    default_col_def: Option<ColumnDef>,
49    // default_col_group_def
50    // column_types
51    /// Keeps the order of Columns maintained after new Column Definitions are
52    /// updated.
53    maintain_column_order: Option<bool>,
54
55    /// If `true`, then dots in field names (e.g. 'address.firstLine') are not
56    /// treated as deep references. Allows you to use dots in your field name if
57    /// you prefer.
58    suppress_dot_field_notation: Option<bool>,
59
60    // Column Headers
61    /// The height in pixels for the row containing the column label header. If
62    /// not specified, it uses the theme value of `header-height`.
63    header_height: Option<u32>,
64
65    /// The height in pixels for the rows containing header column groups. If
66    /// not specified, it uses [`GridOptions::header_height`].
67    group_header_height: Option<u32>,
68
69    /// The height in pixels for the row containing the floating filters. If not
70    /// specified, it uses the theme value of `header-height`.
71    floating_filters_height: Option<u32>,
72
73    // Column Moving
74    /// Set to `true` to suppress column moving, i.e. to make the columns fixed
75    /// position.
76    suppress_movable_columns: Option<bool>,
77
78    /// If `true`, the `ag-column-moving` class is not added to the grid while
79    /// columns are moving. In the default themes, this results in no animation
80    /// when moving columns.
81    suppress_column_move_animation: Option<bool>,
82
83    /// If `true`, when you drag a column out of the grid (e.g. to the group
84    /// zone) the column is not hidden.
85    suppress_drag_leave_hides_columns: Option<bool>,
86
87    /// If `true`, when you drag a column into a row group panel the column is
88    /// not hidden.
89    suppress_row_group_hides_columns: Option<bool>,
90
91    // Column Sizing
92    /// Set to 'Shift' to have shift-resize as the default resize operation
93    /// (same as user holding down `Shift` while resizing).
94    col_resize_default: Option<ResizeMethod>,
95
96    /// Suppresses auto-sizing columns for columns. In other words, double
97    /// clicking a column's header's edge will not auto-size.
98    suppress_auto_size: Option<bool>,
99
100    /// Number of pixels to add to a column width after the auto-sizing
101    /// calculation. Set this if you want to add extra room to accommodate (for
102    /// example) sort icons, or some other dynamic nature of the header.
103    auto_size_padding: Option<u32>,
104
105    /// Set this to `true` to skip the `header_name` when `auto_size` is called
106    /// by default.
107    skip_header_on_auto_size: Option<bool>,
108
109    // Components
110    // TODO
111
112    // Editing
113    /// Set to 'FullRow' to enable Full Row Editing. Otherwise leave blank to
114    /// edit one cell at a time.
115    edit_type: Option<EditType>,
116
117    /// Set to `true` to enable Single Click Editing for cells, to start editing
118    /// with a single click.
119    single_click_edit: Option<bool>,
120
121    /// Set to `true` so that neither single nor double click starts editing.
122    suppress_click_edit: Option<bool>,
123
124    /// Set to `true` to stop cell editing when grid loses focus. The default is
125    /// that the grid stays editing until focus goes onto another cell.
126    stop_editing_when_cells_lose_focus: Option<bool>,
127
128    /// Set to `true` along with [`GridOptions::enter_moves_down_after_edit`] to
129    /// have Excel-style behaviour for the `Enter` key, i.e. pressing the
130    /// `Enter` key will move down to the cell beneath.
131    enter_moves_down: Option<bool>,
132
133    /// Set to `true` along with [`GridOptions::enter_moves_down`] to have
134    /// Excel-style behaviour for the `Enter` key, i.e. pressing the `Enter` key
135    /// will move down to the cell beneath.
136    enter_moves_down_after_edit: Option<bool>,
137
138    /// Set to `true` to enable Undo / Redo while editing.
139    undo_redo_cell_editing: Option<bool>,
140
141    /// Set the size of the undo / redo stack.
142    undo_redo_cell_editing_limit: Option<u32>,
143
144    /// Set to `true` to stop the grid updating data after and edit. When this
145    /// is set, it is intended the application will update the data, e.g. in an
146    /// external immutable store, and then pass the new dataset to the grid.
147    read_only_edit: Option<bool>,
148
149    // Export
150    /// Prevent the user from exporting the grid to CSV.
151    suppress_csv_export: Option<bool>,
152
153    /// Prevent the user from exporting the grid to Excel.
154    suppress_excel_export: Option<bool>,
155    // TODO
156
157    // Filtering
158    // TODO
159
160    // Integrated Charts
161    // TODO
162
163    // Keyboard Navigation
164    // TODO
165
166    // Loading Cell Renderers
167    // TODO
168
169    // Localisation
170    // TODO
171
172    // Master Detail
173    // TODO
174
175    // Miscellaneous
176    /// Provide a context object that is provided to different callbacks the
177    /// grid uses. Used for passing additional information to the callbacks by
178    /// your application.
179    context: Option<HashMap<String, String>>,
180
181    /// Change this value to set the tabIndex order of the Grid within your
182    /// application.
183    tab_index: Option<u32>,
184
185    /// The number of rows rendered outside the viewable area the grid renders.
186    /// Having a buffer means the grid will have rows ready to show as the user
187    /// slowly scrolls vertically.
188    row_buffer: Option<u32>,
189
190    /// Set to `true` to enable debug information from the grid and related
191    /// components. Will result in additional logging being output, but very
192    /// useful when investigating problems.
193    debug: Option<bool>,
194
195    // Overlays
196    // TODO
197
198    // Pagination
199    /// Set whether pagination is enabled.
200    pagination: Option<bool>,
201
202    /// How many rows to load per page. If
203    /// [`GridOptions::pagination_auto_page_size`] is specified, this property
204    /// is ignored.
205    pagination_page_size: Option<u32>,
206
207    /// Set to `true` so that the number of rows to load per page is
208    /// automatically adjusted by the grid so each page shows enough rows to
209    /// just fill the area designated for the grid. If `false`,
210    /// [#GridOption::pagination_page_size`] is used.
211    pagination_auto_page_size: Option<bool>,
212
213    /// Set to `true` to have pages split children of groups when using Row
214    /// Grouping or detail rows with Master Detail.
215    paginate_child_rows: Option<bool>,
216
217    /// If `true`, the default grid controls for navigation are hidden. This is
218    /// useful if `pagination=true` and you want to provide your own pagination
219    /// controls. Otherwise, when `pagination=true` the grid automatically shows
220    /// the necessary controls at the bottom so that the user can navigate
221    /// through the different pages.
222    suppress_pagination_panel: Option<bool>,
223
224    // Pivot and Aggregation
225    // TODO
226
227    // Rendering
228    /// Set to `true` to enable Row Animation.
229    animate_rows: Option<bool>,
230
231    /// Set to `true` to have cells flash after data changes.
232    enable_cell_change_flash: Option<bool>,
233
234    /// To be used in combination with
235    /// [`GridOptions::enable_cell_change_flash`], this configuration
236    /// will set the delay in milliseconds of how long a cell should remain in
237    /// its "flashed" state.
238    cell_flash_delay: Option<u32>,
239
240    /// To be used in combination with
241    /// [`GridOptions::enable_cell_change_flash`], this configuration
242    /// will set the delay in milliseconds of how long the "flashed" state
243    /// animation takes to fade away after the timer set by
244    /// [`GridOptions::cell_flash_delay`] has completed.
245    cell_fade_delay: Option<u32>,
246
247    /// Set to `true` to have cells flash after data changes even when the
248    /// change is due to filtering.
249    allow_show_change_after_filter: Option<bool>,
250
251    /// Switch between layout options.
252    dom_layout: Option<DomLayout>,
253
254    /// When `true`, the order of rows and columns in the DOM are consistent
255    /// with what is on screen.
256    ensure_dom_order: Option<bool>,
257
258    /// Set to `true` to operate the grid in RTL (Right to Left) mode.
259    enable_rtl: Option<bool>,
260
261    /// Set to `true` so that the grid doesn't virtualise the columns. For
262    /// example, if you have 100 columns, but only 10 visible due to scrolling,
263    /// all 100 will always be rendered.
264    suppress_column_virtualisation: Option<bool>,
265
266    /// Set to `true` so that the grid doesn't virtualise the rows. For example,
267    /// if you have 100 rows, but only 10 visible due to scrolling, all 100 will
268    /// always be rendered.
269    suppress_row_virtualisation: Option<bool>,
270
271    /// By default the grid has a limit of rendering a maximum of 500 rows at
272    /// once (remember the grid only renders rows you can see, so unless your
273    /// display shows more than 500 rows without vertically scrolling this will
274    /// never be an issue). This is only relevant if you are manually setting
275    /// [`GridOptions::row_buffer`] to a high value (rendering more rows than
276    /// can be seen) or if your grid height is able to display more than 500
277    /// rows at once.
278    suppress_max_rendered_row_restriction: Option<bool>,
279
280    // Row Drag and Drop
281    /// Set to `true` to enable Managed Row Dragging.
282    row_drag_managed: Option<bool>,
283
284    /// Set to `true` to enable clicking and dragging anywhere on the row
285    /// without the need for a drag handle.
286    row_drag_entire_row: Option<bool>,
287
288    /// Set to `true` to enable dragging multiple rows at the same time.
289    row_drag_multi_row: Option<bool>,
290
291    /// Set to `true` to suppress row dragging.
292    suppress_row_drag: Option<bool>,
293
294    /// Set to `true` to suppress moving rows while dragging the row drag
295    /// waffle. This option highlights the position where the row will be
296    /// placed and it will only move the row on mouse up.
297    suppress_move_when_row_dragging: Option<bool>,
298
299    // Row Full Width
300    // TODO
301
302    // Row Pinning
303    // TODO
304
305    // RowModel
306    /// Sets the row model type.
307    row_model_type: Option<RowModelType>,
308    // get_row_id
309
310    // RowModel: Client Side
311    /// Set the row data.
312    row_data: Option<Vec<T>>,
313
314    // RowModel: Infinite
315    datasource: Option<DataSource>,
316    /// How many extra blank rows to display to the user at the end of the
317    /// dataset, which sets the vertical scroll and then allows the grid to
318    /// request viewing more rows of data.
319    cache_overflow_size: Option<u32>,
320
321    /// How many requests to hit the server with concurrently. If the max is
322    /// reached, requests are queued. Set to `-1` for no maximum restriction on
323    /// requests.
324    max_concurrent_datasource_requests: Option<i32>,
325
326    /// How many rows for each block in the store, i.e. how many rows returned
327    /// from the server at a time.
328    cache_block_size: Option<u32>,
329
330    /// How many blocks to keep in the store. Default is no limit, so every
331    /// requested block is kept. Use this if you have memory concerns, and
332    /// blocks that were least recently viewed will be purged when the limit is
333    /// hit. The grid will additionally make sure it has all the blocks needed
334    /// to display what is currently visible, in case this property is set to a
335    /// low value.
336    max_blocks_in_cache: Option<u32>,
337
338    /// How many extra blank rows to display to the user at the end of the
339    /// dataset, which sets the vertical scroll and then allows the grid to
340    /// request viewing more rows of data.
341    infinite_initial_row_count: Option<u32>,
342    // TODO
343
344    // RowModel: Server Side
345    // TODO
346
347    // RowModel: Viewport
348    // TODO
349
350    // Scrolling
351    /// Set to `true` to always show the horizontal scrollbar.
352    always_show_horizontal_scroll: Option<bool>,
353
354    /// Set to `true` to always show the vertical scrollbar.
355    always_show_vertical_scroll: Option<bool>,
356
357    /// Set to `true` to debounce the vertical scrollbar. Can provide smoother
358    /// scrolling on slow machines.
359    debounce_vertical_scrollbar: Option<bool>,
360
361    /// Set to `true` to never show the horizontal scroll. This is useful if the
362    /// grid is aligned with another grid and will scroll when the other grid
363    /// scrolls. (Should not be used in combination with
364    /// [`GridOptions::always_show_horizontal_scroll`].)
365    suppress_horizontal_scrollbar: Option<bool>,
366
367    /// When `true`, the grid will not scroll to the top when new row data is
368    /// provided. Use this if you don't want the default behaviour of scrolling
369    /// to the top every time you load new data.
370    suppress_scroll_on_new_data: Option<bool>,
371
372    /// When `true`, the grid will not allow mousewheel / touchpad scroll when
373    /// popup elements are present.
374    suppress_scroll_when_popups_are_open: Option<bool>,
375
376    /// When `true`, the grid will not use animation frames when drawing rows
377    /// while scrolling. Use this if the grid is working fast enough that you
378    /// don't need animation frames and you don't want the grid to flicker.
379    suppress_animation_frame: Option<bool>,
380
381    /// When `true`, middle clicks will result in click events for cells and
382    /// rows. Otherwise the browser will use middle click to scroll the grid.
383    /// Note: Not all browsers fire click events with the middle button. Most
384    /// will fire only mousedown and mouseup events, which can be used to focus
385    /// a cell, but will not work to call the onCellClicked function.
386    suppress_middle_click_scrolls: Option<bool>,
387
388    /// When `true`, mouse wheel events will be passed to the browser. Useful if
389    /// your grid has no vertical scrolls and you want the mouse to scroll the
390    /// browser page.
391    suppress_prevent_default_on_mouse_wheel: Option<bool>,
392
393    /// Tell the grid how wide in pixels the scrollbar is, which is used in grid
394    /// width calculations. Set only if using non-standard browser-provided
395    /// scrollbars, so the grid can use the non-standard size in its
396    /// calculations.
397    scrollbar_width: Option<u32>,
398
399    // Selection
400    /// Type of row selection.
401    row_selection: Option<RowSelection>,
402
403    /// Set to `true` to allow multiple rows to be selected using single click.
404    row_multi_select_with_click: Option<bool>,
405
406    // is_row_selectable
407    /// If `true`, rows will not be deselected if you hold down `Ctrl` and click
408    /// the row or press `Space`.
409    suppress_row_deselection: Option<bool>,
410
411    /// If `true`, row selection won't happen when rows are clicked. Use when
412    /// you only want checkbox selection.
413    suppress_row_click_selection: Option<bool>,
414
415    /// If `true`, cells won't be focusable. This means keyboard navigation will
416    /// be disabled for grid cells, but remain enabled in other elements of the
417    /// grid such as column headers, floating filters, tool panels.
418    suppress_cell_focus: Option<bool>,
419
420    /// Set to `true` to be able to select the text within cells. Note: When
421    /// this is set to true, the clipboard service is disabled.
422    enable_cell_text_selection: Option<bool>,
423
424    // Sorting
425    /// Vector defining the order in which sorting occurs (if sorting is
426    /// enabled).
427    sorting_order: Option<Vec<SortMethod>>,
428
429    /// Set to `true` to specify that the sort should take accented characters
430    /// into account. If this feature is turned on the sort will be slower.
431    accented_sort: Option<bool>,
432
433    /// Set to `true` to show the 'no sort' icon.
434    #[js_value(rename = "unSortIcon")]
435    unsort_icon: Option<bool>,
436
437    /// Set to `true` to suppress multi-sort when the user shift-clicks a column
438    /// header.
439    suppress_multi_sort: Option<bool>,
440
441    /// Set to `true` to always multi-sort when the user clicks a column header,
442    /// regardless of key presses.
443    always_multi_sort: Option<bool>,
444
445    /// Set to 'Ctrl' to have multi sorting work using the `Ctrl` (or `Command
446    /// ⌘` for Mac) key.
447    multi_sort_key: Option<MultiSortKey>,
448
449    /// Set to `true` to suppress sorting of un-sorted data to match original
450    /// row data.
451    suppress_maintain_unsorted_order: Option<bool>,
452
453    /// When enabled, sorts only the rows added/updated by a transaction.
454    delta_sort: Option<bool>,
455
456    // Styling
457    /// Default row height in pixels.
458    row_height: Option<u32>,
459
460    /// CSS class(es) for all rows. Provide either a string (class name) or
461    /// vector of strings (vector of class names).
462    row_class: Option<OneOrMany<String>>,
463
464    /// Set to `true` to not highlight rows by adding the `ag-row-hover` CSS
465    /// class.
466    suppress_row_hover_highlight: Option<bool>,
467
468    /// Uses CSS `top` instead of CSS `transform` for positioning rows. Useful
469    /// if the transform function is causing issues such as used in `row
470    /// spanning`.
471    suppress_row_transform: Option<bool>,
472
473    /// Set to `true` to highlight columns by adding the `ag-column-hover` CSS
474    /// class.
475    column_hover_highlight: Option<bool>,
476
477    // Tooltips
478    /// Set to `true` to use the browser's default tooltip instead of using the
479    /// grid's Tooltip Component.
480    enable_browser_tooltips: Option<bool>,
481
482    /// The delay in milliseconds that it takes for tooltips to show up once an
483    /// element is hovered over. Note: This property does not work if
484    /// [`GridOptions::enable_browser_tooltips`] is `true`.
485    tooltip_show_delay: Option<u32>,
486
487    /// The delay in milliseconds that it takes for tooltips to hide once they
488    /// have been displayed. Note: This property does not work if
489    /// [`GridOptions::enable_browser_tooltips`] is `true`.
490    tooltip_hide_delay: Option<u32>,
491
492    /// Set to `true` to have tooltips follow the cursor once they are
493    /// displayed.
494    tooltip_mouse_track: Option<bool>,
495}
496
497impl<T> GridOptions<T>
498where
499    T: ToJsValue,
500{
501    pub fn new() -> Self {
502        Default::default()
503    }
504
505    /// A finaliser method for the [`GridOptions`] struct. This method
506    /// constructs the underlying JavaScript grid and returns a handle,
507    /// [`Grid`], which provides access to the grid APIs.
508    pub fn build(self, div: HtmlElement) -> Grid {
509        let grid_options = self.to_js_value();
510
511        let js_grid = AgGrid::new(div, grid_options);
512
513        Grid {
514            api: js_grid.gridOptions().api(),
515            column_api: js_grid.gridOptions().columnApi(),
516        }
517    }
518}
519
520/// Allowed values for [`GridOptions::multi_sort_key`].
521#[derive(ToJsValueMacro)]
522pub enum MultiSortKey {
523    Ctrl,
524}
525
526/// Allowed values for [`GridOptions::dom_layout`].
527#[derive(ToJsValueMacro)]
528pub enum DomLayout {
529    Normal,
530    Print,
531    AutoHeight,
532}
533
534/// Allowed values for [`GridOptions::edit_type`].
535#[derive(ToJsValueMacro)]
536pub enum EditType {
537    FullRow,
538}
539
540/// Allowed values for [`GridOptions::col_resize_default`].
541#[derive(ToJsValueMacro)]
542pub enum ResizeMethod {
543    Shift,
544}
545
546/// Allowed values for [`GridOptions::row_selection`].
547#[derive(ToJsValueMacro)]
548pub enum RowSelection {
549    Single,
550    Multiple,
551}
552
553/// Allowed values for [`GridOptions::row_model_type`].
554#[derive(ToJsValueMacro)]
555pub enum RowModelType {
556    Infinite,
557    Viewport,
558    ClientSide,
559    ServerSide,
560}
561
562/// A struct passed to the JavaScript grid which is used by AG Grid to fetch the
563/// requested data from the server.
564#[wasm_bindgen]
565#[derive(ToJsValueMacro)]
566pub struct DataSource {
567    #[wasm_bindgen(readonly, getter_with_clone, js_name = getRows)]
568    pub get_rows: Function,
569}
570
571/// Builder for the [`DataSource`].
572pub struct DataSourceBuilder {
573    // Callback the grid calls that the user implements to fetch rows from the
574    // server.
575    get_rows: Closure<dyn FnMut(IGetRowsParams)>,
576    // row_count is deprecated. Use GridOptions.infiniteInitialRowCount instead:
577    // https://github.com/ag-grid/ag-grid/blob/7358e4286fd52946c4fe24bd26b5fbe7fd3b22d4/community-modules/core/src/ts/interfaces/iDatasource.ts#L7-L9
578    //row_count: Option<u32>,
579}
580
581impl DataSourceBuilder {
582    /// Start constructing a new `DataSourceBuilder` by providing a callback
583    /// function which will receive [`GetRowsParams`]. This callback is
584    /// called by AG Grid to request new rows from the server.
585    pub fn new<F, Fut, T>(mut get_rows: F) -> Self
586    where
587        F: FnMut(GetRowsParams) -> Fut + 'static,
588        Fut: Future<Output = Result<(Vec<T>, Option<u32>), Box<dyn std::error::Error>>> + 'static,
589        T: ToJsValue,
590    {
591        let get_rows =
592            Closure::<dyn FnMut(IGetRowsParams)>::new(move |js_params: IGetRowsParams| {
593                let params = (&js_params).into();
594                let fut = get_rows(params);
595
596                let wrapper = async move {
597                    match fut.await {
598                        Ok((data, last_row_index)) => {
599                            let data = data.to_js_value();
600                            let last_row_index = last_row_index.to_js_value();
601                            js_params
602                                .success_callback()
603                                .call2(&JsValue::null(), &data, &last_row_index)
604                                .expect("failed calling success callback");
605                        }
606                        Err(e) => {
607                            log(&format!("Error calling get_rows callback: {e:?}"));
608                            js_params
609                                .fail_callback()
610                                .call0(&JsValue::null())
611                                .expect("failed calling failure callback");
612                        }
613                    };
614                };
615
616                spawn_local(wrapper)
617            });
618
619        Self { get_rows }
620    }
621
622    /// Finalise construction of a [`DataSource`].
623    pub fn build(self) -> DataSource {
624        DataSource {
625            get_rows: self.get_rows.into_js_value().unchecked_into(),
626        }
627    }
628}