Table
This widget shows a tabular view of data.
Note: Features marked with (*) are not supported yet.
Table Data
Refer to the generic widget page for a description of the general principles governing the treatment of data retrieved from a dataSource
Data from Table Holder / KPI Table
The widget fetches the table data from the system and does auto discovering of the header columns. This property is an objspec.
{
"dataSource": {
"type": "read",
"path": "/System/Core/Examples/WebStudio/Tables/SalesOrders"
}
}
Options
{
"options": {
"allowSorting": false,
"alternateColumnColoring": true,
"alternateRowColoring": true,
"editable": false,
"multi": true,
"multiMax": 3,
"multiMin": 1,
"pageSize": 20,
"pagination": true,
"showHoverHighLight": true,
"showRefreshButton": true,
"showSelectedRow": false,
"showToolbar": true,
"showRowNumbers": true,
"style": {
"backgroundColor": "grey",
"color": "blue",
"fontFamily": "\"Courier New\", Courier, sans-serif",
"fontWeight": "bold",
"fontSize": "24px",
"textAlign": "left",
"whiteSpace": "pre-line"
},
"refreshInterval": 30
}
}
name | description |
---|---|
|
When editable is set to true the cell values can be modified. Note that this only affects the original dataset if the table is saved and the user has the permissions to overwrite data. |
|
Can disable sorting icons and sorting functionality. |
|
Apply alternating light and dark column backgrounds. |
|
Apply alternating light and dark row backgrounds. Can be used together with |
|
Allow selection of multiple rows. When |
|
Minimal needed selected rows before the table onSubmit action can be triggered. |
|
Maximum allowed selected rows. |
|
When set to |
|
With |
|
Array of conditional formatting rules. See below |
|
Enable/disable hover effect on the table rows. |
|
Background color will change when a table row is clicked. Defaults to true when |
|
Set this to |
|
When set to |
|
Use to hide the complete toolbar. |
|
Property used to define static style settings for the table. The style settings are applied irrespective of the theme. |
|
Property used to define static style settings for the table based on the active theme. The styles are applied in the For example:
|
|
Refresh with an interval in seconds. |
Conditional Styling
Styling, which needs to be applied conditionally to all cells in a row can be defined within rules
of the model options
property. Cell / column specific styling is applied within the schema
elements.
A row based rule needs to contain a name
field to point to the right data field in the row. The range
element can be used to define a numeric or date range by using the fields from
and to
. The value defined in the to
field is excluded from the range. It is also possible to define only the from
value to match all values greater than or equal to the value defined in the from
field. To match all values less than a certain value, only the to
field can be
defined.
The styles of all matching rules will be applied to all cells in the row.
As is the case for the options.style
property, styleByTheme
can also be used in rule
config.
{
"options": {
"rules": [
{
"name": "temperature",
"value": 20,
"style": {
"backgroundColor": "green",
"fontSize": "15px",
"fontWeight": "normal"
}
},
{
"name": "temperature",
"range": {
"from": 22,
"to": 26
},
"style": {
"fontWeight": "bold"
}
}
]
}
}
Schema
A schema in the model will overrule any returned schema from the data source.
A schema consist of:
name | description |
---|---|
|
Column title. |
|
Key name of the row data. The name is also used by default to uniquely identify columns in the table. If the
same named data field needs to appear in the table multiple times an |
|
When column names are repeated in the schema section, WebStudio will automatically generated a unique |
|
Type of filter: |
|
Cell values can be displayed as different types. The format how the date and number type are displayed depend
on the user’s locale settings. Accepted types: |
|
When type is |
|
When type is |
|
Cell value can be selected from a dropdown list containing predefined values. |
|
Instead of making every cell editable with setting |
|
Width can be defined for the columns manually by providing pixel values as string e.g. "300px". |
|
Styling (optional) |
|
Property controlling column visibility (optional) |
|
Property to define default sorting on the column. Accepted values: |
|
Define a default cell value to display when none is present in the data. |
|
This option can be used for hierarchical data structures, it enables collapsing
and expanding table rows. Set |
|
Tooltip text to display when the mouse hovers over the table column header. If the tooltip is not explicitly set, the column title will be shown instead, or the name if that too is missing. This is useful when explicitly assigning the column width, typically to a number large enough to show the field values, but too narrow to accommodate the title, which might be longer than is needed for the values. |
{
"schema": [
{
"name": "id",
"hidden": true
},
{
"title": "Population",
"name": "population",
"filter": "select",
"type": "number",
"editable": true
},
{
"title": "Value",
"name": "value",
"filter": "slider",
"type": "number",
"numberOfDecimals": 2,
"sort": "desc"
},
{
"title": "Fixed column",
"value": "Click here",
"actions": {
"onClick": {
"type": "notify",
"text": "Fixed column cell clicked!"
}
}
}
]
}
Multiple schema items with the same name
To illustrate the use of repeated names in the schema, consider an example where the data rows include a "timestamp" field expressed as an epoch integer and we want to show the raw number as well as a formatted version.
The data could be something like:
{
"data": [
{
"event": "machine start",
"timestamp": 1635408094000
},
{
"event": "machine stop",
"timestamp": 1635416051000
}
]
}
In the schema the timestamp appears twice. First formatted as a number and then as a date:
{
"schema": [
{
"name": "event",
"title": "Event Description"
},
{
"name": "timestamp",
"type": "number",
"title": "raw timestamp"
},
{
"name": "timestamp",
"type": "date",
"title": "Date-Time",
"format": "YYYY-MM-DD HH:mm:ss"
}
]
}
Note: Looking at the work-model for this table, we see that an
id
= "timestamp_2" was automatically generated in the schema for the second occurrence of the column. It can also be explicitly added to the initial model, in which case we are free to choose theid
value:
{
"schema": [
{ "name": "event", /* etc ... */ },
{ "name": "timestamp", /* etc ... */ },
{
"name": "timestamp",
"id" : "formatted_timestamp",
"type": "date",
"title": "Date-Time",
"format": "YYYY-MM-DD HH:mm:ss"
}
]
}
Grouped columns
{
"schema": [
{
"title": "Employee",
"columns": [
{
"title": "Name",
"name": "firstName"
},
{
"title": "Last Name",
"name": "lastName"
},
{
"title": "Age",
"name": "age",
"filter": "slider"
}
]
},
{
"title": "Address",
"columns": [
{
"title": "Street",
"name": "street",
"filter": "text"
},
{
"title": "City",
"name": "city"
},
{
"title": "Country",
"name": "country",
"filter": "select"
}
]
}
]
}
Dropdown selection
Select a predefined input value from a dropdown. Inputs need to be defined in the items
array. This can be an array of strings or objects containing a label
and value
. The latter can be used when the text to show should be different from the value
.
Example items
as string array:
{
"schema": [
{
"name": "day",
"title": "Day of week",
"items": [
"Monday",
"Tuesday",
"Wednesday",
"Thursday",
"Saturday",
"Sunday"
]
}
]
}
Example items
by defining labels and values:
{
"schema": [
{
"name": "day",
"title": "Day of week",
"items": [
{
"label": "MON",
"value": "Monday"
},
{
"label": "TUE",
"value": "Tuesday"
}
]
}
]
}
Formatting
{
"schema": [
{
"name": "temperature",
"title": "Temperature",
"type": "number",
"numberOfDecimals": 2,
"engUnit": "°C"
},
{
"name": "timestamp",
"title": "Timestamp",
"type": "date",
"format": "YYYY-MM-DD HH:mm:ss.SSS"
},
{
"name": "status",
"title": "Status",
"enumMode": "valueToName", // valueToName (default), nameToValue
"enum": {
"Dry": 1,
"Wet": 2
}
}
]
}
Enum formatting can do valueToName
(default) or nameToValue
.
-
valueToName
: Table cell value will be matched with a value of an enum and the name will be shown in the table cell. -
nameToValue
: Table cell value will be matched with a name of an enum and the value will be shown in the table cell.
Style
Cell or column based styling can be defined in the style
within a schema
element.
{
"schema": [
{
"name": "value",
"title": "Value",
"style": {
"backgroundColor": "#00c302",
"fontSize": "15px",
"fontWeight": "bold",
"whiteSpace": "pre-line"
}
}
]
}
Conditional styling on schema level applies for to cell. The name
field is optional and can be defined in case the
value match needs to be done with another data field. The styles of all matching rules will be applied to the cell.
Cell based rules:
{
"schema": [
{
"name": "value",
"title": "Value",
"style": {
"backgroundColor": "#00c302",
"fontSize": "15px",
"fontWeight": "bold",
"whiteSpace": "pre-line"
},
"rules": [
{
"value": 1,
"style": {
"backgroundColor": "green",
"fontSize": "15px",
"fontWeight": "normal"
}
},
{
"value": 2,
"style": {
"color": "yellow"
}
},
{
"range": {
"from": 5,
"to": 10
},
"style": {
"color": "yellow"
}
}
]
}
]
}
Hierarchical Data
Data field has a key children
, which is used in schema with isExpander
to create hierarchical table layout.
"data": [
{
"Item": "Pencil",
"Total": 189.05,
"Unit Cost": 1.99,
"children": [
{
"Item": "Pencil",
"Total": 59.7,
"Unit Cost": 1.99,
"OrderDate": "2019-06-08"
},
{
"Item": "Pencil",
"Total": 59.7,
"Unit Cost": 1.99,
"OrderDate": "2019-06-10"
}
]
}
]
"schema": [
{
"name": "children",
"collapsedIcon": "▷",
"expandedIcon": "▽",
"isExpander": true
},
{
"name": "Item",
"title": "Item"
},
{
"name": "Total",
"title": "Total"
},
{
"name": "Unit Cost",
"title": "Unit Cost"
},
{
"name": "OrderDate",
"title": "Order date",
"type": "date",
"format": "YYYY-MM-DD"
}
],
Toolbars
Define custom tools to be added to the toolbar and their actions.
{
"toolbars": {
"top": {
"tools": {
"addRow" : {
"type" : "button",
"title": "",
"icon": {},
"style": {},
"styleByTheme": {},
"actions": {
"onClick": {}
}
}
},
"toolsOrder": {
"leftOrTop": ["addRow"]
}
}
},
}
Field | Description | |||
---|---|---|---|---|
|
Currently toolbars can only be located at the top of the widget. Other options may be added later. |
|||
|
Define the order in which the tools are drawn. For now, they are always arranged from left to right. Additional options, to have center or right aligned tools, may be added later. |
|||
|
List of tool-names indicating the order they are drawn from left to right. The property is called |
|||
|
Contains the "named" tools to be added to the toolbar. In the example above, a single addRow button is defined. The name is used to set the display order in the |
|||
|
Define the appearance and actions for a tool. The name should be chosen to reflect its purpose. |
|||
|
The only tool type supported at the moment is button. While it is the only option, the property can be omitted. |
|||
|
Optional tool text. Can be omitted if only an Icon should be displayed. |
|||
|
Tool icon. Can be omitted if only the title is needed. |
|||
|
Optional styling to be applied. |
|||
|
Optional theme specific styling |
|||
|
Define tool actions to respond to. Currently the only action trigger available is
|
State
The table widget maintains some dynamic state information in the state
property to record the currently selected
row(s) as well as the active search and filter options.
{
"state": {
"selectedRowIndex": [],
"filters": [
{
"name": "Count",
"value": [
2,
5
]
}
],
"search": {
"value": ""
}
}
}
Field | Description | |
---|---|---|
|
list of 0 based row indices of selected rows |
|
|
List of filter objects |
|
|
Name of the column the filter is applied to |
|
|
Filter value. The content of this field depends on the type of the filter. |
|
|
Search text |
These may be set in the initial model, but it is more common to access and manipulate the values at run-time.
Note: The state properties can be modified using action pipelines to explicitly set the filters, selected rows or search values. When applying such changes the current state fields need to be overwritten in their entirety. Changing fields inside the root level properties is not supported.
To put this into perspective, consider the following example: Suppose we want to change the "range" filter on the "Count" field so it ends at 10 rather than 5, as in the example above.
We might be tempted to do something like this:
{
"type": "modify",
"id": "table",
"set": [
{ // This is not supported !
"name": "model.table.state.filters.0.value.1",
"value": 10
}
]
}
What we need to do instead, is to provide the complete filter array.
{
"type": "modify",
"id": "table",
"set": [
{
// The model field being modified is the "filter" array
"name": "model.table.state.filters",
// The value assigned to it must includes all filter settings to be applied.
"value": [
{
"value": [
3,
10
],
"name": "Count"
}
]
}
]
}
In this case only one field is involved in the filter, but if there were more, they would all need to be included in the
filters
array even if only one of them changes.
Actions
-
onClick
: Cell is clicked. Can be defined via the Schema. -
onSelect
: Single row is selected. -
onSelectionChanged
: Perform an action each time the selection is changed. -
onSubmit
: Submit button is clicked and selected rows are in the message payload.
onClick
Cell click can be defined to a whole table column. This by setting the onClick
action in a schema
item.
{
"schema": [
{
"name": "value",
"title": "Value",
"actions": {
"onClick": [] // Can be a single action or action pipeline.
}
}
]
}
The input message payload
will contain the complete row data and the selected cell info. Example:
{
"row": {
"_idx": 1,
"name": "Temperature",
"value": 26
},
"cell": {
"_idx": 2,
"name": "value",
"value": 26
}
}
onSelect
Gets invoked when a row is selected. The input message payload
contains the selected row data.
{
"actions": {
"onSelect": [
{
"type": "function",
"lib": "library-name",
"func": "function-name",
"farg": {} // This will be set automatically.
}
]
}
}
Transforming the selected row data and invoke a function:
{
"actions": {
"onSelect": [
{
"type": "transform",
"aggregateOne": [] // This will return one object instead of an array.
},
{
"type": "function",
"lib": "library-name",
"func": "function-name",
"farg": {} // This will be set automatically.
}
]
}
}
Send a message to another widget with selected row data
{
"actions": {
"onSelect": [
{
"type": "send",
"to": "widget01"
}
]
}
}
onSelectionChanged
Gets invoked when a row is (de)selected. The input message payload
contains all the selected rows (array).
{
"actions": {
"onSelectionChanged": [] // Can be a single action or action pipeline.
}
}
onSubmit
The selected rows (array) are set on the input message payload
. Whether rows can be selected with respect to the
minimum and maximum number of selected rows, can be set with multi
, multiMin
and multiMax
in the
Options.
{
"actions": {
"onSubmit": []
}
}
Receive messages (Send Topics)
This widget receives messages from others. Besides the generic, this widget also support topics:
-
selectRows
: Can be used to select one or more rows in the table. The messagepayload
should contain arowIndex
array, which contains the index(es) of the rows which need to be selected.
Here’s an example to send a message to a table widget with an array of the selected rows
{
"type": "send",
"to": "table",
"message": {
"topic": "selectRows",
"payload": {
"rowIndex": [
5,
6
]
}
}
}
Collect
Collect without a topic
defined will result in the data rows.
This widget supports the following topics to collect data:
-
No topic defined: collects all the data rows.
-
selectedRows
: collects the selected rows data.
Here’s an example of getting the selected rows data from a table widget by using an onClick action of a text Widget:
{
"type": "text",
"text": "Click here",
"actions": {
"onClick": [
{
"type": "collect",
"from": "table",
"message": {
"topic": "selectedRows"
}
},
{
"type": "consoleLog",
"tag": "Selected Row Data"
}
]
}
}