Tables
Tables
The table component is a highly configurable, feature rich and navigable data grid. It allows for presentation of data in many different ways, and it is often possible fulfil business requests, just by configuration. The table implements the common framework concept and uses Cytoscape.js#data eles data select keys to configure data into cells. Read Understanding the graph model to learn more about the high level concept.
{
"tables" : {
"example" : {
"datasets": ["rootNodesInitalLoadData"],
"columns": [
"title",
"owner",
"state",
"DEFAULT_SEPARATOR",
"related_docs"
],
"services": ["initialLoadService"],
"expand": {
"services": ["expandService"],
"datasets": ["expandData"]
}
}
}
}
Table properties
| Prop Name | Description | Data Type | Required | Example |
|---|---|---|---|---|
columns | List of column names to display in the table. "DEFAULT_SEPARATOR" is a built in column that adds a small space in between columns. | array string | yes | ["title", "name","DEFAULT_SEPARATOR" "state"] |
contextMenu | Reference to a context menu definition. | string | no | "issueContextMenu" |
datasets | References to datasets providing data for the table. | array string | yes | ["issueData"] |
deferredServices | Services loaded lazily after initial render. | array string | no | ["lazyLoadDetails"] |
dropHandler | Reference to a drop handler for drag-and-drop functionality. | string | no | "dropHandler": "cr_table_drop_zone", |
expand | Configuration for expandable rows or data. | object | no | Table expand |
name | Name of the table (not used explicitly here). | string | yes | "IssueTable" |
services | References to services fetching data for the table. | array string | no | "services": ["fetchAllIssues"] |
settings | Table-specific settings (e.g., drag behavior, column mapping). | object | no | {"multiDraggable": true} |
toolbars | Reference to a toolbar definition for interactivity. Panel commands may use useSelectedRow to bind the opened form to the selected table row. See Commands — Panel commands. | string | no | "toolbars": "toolbar_issue_details" |
Context menu
Right-clicking a table row shows a context menu. Define menus in the top-level contextMenus map and reference one by name from the table's contextMenu property. Each menu is an array of command-name references — commands themselves are defined in the top-level commands map (same pattern used by toolbars).
{
"tables": {
"productStructure": {
"datasets": ["contextNode"],
"columns": ["title", "owner", "state"],
"contextMenu": "openWithMenu"
}
},
"contextMenus": {
"openWithMenu": ["openWith", "promote", "demote"]
},
"commands": {
"openWith": {
"type": "openWith",
"isMenu": true,
"label": "Open With",
"openApps": {
"ENOLCMI_AP": { "label": "Item Lifecycle" },
"VPLMProjectManagement_AP": { "label": "Project Management" },
"ENO3DMultiCAD_AP": { "label": "3D Multi CAD" }
}
},
"promote": {
"label": "Promote",
"type": "genericService",
"settings": {
"relatedConfig": {
"services": ["promoteItemService"],
"responseMapping": { "expression": "results[0].maturityState", "attribute": "state" }
}
}
},
"demote": {
"label": "Demote",
"type": "genericService",
"settings": {
"relatedConfig": {
"services": ["demoteItemService"],
"responseMapping": { "expression": "results[0].maturityState", "attribute": "state" }
}
}
}
}
}
contextMenus map
| Field | Description | Type | Required |
|---|---|---|---|
<menuName> | An ordered list of command-name references. Items are rendered in declaration order. | array of string | yes |
Open With submenu
If one of the referenced commands has type: "openWith", it is rendered as a submenu (with a ▶ arrow) instead of a plain menu item. Hovering the entry reveals a submenu containing:
- The apps declared in the command's
openApps, in declaration order. - A More apps… entry (always appended) — opens the Compass side panel so the user can pick any other compatible app.
The submenu label comes from the openWith command's label. openApps is an object where each key is the app ID and the value is { "label": "..." }. An app entry may also carry icon, ds-icon and icon-color to show a coloured glyph next to its label — see Commands — Icons. Only configured entries take these; apps discovered from the platform supply their own image, which is not recoloured.
Submenus (isMenu: true)
Any context menu entry can be turned into a nested submenu by setting isMenu: true and defining the submenu in the top-level menus array. Hovering the entry reveals the submenu with a ▶ arrow.
{
"contextMenus": {
"myMenu": [
"openWith",
"stateActions"
]
},
"menus": {
"stateActions": {
"label": "State Actions",
"icon": "Workflow",
"ds-icon": "fonticon fonticon-collaborative-lifecycle-management",
"commands": ["promote", "demote"]
}
},
"commands": {
"promote": {
"label": "Promote",
"type": "genericService",
"settings": {
"relatedConfig": {
"services": ["promoteItemService"],
"responseMapping": [
{ "expression": "results[0].maturityState", "attribute": "state" }
]
}
}
},
"demote": {
"label": "Demote",
"type": "genericService",
"settings": {
"relatedConfig": {
"services": ["demoteItemService"],
"responseMapping": [
{ "expression": "results[0].maturityState", "attribute": "state" }
]
}
}
}
}
}
The context menu entry "stateActions" is resolved from the top-level menus map because that name is defined there. The label, icon and ds-icon on the menu definition control what the parent entry looks like — you do not repeat them in contextMenus. Commands inside the submenu are looked up from the same top-level commands map.
ds-icon renders the 3DEXPERIENCE icon-font glyph inside the DS widget shell, with icon as the bundled fallback everywhere else, and the optional icon-color tints whichever one is drawn; see Commands — Icons.
You can still use { "name": "stateActions", "isMenu": true } explicitly, or add inline label / icon / ds-icon / icon-color overrides on the context menu reference when needed.
menus array
| Field | Description | Type | Required |
|---|---|---|---|
name | Unique identifier referenced by isMenu: true entries in contextMenus. | string | yes |
label | Display label for the submenu parent entry. | string | yes |
icon | Bundled icon for the submenu parent entry — a lucide icon name, or a path/URL to an image. | string | no |
ds-icon | 3DEXPERIENCE icon-font classes for the submenu parent entry, e.g. "fonticon fonticon-collaborative-lifecycle-management". Used in preference to icon when the shell's icon font is loaded. See Commands — Icons. | string | no |
icon-color | Optional CSS colour for the submenu parent entry's icon, e.g. "#6a1b9a". Applies to the ds-icon glyph and to a lucide icon; image icons are not recoloured. | string | no |
commands | Ordered list of { "name": "<commandName>" } references into the top-level commands map. | array | yes |
contextMenus entry fields (when using isMenu)
A context menu array item can be either a plain string (command reference) or an object:
| Field | Description | Type | Required |
|---|---|---|---|
name | Command or menu name to look up. | string | yes |
isMenu | Set to true to render this entry as a submenu (resolved from the menus array). When omitted, a name that exists only in menus is treated as a submenu automatically. Set to false to force command lookup. | boolean | no |
label | Inline label override. When present, overrides the label from the resolved command/menu definition. | string | no |
icon | Inline icon override. | string | no |
ds-icon | Inline icon-font override, e.g. "fonticon fonticon-pin". Wins over the ds-icon on the resolved command/menu definition. See Commands — Icons. | string | no |
icon-color | Inline icon-colour override, e.g. "#c0392b". Wins over the icon-color on the resolved command/menu definition. | string | no |
Command types
Commands referenced from a context menu (or from inside a menus submenu) support the following type values:
type | Description |
|---|---|
openWith | Renders an Open With submenu populated by the command's openApps. |
genericService | Calls a service on the selected row's object. services is an array of service names (strings). After the call completes, the row is refreshed according to settings.relatedConfig.refreshBehavior or responseMapping. |
close / closeContext | Removes the right-clicked row (or all selected rows) from the widget context. Only shown for rows that are part of the widget context (i.e. xuiContext: true). |
Commands without a type are treated as plain menu items — clicking invokes the configured onClick handler (if any).
Conditional visibility (condition)
A command can declare a condition that is evaluated against the row data at render time. If the condition is not satisfied, the menu item is hidden. The syntax uses bracket-notation — the same style as service nodeCondition / edgeCondition selectors.
"commands": {
"close": {
"label": "Close",
"type": "close",
"icon": "X",
"condition": "[xuiContext]"
},
"promote": {
"label": "Promote",
"type": "genericService",
"condition": "[state = \"InWork\"]",
"settings": {
"relatedConfig": {
"services": ["promoteItemService"],
"responseMapping": { "expression": "results[0].maturityState", "attribute": "state" }
}
}
},
"reject": {
"label": "Reject",
"type": "genericService",
"condition": "[state != \"Approved\"]",
"settings": {
"relatedConfig": {
"services": ["rejectItemService"]
}
}
}
}
Supported expressions:
| Expression | Evaluates to true when… |
|---|---|
[prop] | row.prop is truthy (non-null, non-empty, non-false) |
[prop = "value"] | row.prop equals "value" (string comparison) |
[prop != "value"] | row.prop does not equal "value" |
Multiple bracket expressions are AND-ed together:
"condition": "[xuiContext][state = \"InWork\"]"
This shows the item only when the row is a context object and its state is InWork.
The condition field is supported on:
- Top-level context menu commands
- Commands inside a
menussubmenu (isMenu: true)
When condition is omitted, the item is always visible (existing behaviour unchanged).
refreshBehavior values
| Value | Description |
|---|---|
refreshRowWithColumnService | Re-fetches column-level services for the affected row only. |
refreshRow | Re-renders the row from the current graph data without a network call. Used automatically when responseMapping is defined. |
expandRow | Expands the affected row, rebuilding its children from the graph datasets alone — no service call. Use it when the action already put the children in the graph. |
expandRowWithService | Expands the affected row and calls the table's expand service to fetch children that are not in the graph yet. |
removeRow | Detaches the affected row from the table. Use it after an action that moves the object out of the current view. |
syncRows | Table scoped: re-runs the table's datasets against the graph, adding rows that are new and dropping ones that are gone. Needs no selected row, so it is the one to use after a service that creates an object. |
refreshParents also exists in the configuration schema but is currently a no-op — do not rely on it.
refreshBehavior is ignored whenever responseMapping is set on the same command — the row is re-rendered from the mapped graph data instead (equivalent to refreshRow). If you configure expandRow (or any other value) and nothing happens, check whether the command also defines responseMapping, and remove it if you want the refresh behaviour to run.
responseMapping — update the row from the service response
When a genericService command returns data that should be immediately reflected in the table (for example a maturity state change), use responseMapping instead of refreshRowWithColumnService. The row updates instantly from the service response — no second network round-trip is needed.
"promote": {
"label": "Promote",
"type": "genericService",
"settings": {
"relatedConfig": {
"services": ["promoteItemService"],
"responseMapping": { "expression": "results[0].maturityState", "attribute": "state" }
}
}
}
responseMapping fields:
| Field | Description | Type | Required |
|---|---|---|---|
expression | JSONata expression evaluated against the raw HTTP response body. | string | yes |
attribute | Graph node attribute to write the result to. Must match the data field of the target column definition. | string | yes |
Finding the right attribute name — look at the column definition; the data field is the graph attribute:
"maturity_state": {
"label": "Maturity State",
"data": "state"
}
Here "data": "state" means the graph attribute is state, so "attribute": "state" is correct.
Multiple attributes — pass an array:
"responseMapping": [
{ "expression": "results[0].maturityState", "attribute": "state" },
{ "expression": "results[0].owner", "attribute": "owner" },
{ "expression": "results[0].modifiedDate", "attribute": "modified" }
]
JSONata expressions can transform values, not just extract them:
{ "expression": "$uppercase(results[0].maturityState)", "attribute": "stateLabel" }
When responseMapping is defined, refreshBehavior is ignored — the row re-renders directly from the updated graph data.
Open with app (column-level)
You may also set launchApp on an individual column for a single-app left-click launch (no menu). The right-click Open With menu is configured via context menus / the openWith command as shown above.
Selecting an entry invokes the platform-provided handler (the same one the OOTB Compass uses), so the chosen app opens via TransientWidget with the row's object as context.
launchApp — direct left-click launch
launchApp (configured under column.settings) makes the column's main link open the row object directly in a pre-configured OOTB app in a single click, instead of navigating within the widget. It takes precedence over href on the same column.
For launch behavior, use the array form:
"name": {
"label": "Name",
"data": "name",
"iconSelect": "",
"settings": {
"launchApp": [
{
"renderer": "nameHyperlink",
"mappings": [
{
"app": "ENOPSTE_AP",
"condition": { "node": "[type='VPMReference']" }
},
{
"app": "ENOLCMI_AP",
"condition": { "node": "[type='Change Action']" }
},
{
"app": "ENOLCMI_AP"
}
]
},
{
"renderer": "iconhyperlink",
"mappings": [
{
"app": "ENOPSTE_AP",
"iconSettings": {
"name": "Info",
"strokeWidth": 2,
"size": 21,
"color": "#368ec4"
},
"condition": { "node": "[type='VPMReference'][state='FROZEN']" }
},
{
"app": "X3DPLAW_AP",
"iconSettings": {
"name": "box",
"strokeWidth": 2,
"size": 21,
"color": "#368ec4"
},
"condition": { "node": "[state='RELEASED']" }
},
{
"app": "ENOLCMI_AP",
"iconSettings": {
"name": "Recycle",
"strokeWidth": 2,
"size": 21,
"color": "#f39c12"
}
}
]
}
]
}
}
When no app resolves for a row's object type and the column also defines an href, the link falls back to the normal in-widget navigation.
The rendered link shows a hand (pointer) cursor on hover and a tooltip built from mappings[].label (falling back to the app id).
Out-of-the-box app image (imageSettings)
For an iconhyperlink mapping you can render the app's out-of-the-box image instead of a lucide icon by providing imageSettings. When imageSettings resolves to a URL it takes precedence over iconSettings.
{
"app": "ENXENG_AP",
"label": "Engineering Release",
"imageSettings": {
"image": "widget/images/MyApps/ENXENG_AP_AppIcon.svg",
"baseURL": "${app.urls.myapps}",
"alt": "Engineering Release",
"size": 21
}
}
imageaccepts both absolute URLs (https://…,//…,data:…) and relative paths.- A relative
imageis joined onto the resolvedbaseURL. baseURLmay be a literal URL or a${propertyKey}macro. A macro is resolved againstPlatformAPI.getAllApplicationConfigurations()— for example${app.urls.myapps}resolves to that property's value (e.g.https://…/enovia). Unknown keys resolve to an empty string.
| Property Name | Description | Data Type | Required | Example |
|---|---|---|---|---|
renderer | Renderer name for a launchApp array entry (for example nameHyperlink or iconhyperlink). | string | yes | "nameHyperlink" |
mappings[].app | OOTB app id launched when this mapping matches. | string | yes | "ENOPSTE_AP" |
mappings[].label | Tooltip text shown on hover. Falls back to the app id. | string | no | "Engineering Release" |
mappings[].condition | Optional object with node/edge selector condition. If omitted, mapping is always eligible. | object | no | {"node":"[type='VPMReference']"} |
mappings[].iconSettings | Lucide icon config for iconhyperlink mappings. Required unless imageSettings is provided. | object | conditional | { "name": "Info", "size": 21 } |
mappings[].imageSettings | OOTB image config for iconhyperlink mappings. Takes precedence over iconSettings. | object | conditional | { "image": "…", "baseURL": "${app.urls.myapps}" } |
mappings[].imageSettings.image | Absolute URL or path relative to baseURL. | string | yes (within imageSettings) | "widget/images/MyApps/ENXENG_AP_AppIcon.svg" |
mappings[].imageSettings.baseURL | Literal base URL or ${propertyKey} macro resolved via PlatformAPI.getAllApplicationConfigurations(). Used only for relative image values. | string | no | "${app.urls.myapps}" |
mappings[].imageSettings.alt | Alt text for the image (also used as tooltip fallback). | string | no | "Engineering Release" |
mappings[].imageSettings.size | Image width/height in pixels. | number | no | 21 |
mappings[].type | Optional metadata only. Not used by launch selection logic. | string | no | "VPMReference" |
Settings properties
| Prop Name | Description | Data Type | Required | Example |
|---|---|---|---|---|
colorMappedColumn | Reference to a column name that will have color mapping applied. | string | no | "priority" |
multiDraggable | Allows selecting multiple rows for drag-and-drop. The related column data is dragged together. | boolean | no | true |
onTableRowDropEnable | Enables a drop zone on top of the table for supporting drag-and-drop connections. | boolean | no | true |
hideAncestorValuesOnFilter | In a tree table, a parent row stays visible while a column filter is active when one of its children matches, even if the parent itself does not. By default the table empties, on that parent, the filtered column and the multi-value columns lined up with it (for example the whole Derived Outputs group under a Format = DWG filter), so it no longer lists values the filter excluded. This matches what the filtered download commands include. Only columns that list related objects are emptied: columns about the row itself, such as Title, Name or Type, always render, even when the filter is on one of them. A filtered column the parent itself passed also still renders. Set to false to keep showing all of the parent's values. Defaults to true. | boolean | no | false |
avoidColumnServiceRecall | Reuses data already present in the data store (graph) instead of re-calling column level and expand services when a row is collapsed and expanded again. Explicit refresh actions and row edits still refetch. Defaults to false. | boolean | no | true |
paginationEnable | if set false then pagination disabled for table. | boolean | no | "paginationEnable": false |
paginationConfig | Control selectable pagination sizes and the default used | object | no | "paginationConfig":{ "pagination": true, "itemsPerPage":[25,50,100], "defaultItemsPerPage": 25 } |
Expand properties
Expand setting defines how rows or nodes are expanded in a structure table. For expanding node in some cases a service call is needed to fetch the data. Dataset is used to navigate to or from the node / row to get child nodes.
| Prop Name | Description | Data Type | Required | Example |
|---|---|---|---|---|
datasets | Defines which datasets to call to navigate from row or node to get child nodes. | array string | yes | "expand": { "services": [ "physicalProductService" ], "datasets": [ "ups1Level" ] }, |
services | In case data is not yet present in data store (graph) services are used to load data on expandRow that is getting expanded as used as contextId while calling service | array string | no | "expand": { "services": [ "physicalProductService" ], "datasets": [ "ups1Level" ] }, |
expandRootNodesOnLoad | Set to true for making default expand enable for level 1 | boolean | no | "expand": { "services": [ "physicalProductService" ], "datasets": [ "ups1Level" ], "expandRootNodesOnLoad": true } |
Advanced table implementations
The table component allows advanced implementations such as custom rendering or data calculations using the plugin architecture. Learn more about plugins in Plugin code extensions.