Skip to content

Data Grid

Gabi edited this page May 10, 2024 · 50 revisions

Data Grid is a table providing advanced functionalities such as row grouping for the given foundset.

This table component is designed to work with large data, potentially infinite, since data is loaded lazily into the table even when grouped; group nodes are loaded lazily with incremental scrolling and children of groups are loaded only when the nodes are expanded; also children of groups are loaded incrementally with scrolling.

IMPORTANT ! Grouping is not yet supported for foundset having multiple primary key columns. To use grouping feature of this component the foundset MUST have a single primary key.

Note: since all data is loaded lazily on demand, the table doesn't provide any built in aggregation functionality such as count, sum, max, min etc.

Grouping Table

Table of contents

Features

The table fetch data from a foundset; as common table components it can be bound to the form's foundset, to a related foundset, to a separate foundset or to a named foundset. It has typical table features, (fixed) table header, formats, styling, cell editing, column resize, column move, column sort, valuelist support (for translating a real value to a display value). The model and API can be seen in Servoy Developer.

The table can be grouped on any foundset's dataprovider or related dataprovider by setting the rowGroupIndex in the column's properties. The grouped columns can be configured at design time and the user can change grouping criteria at runtime if enableRowGroup is true.

IMPORTANT ! Calculations Aggregations or form variables SHOULD not be used in group mode and enableRowGroup MUST be set to false.

When there are no groups it behaves like a common readOnly table, however it has a limited set of features compared to the default table of Servoy or the Servoy Extra Table.

Unsupported features

Currently the table doesn't support the following features

  • The grouping cannot be performed if the foundset has multiple primary keys. A single primary key is required.
  • The table doesn't support paging but only infinite scrolling.

At Servoy we are aware of the importance of these features and our intention is to integrate relevant features during the next releases of the grouping table component.

Data changes and Data broadcast

When the table is showing plain rows without grouped columns it updates spontaneously it’s rows at any data change which affect the rows visible in the table viewport; as common tables in Servoy the table component receive foundset updates which may be originated from a foundset update within the client itself or from a data broadcast update; it always presents the latest data to the user when the columns are not grouped.

This is not the case when the table is grouping one ore more columns; a data update may affect how the group are displayed; a new group node or sub-node may be created or even removed after a data update. Adding and removing groups on the fly will result on a bad user experience therefore the table component doesn’t react proactively to data updates.

The table lets the user to ask for latest data with a “Refresh Data” action; the refresh button will show up to the top-right corner of the table when there are grouped columns.

When the table receives any data change ( either a record insert, a record delete or a record update for any of the columns in table ) which affect the records in it’s viewport, the table will notify the user highlighting the “Refresh Data” action; by default the refresh button is colored as orange to notify the user of a pending data change. You can style in CSS the refresh button when highlighted with the .ag-table-info-notify style Class.

Notice that, for obvious perfomance reasons, the table components won’t listen for data changes on the whole foundset’s table (and related foundset table) but only for the data in table's viewport; the implication of this is that if a table record, which is not in viewport, is being updated (for instance the client receives a data broadcast from another client) the table component won’t be notified even if the update may result in a new group node within the table viewport.

If you would like to notify the table component of ANY data change, you can use the notifyDataChange api of the component. The notifyDataChange api is best use in conjunction with the onDataBroadcast event of Servoy to notify the table of any data change from other clients and with the onAfterRecordInsert, onAfterRecordUpdate, onAfterRecordDelete events to notify the table of any data changes within the client; the client doesn’t receive a data broadcast notification for it’s own changes, therefore if the foundset’s record (or the related foundset’s record if related dataproviders are used in columns), which are not in the viewport, are changed in background you can rely on the onAfterRecordInsert/Update/Delete, or proactively notify the table component in your business logic. Please note that it’s not necessary to notify the table component is the component is not visible; the component will always present the latest data when rendered again.

Record selection

When the table is showing plain rows without grouped columns it highlights the selected record in foundset; if the selected record in foundset is changed serverside the table will change the selection to the new record however it won't scroll to the selected record but will remain to it's position.

When the table is grouping one ore more columns instead the record selection is disabled. If you would like to use change the selected record in foundset you can use the onCellClickEvent to change record selection on the foundset. Please note that the foundsetIndex param of the onCellClickEvent will always be -1 when there are grouped columns; use the pks of the record object to select the clicked record.

Configuration

The table is configurable from Properties View - in Developer. In the future more properties will be configurable at runtime via scripting.

Grid Height in Responsive Form

It can be used both in responsive forms and absolute forms. If used in responsive mode, its 'responsiveHeight' property must be set in Properties View (which is the fixed height it will occupy).

Adding a table in a flex-content layout and setting the table responsiveHeight property to 0, let the table grow up to 100% height of parent element (see more on flex-layout here). Used with other containers than flex-content layout in order to grow the table to 100% height, the parent element must have a known height.

Using custom cell editor

It is possible to use a form as a custom editor, by setting the 'editType' of a column to 'FORM' and 'editForm' to the desired form. When a cell will enter edit mode, the form will be shown in a popup and the 'onColumnFormEditStarted' handler will be called; this is where you can setup the values displayed in the form. To update the edited cell value with the result of the form editor, the 'setFormEditorValue' api function should be used (ex. if you have a save/ok button in the editor, this is the function that you need to call to set the result of the editing). In order to stop the editing and close the form editor popup, the 'stopCellEditing' api should be used.

Styling Grouping Table

There are several CSS class selectors you can use for fine-grained styling of the grouping table component.

element selector summary
.ag-table style the whole table component
.ag-table-info style the refresh icon
.ag-table-info-nofity style the refresh icon when is notified of pending data changes
.ag-header the table header
.ag-body the table body
.ag-header-cell style the header cell
.ag-header-label style the label text
.ag-row style the row
.ag-row even style the even rows
.ag-row-odd style the odd rows
.ag-row style the row
.ag-row-selected style the selected row
.ag-row-level-x style the row at group level x; when rows are grouped each row will have a row-level-x class where x is the level index, starting from 0.
.ag-icon style the icons.
.ag-column-drop-cell style the droppable column in the row group panel
.ag-column-drop-cell-text style the label in the droppable column of the row group panel
.ag-column-drop-cell-button style the remove button in the droppable column of the row group panel
.ag-table-header-tooltip style the header column tooltip
.ag-table-cell-tooltip style the column cell tooltip

Column

Type Property Default Description
DataProvider dataprovider The dataprovider of the column.
Boolean enableRowGroup true Allow the user to group or ungroup the column.
String format The format to be use for the dataprovider.
String headerStyleClass The column's header style Classes.
Number headerGroupIndex Position of header group, 0-based"; by default it is placed at the end.
String headerTitle The column's header text.
String headerTooltip The column's header tooltip.
String headerGroup Header group, that this column will be part of.
String headerGroupStyleClass Header group style Class
Boolean headerCheckbox When true the column has checkbox for selecting/unselecting all rows
Number rowGroupIndex -1 Set the rowGroupIndex to group on the column; the index defines the order of the group when there are multiple grouped columns. The index is 0-based. Set the rowGroupIndex to -1 when the column is not used as group criteria.
String styleClass ag-fresh Table style Classes.
DataProvider styleClassDataprovider Use a Servoy calculation as styleClassDataprovider to set styleClass conditionally to the table cell. The calculation should return the class name (or names) to be applied to the table cell.
Valuelist valuelist true Valuelist to resolve the dataprovider realValue into the displayValue.
Boolean visible true If the column is visible or not.
Number width 0 Set the column's width. Auto-size itself when the width is 0.
Number minWidth Set the column's minimum width.
Number maxWidth Set the column's maximum width.
Boolean enableSort true If the column can be sorted.
Boolean enabledResize true If the column can be resized.
Boolean enableToolPanel true If the column should be visible in the tool panel.
Boolean autoResize true If the column should auto resize when the table's width is changing.
DataProvider isEditableDataprovider Use a Servoy calculation as isEditableDataprovider to set edit state conditionally to the table cell. The calculation should return non-zero number to be editable.
String editType null (NONE) Type of editing used for that column. Can be one of the followings: null (NONE), TEXTFIELD, DATEPICKER, COMBOBOX, TYPEAHEAD, FORM, CHECKBOX.
Form editForm Form used as custom editor.
String id Used to set the column id (colId) property in the serialized column state json string of getColumnState and onColumnStateChanged.
Map columnDef Map where additional column properties of ag-grid can be set (see https://www.ag-grid.com/javascript-grid-column-properties/ ).
DataProvider tooltip Tooltip used for cells.
String filterType null (NONE) Type of filter used for that column. Can be one of the followings: null (NONE), TEXT, NUMBER, DATE, VALUELIST, RADIO. When TEXT is used, it is possible to filter on null values using '^' , or on null/empty string values using '^=' as value, along with equals or not equals operators. NOTE: When a filter is applied, NGGrids uses the Servoy API 'addFoundSetFilterParam' to add a custom filter to the grid's foundset, that will be removed when the filter is cleared or the grid is hidden. That also means that the selected index when the filter is applied is different then that of the foundset without filter, so when you navigate away from a filtered grid (it is hidden and filter removed), you can't use its selected index on the same foundset in a different form, where it will be without the filter - you should rely on the pk of the selected record, save that in the filtered grid and use that in the new form.
Boolean dndSource Allow dragging.
DataProvider dndSourceDataprovider Boolean dataprovider for allow/disallow dragging.

Grouping Table Properties

Type Property Default Description
Column columns List all columns to be used in table as dataprovider.
Boolean enableColumnResize true Allow the user to resize columns.
Boolean enableSorting true Enable column sorting by clickin on the column's header.
Boolean groupUserEntireRow true When true the group takes the entire row.
Boolean groupCheckbox false When true the group has checkbox for selecting/unselecting.
String iconGroupContracted glyphicon glyphicon-plus ag-icon Font Icon used as icon for the group row when is contracted.
String iconGroupExpanded glyphicon glyphicon-minus ag-icon Font Icon used as icon for the group row when is expanded.
String iconSortAscending Font Icon used when a column is sorted ascending.
String iconSortDescending Font Icon used when a column is sorted descending.
String iconSortUnSort Font Icon used when a column is not sorted.
String iconRefreshData glyphicon glyphicon-refresh Font Icon for the refresh data action.
JSFoundset myFoundset The form's foundset The foundset where data are fetched from.
Number responsiveHeight 300 Table's height to be set in a responsive form. When responsiveHeight is set to 0, the table will use 100% height of the parent container.
Number rowHeight 25 The height in pixels of the table's rows.
DataProvider rowStyleClassDataprovider Use dataSource calculation as rowStyleClassDataprovider to set styleClass conditionally to rows. The calculation should return the class name (or names) to be applied to the row.
String styleClass Table style Classes.
String tooltipTextRefreshData Refresh for latest data ! Tooltip text shown when hovering the refresh button.
Boolean visible true If the table is visible or not.
Boolean enableColumnMove true If moving of columns is enabled.
Boolean showColumnsMenuTab false If the column selection panel should be shown in the column menu.
ToolPanelConfig toolPanelConfig Tool panel configuration options.
IconConfig iconConfig Icons configuration options.
Map gridOptions Map where additional grid properties of ag-grid can be set (see https://www.ag-grid.com/javascript-grid-properties/ ).
Map localeText Map where locales of ag-grid can be set (see https://www.ag-grid.com/javascript-grid-internationalisation/). As values, beside simple texts, you can also use i18n values defined in Servoy, like i18n:myi18nkey.
MainMenuItemsConfig mainMenuItemsConfig Main menu items configuration options.
String arrowsUpDownMoveWhenEditing NONE Defines action on TEXTFIELD editor for up/down arrow keys. Can be one of the followings: NONE - editor's caret moves to start/end, NEXTCELL - starts editing the cell from the previos/next row, same column, if editable, else it just selects the row, NEXTEDITABLECELL - starts editing the cell from the first editable previous/next row, same column.
Boolean showGroupCount false When true the number of rows for groups is shown, beside the name.
Boolean showLoadingIndicator true When true a data loading indicator is shown. The text that is shown can be customized by setting 'loadingOoo' in the localeText.
Boolean editNextCellOnEnter false If start editing next cell on ENTER (when in TEXTFIELD editor).
String onDragOverFunc Callback when dragging over a row - returns one of the strings: 'copy', 'move', 'none' depending on the allowed drag operation. Ex. (function (src, dest, e) { return dest.id == 'myId' ? 'copy' : 'none';})
String onDragGetImageFunc Called when row(s) drag-n-drop is started, to get the drag image as an html code. Ex. (function (src, e) { return '<div>Dragging ' + src.length + ' records</div>';})
String checkboxEditorValueServerToClientFunc Callback to convert checkbox editor server data to client boolean value. Ex. (function (colid, value) { return colid == 'mycolumn' && value == 'yes';})
String checkboxEditorValueClientToServerFunc Callback to convert checkbox editor client boolean value to server data.. Ex. (function (colid, value) { return colid == 'mycolumn' && value ? 1 : 0;})

Grouping Table Events

Event Params Return Description
onCellClick foundsetIndex:Number, columnIndex:Number, record:Object, event:JSEvent Event executed when the user clicks on a table cell. The foundsetIndex is always equal to -1 when the table is grouping columns.
onCelldoubleClick foundsetIndex:Number, columnIndex:Number, record:Object, event:JSEvent Event executed when the user double clicks on a table cell. The foundsetIndex is always equal to -1 when the table is grouping columns.
onCellRightClick foundsetIndex:Number, columnIndex:Number, record:Object, event:JSEvent Event executed when the user right clicks on a table cell. The foundsetIndex is always equal to -1 when the table is grouping columns.
onColumnStateChanged columnState:String Event executed when the state of columns is changed, like position, width, visibility.
onColumnDataChange foundsetIndex:Number, columnIndex:Number, oldValue:Object, newValue:Object, event:JSEvent, record:Object Boolean Event executed when the value of a cell is changed by editing. Return false to keep the cell in edit mode.
onReady Event executed when the table is ready to be shown.
onColumnFormEditStarted foundsetIndex:Number, columnIndex:Number, value:Object Event executed when the column's form editor is started.
onSort columnIndexes:Number[], sorts:String[] Event executed when sort has changed.
onRowGroupOpened groupColumnIndexes:Number[], groupKeys:String[], isOpened:Boolean Event executed when group is opened/closed
onSelectedRowsChanged isgroupselection:Boolean, groupcolumnid:String, groupkey:Object, groupselection:Boolean Event executed when the row selection is changed.
onDrop sourceRecords:Object[], targetRecord:Object, event:JSEvent Called when a row is dropped as a result of a drag-n-drop.

Grouping Table API

Method Params Return Description
notifyDataChange Notify the component about a data change. Makes the component aware of a data change. Call this method when you are aware of a relevant data change in the foundset which may affect data grouping (e.g. group node created or removed). Highlight the refresh action button to indicate to the user new data is available.
refreshData Force a full refresh of the data. WARNING! be aware that calling this API results in bad user experience since all group nodes will be collapsed instantaneously.
getColumnState String Returns a json object as string with the current state of the columns.
restoreColumnState columnState:String, onError:Function, columns:Boolean, filter:Boolean, sort:Boolean Restore columns state to a previously save one, using getColumnState. If no argument is used, it restores the columns to designe time state. If the columns from columnState does not match with the columns of the component, no restore will be done. The optional boolean arguments: columns, filter, sort can be used to specify what to restore, the columns size/position/visibility (default true), the filter state (default false), the sort state (default false).
getColumnsCount Number Returns the number of columns.
newColumn dataprovider:String, index:Number Column Creates a new column.
removeColumn index:Number Boolean Removes column at specified index. Returns whatever the remove was successfully.
removeAllColumns Boolean Removes all columns. Returns whatever the remove was successfully.
moveColumn id:String, index:Number Moves column with id to the 0-based index.
getGroupedSelection Record[] Returns the selected records in grouping mode.
setGroupedSelection selectedRecords:Record[] Set the selection in grouping mode. The table must be already in grouping mode, and the record already loaded (the group of the record expanded - see: setExpandedGroups).
getCheckboxGroupSelection Object[] Returns the selected rows when in grouping mode.
setCheckboxGroupSelection selectedGroups:Object[] Set the selected headers/groups when using headerCheckbox/groupCheckbox property.
editCellAt foundsetindex:Number, columnindex:Number Start cell editing (only works when the table is not in grouping mode). 'foundsetindex' is the foundset row index of the editing cell (1-based), 'columnindex' is the column index in the model of the editing cell (0-based).
stopCellEditing cancel:Boolean If a cell is editing, it stops the editing; use cancel 'true' to cancel the editing (ie don't accept changes).
scrollToSelection Scroll to selected row.
setReadOnly readonly:Boolean, columnids:String[] Set the table read-only state. If no columnids is used, all columns read-only state is set, otherwise only for the columns specified.
setFormEditorValue value:Object Set the currently opened form editor value.
getColumnIndex colId:String Number Return the column index for the given column id. Can be used in combination with getColumnState to retrieve the column index for the column state with colId in the columnState object.
getExpandedGroups groups:Object Returns currently expanded groups as an object like {expandedGroupName1:{}, expandedGroupName2:{expandedSubGroupName2_1:{}, expandedSubGroupName2_2:{}}}
setExpandedGroups groups:Object Sets expanded groups
setFilterModel filterModel:Object Set the filter model. This api maps to ag-grid's setFilterModel; for more details on the model's structure check this page: https://www.ag-grid.com/angular-data-grid/filter-api/ NOTE: The name of the columns from the model are the id properties of the column; to clear the filter, use an empty object ({}) as filterModel.