Table

This widget shows a tabular view of data.

Model

{
    "type": "table",
    "options": {},
    "schema": {},
    "toolbars": {},
    "state":{}
}

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.

{
    "dataSource": {
        "type": "read",
        "path": "/System/Core/Examples/WebStudio/Tables/SalesOrders"
    }
}
The table widget can display data from any table property in the back-end, not just those in table-holders or KPI tables. This is achieved by including the table property name in the path.

By using a "read-write" action in the dataSource pipeline the data will be saved back to the source table when the user clicks the "Save" toolbar button, without the need to implement explicit "onSave" logic.

The path in this case must also contain the name of the object’s table property, which in the case of a table holder is called .TableData.

{
    "dataSource": {
        "type": "read-write",
        "path": "/System/Core/Examples/WebStudio/Tables/SalesOrders.TableData"
    },
}

Data from Advanced Endpoint

{
    "dataSource": {
        "type": "function",
        "lib": "library-name",
        "func": "function-name",
        "farg": {
            "equipment": "MyEquipment",
            "threshold": 120
        }
    }
}

Fixed Data

Fixed data set. Instead of the data coming from fetch, a fixed data set can be defined in the model.

{
    "data": [
        {
            "name": "Inside Temperature",
            "value": 26
        }
        {
            "name": "Outside Temperature",
            "value": 18
        }
    ]
}

Options

The options section is used to control various aspects of the appearance and behavior of the table.

{
    "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,
        "submitButton": {
            "label" : "CLICK ME"
        },
        "style": {
            "backgroundColor": "Gainsboro",
            "color": "blue",
            "fontFamily": "\"Courier New\", Courier, sans-serif",
            "fontWeight": "bold",
            "fontSize": "20px",
            "textAlign": "left",
            "whiteSpace": "pre-line"
        },
        "header": {
            "style": {
                "backgroundColor": "DimGrey",
                "color": "white",
                "fontWeight": "bold"
            }
        },
        "refreshInterval": 30
    }
}
name description

editable

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.

allowSorting

Can disable sorting icons and sorting functionality.

alternateColumnColoring

Apply alternating light and dark column backgrounds.

alternateRowColoring

Apply alternating light and dark row backgrounds. Can be used together with alternateColumnColoring

header

Used to define style and styleByTheme attributes for the header row. These settings override the options.style and options.styleByTheme parameters if defined.

multi

Allow selection of multiple rows. When multi is true, a column showing check-boxes, or radio buttons, is added to the left of the data columns with which rows can be interactively selected or unselected.

Rows can be filtered based on their selected state by cycling through the tri-state icon at the top-left of the filter input row. (Also see table state for more information)

  • FilterNone: Show all rows

  • FilterSelected: Show only selected rows

  • FilterUnselected: Show only unselected rows

The multiMin and multiMax properties can limit how many table rows can be selected. If multiMax is set to 1, the table renders radio buttons instead of checkboxes.

multiMin

Minimal needed selected rows before the table onSubmit action can be triggered.

multiMax

Maximum allowed selected rows.

pagination

When set to false, disables the pagination functionality of the table, showing all the rows from the database on one page. Toolbar is also hidden if there is no onSubmit action defined.

pageSize

With pagination enabled, sets the maximum number of rows shown per page.

rules

Array of conditional formatting rules. See below

showHoverHighLight

Enable/disable hover effect on the table rows.

showSelectedRow

Background color will change when a table row is clicked. Defaults to true when onSelect pipeline is defined.

showRefreshButton

Set this to false to hide the refresh button. By default, the refresh button is visible.

showRowNumbers

When set to true shows a row-number in the first column of the table. The numbers are not bound to the data, nor are they part of the table schema, and remain unchanged when sorting or filtering is applied.

showToolbar

Use to hide the complete toolbar.

style

Property used to define static style settings for the table header and body. See Table styles for more details.

styleByTheme

Property used to define static style settings for the table based on the active theme.

For example:

{
    "options": {
        "style": {
            "fontSize": "14px",
        },
        "styleByTheme": {
            "dark": {
                "color": "yellow"
            },
            "light": {
                "color": "blue"
            }
        },
    }
}

submitButton

The text-label of the submit-button, which appears in the bottom right corner of the table when an onSubmit action pipeline is defined, can be assigned a custom value by assigning a string to its label property.

{
    "options": {
        "submitButton": {
            "label" : "Custom submit Text"
        }
    }
}

refreshInterval

Refresh with an interval in seconds.

Table Styles

There are a number of properties available in the model which allow the table header and content to be styled. The order of precedence in which styles are applied depends on where they are declared, as shown here from lowest to highest:

  • options: For all widgets, overall style settings can be defined in the options property, as shown above.

  • options.rules: Conditional styling rules declared in the options property provide a means to control the appearance of matching rows. Rules don’t affect the header appearance.

  • schema: Column specific styles can be defined in the schema section of the model. These affect both the table header and data.

  • options.header: Used to explicitly control the appearance of the header row. When set it takes precedence over the style settings in both the options.style and schema.style sections.

  • schema specific header: The appearance of a column header can be further customized on a column by column basis using the header element in the schema section.

  • schema specific rules: Conditional styling defined in the schema section affects only the data cells for which the rule conditions match, as opposed to those in the options, which affect the row as a whole.

For each of the properties listed style and/or styleByTheme can be defined. styleByTheme settings override style settings at the same level.

Conditional Styling Using Rules

The appearance of individual data rows and/or cells can be conditionally set using rules defined inside the options property, for rows, and in the schema elements for cells.

The rules property is an array, allowing multiple rules to be applied to the same or different fields.

When value or range properties are used as the rule condition, each rule refers to a single field in the data for input. Which data field is used can either be explicitly specified using the name property, or implicitly by virtue of the schema element the rule resides in. When the data field value matches the rule value or range, the style/styleByTheme settings are applied.

{
    "options": {
        "rules": [
            {
                "name": "temperature",
                "value": 20,
                "style": {
                    "backgroundColor": "green",
                    "fontSize": "15px",
                    "fontWeight": "normal"
                }
            },
            {
                "name": "temperature",
                "range": {
                    "from": 22,
                    "to": 26
                },
                "style": {
                    "fontWeight": "bold"
                }
            }
        ]
    }
}
name description

match

A match expression defines a condition that determines whether the style or styleByTheme settings in the rule should be applied to the associated table row or cell. It is similar to that used in the tree widget rules.

The input to the match expression is the table data element/object of the row for which the condition is being evaluated. This means that irrespective of whether the rule is defined in the options or schema property, all fields in the data row can be referenced in the expression.

The match expression is only evaluated if the rule type is set to "match". Specifying the rule type as "match" will override the range and value properties.

The example below shows how a match expression can be used to apply style settings based on the value of a single data field. In this case, the rule checks if the name field is "Average Temperature" and if it is, the corresponding cell will be green.

{
    "schema": {
        "name": "name",
        "title": "Name",
        "rules": [
            {
                "type": "match",
                "match": {
                    "name": "Average Temperature"
                },
                "style": {
                    "backgroundColor": "forestgreen"
                }
            }
        ]
    }
}

This second example shows how a match expression can be used to apply style settings based on the values of multiple data fields. In this case, the rule checks if the name field starts with "Inside" AND if the value field is greater or equal to 25. If so, the row text will be red.

{
    "options": {
        "rules": [
            {
                "type": "match",
                "match": {
                    "name": {
                        "$regex": "^Inside.*"
                    },
                    "value": {
                        "$gte": 25
                    }
                },
                "style": {
                    "color": "red"
                }
            }
        ]
    }
}

name

Name of the data field the rule condition refers to. For rules in the model options section, the name field is mandatory when using value or range conditions. If the name is omitted in schema rules, the current schema column field is assumed.

range

Used to define a numeric from and to range the field value should fall within.

When from is provided on its own, the rule matches field data greater than or equal to the stated value. To match values less than a certain upper bound, only the to property should be set.

Note: The to value is excluded from the range.

style styleByTheme

Define the appearance of the row or cell when the rule condition is met.

type

Can be one of the following options:

  • equal: Check if the input is equal to a specific value.

  • match: Use a match expression as the rule condition.

  • isNull: Check if the input field is null.

  • isUndefined: Check if the input field is undefined.

  • range: Check if the input is within a numeric range.

value

The exact value to match the data field to.

Schema

The table schema is used to control which fields in the data to show, how they are shown and in what order.

The schema can be statically defined in the model but can also be provided by a dataSource. If this is the case, the model schema should be omitted, since it takes precedence over any returned by the data source UNLESS the dataSource contains a type field set to "table" in which case the schema in the dataSource is used!. (Also refer to the widget dataSource rules.)
{
    "schema": [
        {
            "name": "id",
            "hidden": true
        },
        {
            "title": "Population",
            "name": "population",
            "filter": "select",
            "type": "number",
            "editable": true,
            "value": 100
        },
        {
            "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!"
                }
            }
        }
    ]
}
name description

editable

Instead of making every cell editable with setting editable: true on the table, there’s an option to set this property on selected columns only. The input should match the type declared for the cell. If the input is invalid for the selected schema type, the current value will remain unchanged and the input box appearance will change to warn the user. Note that this only affects the original dataset if the table is saved and the user has the permissions to overwrite data (optional, default is false).

enum

The enum property is used to declare a set of key-value pairs that can be used to translate the content of the field. Refer to the formatting section below for more details.

filter

Used to define which input control is shown when the table filter is activated. Options are:

  • none: Prevent filtering on the current column.

  • text: This is the default filter type. Which rows are shown, depends on the selected filter mode and the filter text entered. The applied logic is to include all rows where <mode-verb> applied to the cell value matches the specified filter text. Supported filter modes are:

    • Starts With

    • Ends With

    • Contains (Default Mode)

    • Equal

    • Not Equals

    All comparisons are case insensitive.

  • select: A drop-down is presented, containing the set of unique values in the column data fields. If the data includes fields that are undefined or null, or empty string (""), then the list will contain matching entries shown as (undefined), (null) or (blank). The data is filtered to the selected value.

  • range: Applies to number fields. When selected, an inclusive lower and excluded upper bound can be provided.

  • slider : Applies to number fields. The slider is ranged from the smallest to largest value in the column. As the slider is moved, the entries to the left of the marker are filtered out.

format

When type is date, the date format can be changed within the optional format property. Example of date formats: "YYYY-MM-DD HH:mm:ss.SSS", LLLL, DD.MM.YYYY HH:mm (optional).

header

Used to define style and styleByTheme attributes for individual column headers. These settings override the options.header parameters, which apply to the header row as a whole.

hidden

Property used to control column visibility (optional)

id

When column names are repeated in the schema section, WebStudio will automatically generated a unique id for all but the first occurrence. The id field for the repeated columns will consist of the field name with a count suffix appended, such as "date_2" for example. The count starts at 2 and increments from there for each repeated name.

The id can also be explicitly provided in the initial-model, in which case any unique value can be assigned. Note: If the assigned id is itself repeated in the schema, from the second occurrence on, WebStudio will disambiguate them in the same ways as the name by appending a count to the end.

isExpander

This option can be used for hierarchical data structures, it enables collapsing and expanding table rows. Set isExpander: true on a key of sub rows item, which is of type array. Key has to be defined in data structure. Global or column filtering of the table is not supported when this options is used. Default collapsedIcon and expandedIcon can be replaced by custom icons, e.g. emoji or special characters.

items

Cell value can be selected from a dropdown list containing predefined values.

name

Key name of the data field displayed in this column. 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 id field is used to identify the column instead. In the examples below, further details can be found on how to bind table columns to data. Topics covered are:

numberOfDecimals

This property only applies when the field is of type number. The numberOfDecimals property specifies how many digits to show after a decimal separator (optional).

rules

Custom styling rules.

sort

Property to define default sorting on the column. Accepted values: asc (ascending), desc (descending), none (no sorting). Default table sorting on multiple columns is possibly by defining sort in multiple schema items. The column order defines the sorting order. Note that sorting doesn’t change the original row indexes (optional, default is none).

style

Optional styling for the column.

styleByTheme

Optional theme specific styling for the column.

title

Column title.

tooltip

Tooltip text to display when the mouse hovers over the table column header or a table cell. Depending on how the property is configured either a header or a cell tooltip will be shown. The options are as follows:

  • Not set: If the tooltip is not explicitly assigned a value, the column title will be shown as the tooltip or the column name if that too is missing when hovering over the header. No tooltip is shown for the cells in the column.

  • Text string: If a text value is assigned to the property, this will be used as a header tooltip. No cell tooltip will be shown.

  • Tooltip object: An object value can also be assigned to the property to display tooltips on table cells rather than on the header. This provides a way to have dynamic tooltips which are specific to each cell. The object supports the following properties:

    • type: The tooltip type can be either "fixed", in which case all cells will use the same tooltip.text value, or "dynamic" to have the tooltip text read from the row data field named in the tooltip.field setting.

    • field: Defines the name of the data field used to source the cell tooltip.

    • text: Defines the tooltip text to show when the type is "fixed" or when the data row has no value in the nominated field

type

The type property defines how a data field is displayed and the edit control used to modify its value. It says nothing about the source type of the data field referenced in the column. The source and column types should however be compatible.

For example, If the type of a data field is a number and you set the schema column type to string, then users will be able to enter a non-numeric value in the input for this field (which is likely going to be incorrect). Furthermore, when a table entry is edited, the changed value is written back to the data field using the assigned type.

The appearance of cell values can be adjusted by assigning different types to the column. The default formatting of date and number types depends on the user’s locale settings. Date fields can also be shown differently by using the format property.

Valid field types are:

  • string: when the column is editable a single-line edit box is used as the input control.

  • text: For read-only fields, there is no difference between the string and text types. If the field can be edited, a "Text Area" input control will be used, which allows the content to wrap.

  • number: The input text-box limits the user to only enter numbers. The source data type should be a number (either integer or real number).

  • date: The source data field is formatted as a date-time. The source type can be either an epoch integer or an ISO 8601 Date string. The input control checks that the text entered is a valid time expression. Since there is no "date" JSON type, the source type of the field is preserved when editing dates.

  • duration: The source data field which should be a number, in units of milliseconds, is displayed as a duration string using the format:

    [d days] HH:mm:ss

    The days section is omitted if the duration is less than one day. Fields of this type are read-only irrespective of the editable property’s value. When the underlying data field is null or not provided, no output is generated. "Invalid duration" is shown if the input field cannot be formatted as a duration string.

value

A default field value can optionally be provided. It is shown when the data doesn’t contain an entry for this field.

width

Column width can be manually set by providing a size in pixels, such as "300px" for example. The Width declared in the schema will override the default column size.

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 the id 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"
        }
    ]
}

Dealing with composite data

In most cases the data presented to the table is likely to be in the form of a flat array where each element contains a set of named fields and their values. Something like:

{
    "data": [
        {
            "value": 26,
            "location": "Eindhoven"
        },
        {
            "value": 18,
            "location": "Cologne"
        }
    ]
}

Mapping these to columns in the table is simply a matter of setting the name field in the schema definitions to the corresponding field in the data…​ like so:

    "schema": [
        {
            "name": "location",
            "title": "City",
        },
        {
            "name": "value",
            "title": "Temperature"
        }
    ],

Occasionally, you may need to deal with data that has composite values as shown:

{
    "data": [
        {
            "temperature": {
                "wetBulb": 22,
                "dryBulb": 26
            },
            "location": "Eindhoven"
        },
        {
            "temperature": {
                "wetBulb": 17,
                "dryBulb": 18
            },
            "location": "Cologne"
        }
    ]
}

One way to deal with this would be to transform the data by moving all the fields to the root object. Fortunately this is not necessary since you can bind to nested fields directly. Simply assign the dot-notation property key to the name parameter in the schema.

    "schema": [
        {
            "name": "location",
            "title": "City"
        },
        {
            "name": "temperature.wetBulb",
            "title": "Wet Bulb Temperature"
        },
        {
            "name": "temperature.dryBulb",
            "title": "Dry Bulb Temperature"
        }
    ],

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"
                }
            ]
        }
    ]
}

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

Customizing toolbars has become available for every widget. See Toolbars.

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

selectedRowIndex

list of 0 based row indices of selected rows

showColumnFilters

boolean flag indicating whether the bar used to edit column filters is visible or not.

showGlobalSearch

boolean flag indicating whether the global search input box is visible or not.

filters

List of filter objects

name

Name of the column the filter is applied to

value

Filter value. The content of this field depends on the type of the filter.

mode

Mode selected for the text filter. Valid options are:

  • startsWidth

  • endsWith

  • contains

  • equals

  • notEquals

type

The type field is used in conjunction with either the name or the value field. Which of the two is required depends on the selected type. The options are:

  • "isNull", "isUndefined": here type is used in place of value when looking for null or undefined fields in the data. The name field must be provided to indicate which column we are looking at and the filter property in the schema must be set to "select". In the example below, all rows where the "location" is undefined will be returned:

    {
        "schema": [
            {
                "name": "name",
                "title": "Name"
            },
            {
                "name": "location",
                "title": "Location",
                "filter": "select"        // Set the filter type
            }
        ],
        "state": {
            "filters": [
                {
                    "name": "location",    // Look for rows where the
                    "type": "isUndefined"  // location field is not set
                }
            ]
        }
    }
  • "selected": Used to filter rows based on whether they are selected or not (when options.multi = true). The selected state being sought is provided in the value field, for which the options are:

    • "notSelected": Return rows where the selection check box is un-checked

    • "selected": Return rows where the selection check box is checked

    • "all": return all rows irrespective of selection state

    In the example below, only selected rows, 1 and 2, in the table are shown:

    {
        "state": {
            "selectedRowIndex": [
                2,
                1
            ],
            "filters": [
                {
                    "type": "selection",
                    "value": "selected"
                }
            ]
        }
    }

search

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: If the filter type is set to "none" in the schema for a particular column, the filter state is ignored for that column.

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 include 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.

  • onSave: Save button is clicked and all rows are in the message.

  • 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

An onClick action defined in the schema is used to trigger pipeline execution when any field in the relevant column is clicked.

{
    "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
    }
}

Example to delete a row from the table using onClick

The schema definition below shows how to add a column to your table containing an icon, which can be clicked to delete a row.

{
    "schema": [
        {
            "type": "string",
            "value": "🗑",
            "actions": {
                "onClick": [
                    {
                        "type": "transform",
                        "aggregateOne": [
                            {
                                "$project": {
                                    "removeFromArray": [
                                        {
                                            "name": "model.data",
                                            "idx": {
                                                "$subtract": [
                                                    "$row._idx",
                                                    1
                                                ]
                                            }
                                        }
                                    ]
                                }
                            }
                        ]
                    },
                    {
                        "type": "modify",
                        "refresh": false,
                        "id": "self"
                    }
                ]
            }
        }
    ]
}

In the pipeline, the delete is performed in two steps.

  1. From the incoming message, row._idx is used to initialize the removeFromArray parameter needed by the modify action. Since the row._idx is provided as a 1-based number, we need to subtract 1 before assigning it. The output message from the first step after clicking on the icon in the first table row looks like this:

    {
        "payload": {
            "removeFromArray": [
                {
                    "name": "model.data",
                    "idx": 0
                }
            ]
        }
    }
  2. modify is invoked on the table, without specifying the removeFromArray property which will be taken from the incoming message. The refresh : false setting prevents the data from being reloaded from the back end when the table uses a dataSource

onSave

Gets invoked when the save button is pressed. The input message payload contains all data rows, unlike the onSubmit action hook, which only receives selected rows in the message. The save button appears in the toolbar when either of the following is true:

  • The table has a dataSource of type "read-write".

  • An onSave action pipeline is configured.

The onSave action hook is not required when the dataSource type is "read-write", since clicking the save button automatically writes the data rows back to the server.

A more interesting scenario presents when the dataSource is read-only and some additional processing is needed before the data can be saved. Another is when a specific server endpoint needs to be used to write the data to the server.

In the example below, the dataSource is configured to read from a Table Holder object while onSave is configured to write the data rows back. Note that the path in the write action needs to explicitly reference the TableData object property!

{
    "actions": {
        "onSave": {
            "type": "write",
            "path": "/System/Core/Examples/WebStudio/Tables/SalesOrders.TableData"
        }
    },
    "dataSource": {
        "path": "/System/Core/Examples/WebStudio/Tables/SalesOrders",
        "type": "read"
    },
}

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 message payload should contain a rowIndex 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"
            }
        ]
    }
}