Grid Widget
Easy to use, fully featured grid widget with state formatting to view information at a glance, based on the Tabulator library.
Usage
The IQNOX Grid Widget is a widget built from the ground up with performance and customization in mind. With features like: cell state formatting, in-cell editing, in-cell mashups, custom columns and more.
The key features that make the IQNOX Grid Widget great:
- An easy UI to configure columns and a purposely built configurator for styling the look and feel of the widget
- Full customization per column. Each column can look totally different from another
- State formatting on entire rows with a fully built in query builder
- State formatting on cells. Cells can have a custom label template which be customized based on value with state formatting
- Support for remote data. No need to output all the data from your server anymore. Using pagination, the service can be built to only get data for the current page
- Freeze columns at the beginning or end of the grid
- Enable different type of filters per columns
- Different selection modes, single, multiple by clicking the row or by enabling selection from checkbox at the beginning of the row
- Enable sorting on desired columns
- Add custom columns that are not present in the
DataShape
- Support for in cell mashups. Each cell can display a mashup that inherits the
Data
from the widget - Custom column renderer. The ability to render anything in a grid cell
Properties
Properties | Type | Binding | Default | Description |
---|---|---|---|---|
CustomClass | STRING | Enables you to define an html class to the top div of the widget. Multiple classes can be entered, separated by space. | ||
Data | INFOTABLE | < | Infotable with data to be displayed in the grid | |
AllowColumnReorder | BOOLEAN | FALSE | Allow the user to reorder the columns in the grid at runtime | |
AllowSelectWithCheckbox | BOOLEAN | FALSE | Allow the user to select rows at runtime using checkboxes | |
PersistenceId | STRING | IQNOX grid can store a variety of table setup options so that each time a user comes back to the page, the table is laid out just as they left it. Allows to enable/disable persistance on grid. If an id is set, persistance will be enabled. The id must be unique so the grid can be identified at runtime when there are multiple of them. | ||
PersistenceSettings | JSON | Grid persistence settings. | ||
DataId | STRING | The infotable field which represents the data id used by the grid | ||
EditedData | INFOTABLE | > | Outputs the edited data in the grid. | |
MultiColumnSortOrder | STRING | < | Set the default multi-column sorting using the column field names: name:asc,value:desc . The priority between them is the order you define them in. | |
AllowEdit | BOOLEAN | < | Enable/Disable grid edit options from column configurator. | |
MinimumItemsSelected | NUMBER | 0 | Minimum items of selected items | |
MaximumItemsSelected | NUMBER | 0 | Maximum items of selected items | |
Layout | STRING | fitDataFill | Change how columns will fit inside your grid container. | |
ExportFileName | STRING | Data | ExportFileName: Filename for all the grid exports. Developers should avoid using unsupported files name characters based on the target OS. | |
ShowExportToCSV | BOOLEAN | TRUE | Shows export option into the grid settings menu at runtime | |
ShowExportToJSON | BOOLEAN | TRUE | Shows export option into the grid settings menu at runtime | |
ShowExportToPDF | BOOLEAN | FALSE | Shows export option into the grid settings menu at runtime | |
ShowExportToXLSX | BOOLEAN | FALSE | Shows export option into the grid settings menu at runtime | |
DefaultSelectedRow | STRING | < | Specifies the row number to be selected on grid load. Specific rows can be selected separated by a comma: 2, 5, 7. Or numeric ranges: 1-6. | |
MovableRows | BOOLEAN | FALSE | Allow the user to move the rows in the grid at runtime | |
HasSelection | BOOLEAN | > | FALSE | Allows the user to take some actions if grid has a selection active or not. |
AutoScroll | BOOLEAN | < | TRUE | Enable/Disable auto scroll. Scrolls to the selected row when selected row changes or window is resized. |
IsEditing | BOOLEAN | > | FALSE | Outputs whether the grid widget is in editing mode |
IsLoading | BOOLEAN | > | Allow the user to know when the service that is populating the grid is running. | |
NumberOfSelectedRows | NUMBER | > | Outputs the number of selected rows | |
HasRows | BOOLEAN | > | Outputs if grid have bound rows | |
NumberOfRows | NUMBER | > | Outputs the total number of rows | |
ColumnsRuleSet | JSON | < | The rule set for columns state formatter. This is not expected to be changed manually, column configurator should be used instead. | |
GridConfiguration | JSON | < | Saved configuration used for columns. This is not expected to be changed manually, column configurator should be used instead. | |
GridIsRendering | BOOLEAN | > | Allow the user to know when the grid is rendering due to the service being triggered by MashupLoaded . | |
AutomaticRemoteData | BOOLEAN | TRUE | Chose if bindings need to be created to load the remote data, or if the bound service is automatically called. See docs for limitations. | |
FilterAndSortMode | STRING | Local | How the filtering and sorting should be done, locally, or on the server. | |
PaginationMode | STRING | Disabled | How paginated data should be loaded(disabled , localPagination , remotePagination , remoteProgressiveLoad ). | |
SelectedRows | INFOTABLE | > | Currently selected rows in the table. Useful when remote pagination is enabled | |
Query | QUERY | <> | When FilterAndSortMode , is set to remote , contains the query the user has built by sorting and filtering the table | |
PageRowOffset | NUMBER | > | When pagination is enabled, the offset of the first row shown. | |
ProgressiveLoadScrollMargin | NUMBER | When pagination is set to progressiveLoad , when to trigger a new page. | ||
PageRowSize | NUMBER | > | When pagination is enabled, the number of rows shown on the page. | |
PageTotalRowCount | NUMBER | < | When PaginationMode is set to remote , the total number of rows be known. | |
UserPreferences | JSON | <> | Settings the user has done to the grid to be saved. | |
InitialMessage | STRING | Start a new search | Message displayed before the first data loading attempt. | |
LoadingMessage | STRING | Data is now loading... | Message displayed while data is loading. | |
NoDataMessage | STRING | No new data found | Message displayed when the data service provides no rows. | |
ErrorMessage | STRING | There was an error | Message displayed when the data service throws an error. |
Services
Property | Type | Binding | Description |
---|---|---|---|
SelectAll | SERVICE | < | Select all rows in the grid. |
DeselectAll | SERVICE | < | Deselect all rows in the grid. |
DownloadAsCsv | SERVICE | < | Download grid data as CSV. |
DownloadAsJson | SERVICE | < | Download grid data as JSON. |
DownloadAsXlsx | SERVICE | < | Download grid data as XLSX. |
EditModeStart | SERVICE | < | Start edit mode on the grid. |
EditModeFinish | SERVICE | < | Finish edit mode on the grid. |
ResetGrid | SERVICE | < | Resets the grid filters, sorters and pagination. |
Events
Property | Type | Binding | Description |
---|---|---|---|
RowClicked | EVENT | > | Triggers when row is clicked |
SelectedRowsChanged | EVENT | > | Triggers when table row selection is changed. |
EditFinished | EVENT | > | Triggers when table cell edit is finished. |
QueryChanged | EVENT | > | When FilterAndSortMode , is set to remote , fires when the user changes the filters and sorters on the data. New data must be bound into the Data infotable. |
PageRequested | EVENT | > | When PaginationMode is set to remote , fires when a new page is requested to be loaded in the gridchanged. |
UserPreferencesChanged | EVENT | > | Triggers when the user makes a change to the grid settings. |
Grid Column Configurator
Default Configuration
When data is bound to the widget, a default configuration is created based on the bound data. The grid widget can be used and its fully functional without changing anything from the default state.
Every change to the used DataShape
will be reflected into the grid column configuration.
Grid configuration will be fully reset to default every time the binding is changed
Custom Configuration
Grid is using our new column configurator for customization like enabling sorters, header filters reordering column, show/hide columns.
-
Columns: Columns name and baseType
-
Include: If true, column is included in the runtime column visibility menu(Right click on grid columns in header)
-
Show: If true, column will be visible at runtime
By selecting a column from the left, you have access to configure column settings for the selected column.
Columns defied in the DataShape
can be restored to default values by clicking the reset button from the top right corner of the column configurator tab.
Add custom columns
Column configurator can be used to add custom columns to display mashups or custom renderers. These columns are not bound to any specific field, but they do have access to the entire Data
.
Column settings
-
General:
- DataShape field: Field name from the
DataShape
used for gridData
INFOTABLE. - Identifier: Column unique identifier(only for custom columns)
- DataShape field: Field name from the
-
Format:
- Title: Title of the column, shown in the headers and visibility menu.
- Width: Sets the width of this column, this can be set in pixels or as a percentage of total table width (if not set the system will determine the best).
- Auto width: Automatically assign a width to the column that makes the entire contents fit.
- Minimum/Maximum width: Minimum/maximum width of the column, this should be set in pixels.
- Header alignment: Sets the horizontal alignment of the header text.
- Cell alignment: Sets the horizontal alignment of the cell text.
- Enable sorting: Sets if the user can sort this column by clicking on the header. This will also show/hide the sort icon.
- Enable header filter: Sets if the user can filter the column by using a header filter.
- Header filter: Header filter type
- Filter placeholder: Placeholder
- Freeze column: Sets if the column is frozen, so during horizontal scrolling, the column will always be visible.
-
Renderer:
- Cell renderer: Setting describing how each column should be rendered
- Template: Template selector for renderers that supports this option.
- Example: String will render an IQNOX Label widget, which can use any of the Templates for that widget
- Format: Will use Format Complex
- Mashup: Mashup selector for renderers that support this option
- Max width: Max width for renderers that support this option
- Max height: Max height for renderers that support this option
-
Editor:
- Editor type: Setting describing how each column should be edited
- Template: Template selector
- Dropdown JSON values: values displayed in dropdown formatted as a json
- Example:
- Input type: Input type(text only)
When String
renderer is selected and column baseType is boolean, some extra options are available in Format
section:
Value when true
: Applies for a column with thebaseType
set to BOOLEAN. Represents the value to be shown when the boolean istrue
.`Icon when true
: Applies for a column with thebaseType
set to BOOLEAN. Represents the icon to be shown when the boolean istrue
Value when false
: Applies for a column with thebaseType
set to BOOLEAN. Represents the value to be shown when the boolean isfalse
Icon when false
: Applies for a column with thebaseType
set to BOOLEAN. Represents the icon to be shown when the boolean isfalse
Show only icon
: Applies for a column with thebaseType
set to BOOLEAN. If only the icon should be shown
User preferences
User preferences can be used to save different configurations used with the grid widget such as column visibility and position, sorting, page number and filters.
For this, a new property called userPreferences
was added in PersistenceSettings
which can be set as local
, where the configuration is saved in the browser and can only be used locally, or as external
. If userPreferences
is set to external
, a new property called UserPreferences
becomes available, which can be bound to the grid to load saved configuration or saved externally, also an event called UserPreferencesChanged
will be available which is triggered when the UserPreferences
changes
PersistenceSettings property
Renderer types
The grid data can be displayed in various forms that can be chosen from column configurator in the renderer section
String renderer
String renderer object structure
StringCellRenderer {
cellRenderer: 'string';
/**
* Allows the user to specify a formatting string to use to render the value
*/
format?: string;
/**
* Applies for a column with the `baseType` set to BOOLEAN. Represents the value to be shown when the boolean is `true`
*/
valueWhenTrue?: string;
/**
* Applies for a column with the `baseType` set to BOOLEAN. Represents the icon to be shown when the boolean is `true`
*/
iconWhenTrue?: string;
/**
* Applies for a column with the `baseType` set to BOOLEAN. Represents the value to be shown when the boolean is `false`
*/
valueWhenFalse?: string;
/**
* Applies for a column with the `baseType` set to BOOLEAN. Represents the icon to be shown when the boolean is `false`
*/
iconWhenFalse?: string;
/**
* Applies for a column with the `baseType` set to BOOLEAN. If only the icon should be shown
*/
showOnlyIcon?: boolean;
/**
* Represents the name of IQNOX Template to be used to render the value
*/
template?: string;
}
Markdown renderer
Markdown renderer object structure
MarkdownCellRenderer {
/**
* Renders the value as markdown text, that is rendered inside the cell. The generated HTML is sanitized
*/
cellRenderer: 'markdown';
}
Html renderer
Html renderer object structure
HtmlCellRenderer {
/**
* Renders the value as a HTML string. This value is sanitized prior to being rendered.
*/
cellRenderer: 'html';
}
Hyperlink renderer
Hyperlink renderer object structure
HyperlinkCellRenderer {
/**
* Renders the value as a hyperlink, allowing the user to click on the value to open a new tab
*/
cellRenderer: 'hyperlink';
}
Mashup renderer
INFOTABLE
parameter on the mashup called Data
that can be used and bound inside the used mashup. Using this type of renderer requires cell width and height to be set to fit the mashupMashup renderer object structure
MashupCellRenderer {
/**
* Renders the value in a ThingWorx mashup, that takes an input parameter the entire infotable row
*/
cellRenderer: 'mashup';
/**
* Represents the ThingWorx mashup name to use.
* The mashup should have a parameter of type INFOTABLE named Data that will contain the full row values.
*/
mashup?: string;
}
Image renderer
This renderer can be used to render an image inside the grid cell. Max width and height must be specified.
Image renderer object structure
ImageCellRenderer {
/**
* Renders that the value as an hyperlink to an image that is then rendered inside the cell
*/
cellRenderer: 'image';
/**
* Applies for the `image` `cellRenderer`, describes the dimensions of the rendered image
*/
maxWidth: {
value: string | number;
unit?: string;
};
/**
* Applies for the `image` `cellRenderer`, describes the dimensions of the rendered image
*/
maxHeight: {
value: string | number;
unit?: string;
};
}
Custom renderer
This renderer allows you to write a custom javascript function to render a column. Only the function body can be modified and must be returned a string
or HTMLElement
.
No validation or sanitization done on the input, but it'a available in the scope for use(docs).
See the following references for documentation and examples:
Custom renderer object structure
CustomCellRenderer {
/**
* Renders the value using an actual typescript function that the user can write in
*/
cellRenderer: 'custom';
/**
* Actual code that should be executed at runtime to render the column
*/
javascriptCode: string;
/**
* The code that the user has entered to render this column.
* This code gets transpiled into javascript and is stored on the {@link javascriptCode} property.
*/
typescriptCode?: string;
}
Editor types
The grid data can be edited in various forms that can be chosen from column configurator in the editor section.
Input editor
Input editor object structure
InputCellEditor {
/**
* Renders a cell editor using an text input
*/
editorType: 'text';
/**
* Represents the name of an IQNOX Template to use to render the value
*/
template?: string;
/**
* Applies for `text` editors. The type of input to use where the user should enter the value
*/
inputType?: 'text' | 'number' | 'datetime-local' | undefined;
}
Checkbox editor
boolean
valuesCheckbox editor object structure
CheckboxCellEditor {
/**
* Renders a cell editor using a checkbox input.
*/
editorType: 'checkbox';
/**
* Represents the name of an IQNOX Template to use to render the value
*/
template?: string;
}
Dropdown editor
Dropdown editor object structure
DropdownCellEditor {
/**
* Renders a cell editor using a dropdown.
*
* Values in the dropdown can either be static, or driven from the distinct values in the dataset
*/
editorType: 'dropdown';
/**
* Represents the name of an IQNOX Template to use to render the value
*/
template?: string;
/**
* Allows the specification a given list of values in a dropdown that the user can pick from.
* Stores a JSON representation of an array of objects with two keys: value(string), display(string).
* Follows this spec:
* ```ts
* { value: string; display: string }[]
* ```
*/
dropdownOptions?: string;
}
Column state formatting
Columns also supports State formatting(only for string renderer) individually, by selecting the State formatting
menu from the top.
Creating custom configuration object
Grid column configuration object can be manually created using the code editor embed into the property editing modal.
Configuration object structure
{
/**
* The schema of the configuration
*/
$schema: string;
/**
* Configuration of the columns.
* For each column, where the data comes from, and how it's rendered.
*/
columns: GridColumnConfiguration[];
}
Grid column configuration
A JSON schema is available after you import the widget into your ThingWorx environment, and include the path where developer can find it at.
If Monaco editor is setup, it will provide hints while editing the config.
Columns object structure
GridColumnConfiguration {
/**
* Name of the field, from the original DataShape that describes this grid column.
* This should be an unique identifier of the field.
*/
field: string;
/**
* Default visibility of the column.
*/
visible: boolean;
/**
* Set to `true` if the field should be included to be shown at runtime, or to `false` to completely exclude it
*/
include: boolean;
/**
* ThingWorx base type of the field this column represents.
*/
baseType: TWBaseType;
/**
* Can the cell be edited
*/
allowEdit: boolean;
/**
* Describes how the column should be formatted.
*/
format: {
/**
* Title of the column, shown in the headers and configuration menu.
*/
title: string;
/**
* Sets the width of this column, this can be set in pixels or as a percentage of total table width (if not set the system will determine the best).
*/
width: {
value: string;
unit?: string;
};
/**
* Automatically assign a width to the column that makes the entire contents fit.
*/
autoWidth: boolean;
/**
* Sets the minimum width of this column, this should be set in pixels.
*/
minimumWidth?: number;
/**
* Sets the maximum width of this column, this should be set in pixels.
*/
maximumWidth?: number;
/**
* Sets the horizontal alignment of the header text.
*/
headerAlignment: 'flex-start' | 'center' | 'flex-end';
/**
* Specifies how each cell in the column is aligned on the horizontal axis.
*/
cellAlignment: 'flex-start' | 'center' | 'flex-end';
/**
* Sets if the user can filter the column by using a header filter.
*/
allowHeaderFilter: boolean;
/**
* Type of header filter to be used.
* - `input`: Allow the user to type in text
* - `list`: Generates a list of selectable entities based on the data
* - `checkbox`: Helpful for boolean columns, filter rows based on true/false
* - `number`: For numeric columns, allows for filtering for based on comparison (see `headerFilterFunction`)
*/
headerFilter: 'input' | 'list' | 'tickCross' | 'number';
/**
* If you want to specify the type of filter used you can pass it to the headerFilterFunc option in the column definition object. This will take any of the standard filters outlined above or a custom function
*/
headerFilterFunction?: '>=' | '<=' | '=' | '>' | '<' | undefined;
/**
* Placeholder text for the header filter.
*/
filterPlaceholder?: string;
/**
* Sets if the user can sort this column by clicking on the header.
*/
allowHeaderSort: boolean;
/**
* Sets if the column is frozen, so during horizontal scrolling, the column will always be visible.
*/
frozenColumn: boolean;
};
/**
* Setting describing how each column should be rendered
*/
renderer:
| StringCellRenderer
| MashupCellRenderer
| MarkdownCellRenderer
| HtmlCellRenderer
| ImageCellRenderer
| HyperlinkCellRenderer
| CustomCellRenderer
/**
* Describes settings related to how the cell is being edited
*/
editor?: InputCellEditor | CheckboxCellEditor | DropdownCellEditor;
}
Each renderer has its own properties that can be specified
Each editor has its own properties that can be specified
Sorting
Sorting is enabled on all columns, this can be changed from grid column configurator for each column individually.
Default multi select order can be configured from widget properties (MultiColumnSortOrder
), See properties
Filtering
IQNOX Grid allows you to filter the table data by any field in the data set.
Available filters:
- Input - Text filtering
- Number - Numbers filtering
- List - Allow to select one or more field from the column to search for
- Checkbox - For
boolean
values
Server side data
The grid widget supports dynamically loading of data form the server using services. The following use-cases are supported:
- Remote pagination (the server paginates the data and just gives the frontend "slices"). UX-wise this can be presented as:
- infinite scrolling
- actual pagination where the users actually selects the page
- Remote filtering and sorting:
- The header filter and the sorting that the user does gets converted into a ThingWorx Query that the backend applies, and returns the matching data.
Note that these capabilities can be used at the same time.
The following properties are added and can be used:
FilterAndSortMode: 'local' | 'remote'
: Describes how filtering and sorting is done. Local means that it's done locally, using only the data present on the frontend. Remote means it's done on the server, and it's the service responsibility to filter and sort the data.PaginationMode: 'disabled' | 'localPagination' | 'remotePagination' | 'remoteProgressiveLoad'
.- If
PaginationMode == 'remoteProgressiveLoad'
:ProgressiveLoadScrollMargin
:SelectedRows: INFOTABLE
: The currently selected rows, especially important in a remote pagination.SelectedRowsChanged: Event
: Triggered when the user changes the selected rows.ResetGrid: Service
: Resets the grid filters, sorters and pagination.
There are two option in regard to how remote data can be configured.
Automatic remote data
With this option set to true, only one binding is needed, but the data service needs to follow some predefined formats. Essentially, it presents some opinionated defaults that the service implementer must follow. The advantage of using this approach is the simplicity of the mashup bindings.
The grid widget then will independently and automatically call the service with the correct parameters in order to retrieve data, without any extra bindings when the user interacts with the grid.
In order to configure remote data, the following must be done:
-
Create a service that returns data as an INFOTABLE with two columns, in the following format. Note that the actual property names can be updated below.
totalRowCount
: INTEGER: Total number of rows in this datasetdata
: INFOTABLE: Actual data
-
The service has the following input parameters (at a minimum). Not that the actual parameter names can be updated below.
query
: QUERY: A query built out of the grid sorters and filters, to get a specific view on the dataset.offset
: INTEGER: Offset of items to get. For pagination, this would becurrentPageNumber / pageSize
pageSize
: INTEGER: Number of rows to retrieve.
-
Bind the nested
data
in the service to the grid Data property, and configure its columns- Configure the
RemotePropertyDataMap
property. This allows remapping of the properties in the service output and input. By default this has value:
{
"totalRowCount": "totalRowCount",
"data": "data",
"query": "query",
"offset": "offset",
"pageSize": "pageSize"
} - Configure the
-
At runtime, the grid can figure out the "Data" binding, and automatically call the service when needed.
Manual bindings
There is no magic, the grid exposes properties and events that the developer has to bind to their services. More work is required, but enables using the grid in all scenarios.
Sorters and filters
To remote support sorters and filters the following properties and events are added:
Query: QUERY
,binding source
: A Thingworx QUERY object built out of thesorters
andfilters
from tabulator, in thedata-loading
event.QueryChanged: TWEvent
,binding source
: Event that fires when the sorters or filters have changed.
The developer would use these to bind to their data service and show updated data whenever necessary.
Pagination (or progressive loading)
The following properties and events are added:
PageRowOffset: INTEGER
,binding source
: the offset to show rows fromPageRowSize: INTEGER
,binding source
: Number of rows to be shown on a pagePageRequested: TWEvent
,binding source
: Event that fires when the user has requested a new page, (withPageSize
rows, offset atCurrentPage
)PageTotalRowCount
:binding target
: Total number of rows available
For pagination to work, TotalRowCount
must be bound, and updated whenever the number of rows shown changes (e.g. on filtering).
The developer would add the data service once, and will create bindings that it both initially, to load the grid data, but also for any grid generated events (QueryChanged
and PageRequested
).
Bindings example:
The following example showcases the bindings that must be done to configure remote pagination, sorters and filtering.
In this example, the data in the grid is completely reset when a Button
widget is clicked.
The data source for the grid is a service, Things.DataService
that returns an infotable with two fields: totalRows
and data
.
However, the same could be used using two separate services, one that returns the total number of rows, and other to return the data.
- Bind an event to the service that should invoke the service:
Button.Clicked
->Invoke Things.DataService
- Bind the data into the grid:
Things.DataService.result.data
->Grid.Data
- Bind the total number of rows into the grid:
Things.DataService.result.totalRows
->Grid.PageTotalRowCount
- Bind the query generated by the grid into the service:
Grid.Query
->Things.DataService.params.query
- Bind the event fired when the grid query changes to invoke the data service:
Grid.QueryChanged
->Invoke Things.DataService
- Bind the grid page row size config into the data service parameter:
Grid.PageRowSize
->Things.DataService.params.pageSize
- Bind the grid page row offset into the data service parameter:
Grid.PageRowOffset
->Things.DataService.params.offset
- Bind the grid event that's fired when a new page is requested to invoke the data service:
Grid.PageRequested
->Invoke Things.DataService
- To reset
Grid.Query
,Grid.PageRowSize
,Grid.PageRowOffset
(e.g., when the user wants to load a completely different dataset):Button.Clicked
->Invoke Grid.ResetGrid