Skip to main content
This page has limited source coverage. Some behaviors should be verified against the running application.

Renderer Architecture

Custom renderers sit between the data model and the grid display. When Risksheet renders a cell, it first applies built-in rendering for the column type, then invokes any custom renderer registered for that column binding.
risksheet.json             Top Panel Template         Grid Cell
───────────────            ─────────────────          ──────────
"columns": [{              risksheetTopPanel.vm       Rendered output
  "id": "severity",  ──>   <script>            ──>   with custom
  "cellRenderer":            function renderSev       HTML, styles,
    "renderSev"              (grid, cell, item,       and formatting
}]                           value) { ... }
                            </script>
Configuration              Implementation             Display

Configuration Properties

Column-Level Renderer Assignment

Register a custom renderer on a specific column using the cellRenderer property in the column definition.
NameTypeDefaultDescription
cellRendererstringundefinedThe name of a JavaScript function registered on window.risksheet.cellDecorators that controls how the cell value is displayed. The function is invoked during cell rendering for every row in that column.
{
  "columns": [
    {
      "id": "severity",
      "header": "Severity",
      "width": 120,
      "type": "rating:severity",
      "cellRenderer": "renderSeverityCell"
    }
  ]
}

Row Header Renderer

The row header (the leftmost fixed column showing row numbers) supports a custom renderer through the headers configuration.
NameTypeDefaultDescription
headers.rowHeader.rendererstringNoneThe name of a cell decorator function applied to row headers. Typically used to apply conditional styling based on row data (e.g., coloring row headers by RPN value).
{
  "headers": {
    "rowHeader": {
      "renderer": "rowHeaderRpnNew"
    }
  }
}
Custom cell renderers are not applied during comparison mode. When viewing revision differences, cells use the standard comparison highlighting instead of custom rendering logic.

Renderer Function Signature

Each custom renderer function receives four parameters:
ParameterTypeDescription
gridobjectThe grid control instance, providing access to grid-level settings, column definitions, and data operations
cellHTMLElementThe DOM element for the cell being rendered. You can modify its innerHTML, style, className, and child elements
itemobjectThe work item data for the current row. Access any bound field value via item['fieldName']
valueanyThe current cell value after any formula calculation. May be null or undefined for empty cells
Define renderer functions in the Top Panel Template using a <script> block, or register them on the global window.risksheet.cellDecorators object from any script loaded into the page.

Built-In Column Type Rendering

Risksheet applies built-in rendering for standard column types before custom renderers execute. Understanding these defaults helps you write renderers that augment rather than conflict with standard behavior.
Column TypeBuilt-In Rendering Behavior
Item link (isItemLink)Displays as HTML hyperlink from the _link postfix property. New items (ID starting with *) show an asterisk prefix with a special CSS class. Supports custom property bindings for display.
Multi-item link (multiItemLink)Parses JSON array with id, label, and title properties. Each link renders as a separate <div> element with a title tooltip showing the full ID and title. Hidden bracket separators between items support clean copy/paste behavior.
Multi-enum (multiEnum:id)Selected values render as span.multi-enum-list containing span.multi-enum-item elements. Reads enum options from configuration and renders selected values with their display labels. Falls back to raw value if the enum option is not found.
Date (date)Parses date strings in YYYY-MM-DD format to local time Date objects. Formats the date according to the column’s format property using the Globalize library and the configured global.culture locale.
Task link (isTaskLink)Displays HTML content from the _link postfix property. Rendering behavior matches item links but is specific to task relationships.
Boolean (boolean)Renders as a checkbox representation.
Server-rendered (serverRender)Displays server-generated HTML content as-is without client-side modification.
HTML content (isContentHtml)Cell content is rendered as HTML rather than plain text.

Formula Integration with Renderers

Formulas execute during cell rendering and produce the value parameter passed to custom renderers. This means your renderer receives the calculated result, not the raw stored data.
PropertyTypeDefaultDescription
formulastringundefinedName of a formula function defined in the formulas object. Formulas execute with info.item context, returning the calculated value. Columns with formulas are automatically read-only.
{
  "formulas": {
    "commonRpn": "function(info){ var value = info.item['occ']*info.item['det']*info.item['sev']; return value?value:null;}"
  },
  "columns": [
    {
      "id": "rpn",
      "header": "RPN",
      "width": 80,
      "formula": "commonRpn",
      "cellRenderer": "renderRpnBadge"
    }
  ]
}
When a formula result differs from the stored value, the system can mark the item as edited. Formula changes respect the readOnly column setting. The formula mark changes behavior enables tracking of calculated field changes for audit purposes.

Read-Only Cell Marking

Cells are visually marked as read-only based on cell-level permissions. The readonly CSS class is applied to indicate non-editable cells. Read-only state is determined by checking the following conditions:
SourceCondition
Column readOnlyThe column definition has readOnly: true
Formula columnsThe column has a formula property set
Server render columnsThe column has a serverRender property set
System fieldsSystem-managed columns (ID, author, created)
Item permissionssystemReadOnly or systemReadOnlyFields includes the column binding
Task permissionssystemTaskReadOnly or systemTaskReadOnlyFields for task rows
Item stateTask attributes on items without tasks are read-only

Comparison and Baseline Highlighting

When a comparison manager is configured (viewing changes against a previous revision or baseline), Risksheet applies specialized cell highlighting that overrides custom renderers.
Highlight TypeApplies ToDescription
Added rowsEntire rowNew rows not present in the compared revision. Row background indicates addition.
Removed rowsEntire rowRows deleted since the compared revision. Row background indicates removal. Ghost items (deleted in one revision) are handled separately.
Modified cellsIndividual cellChanged property values between revisions. Cell background highlights the change. Tooltips explain the modification.
Not comparedIndividual cellColumns that cannot be meaningfully compared (e.g., formulas, server-rendered content).
Downstream addedTask columnsNew downstream task items linked to the master work item since the compared revision.
Downstream removedTask columnsDownstream items removed since the compared revision.
Downstream modifiedTask columnsProperty changes in existing downstream items. Tooltips identify the specific downstream item and change type.
During baseline comparisons, sorting operates on the baseline snapshot values rather than current values, except for system identity fields (systemItemId and systemItemRevision) which always refer to the current item.

Cell Decorator vs. Cell Renderer

Risksheet provides two mechanisms for customizing cell appearance. Understanding the distinction prevents configuration errors.
FeatureCell DecoratorCell Renderer
Configured viacellDecorators object in risksheet.jsoncellRenderer property on column definition
Function contextinfo object with info.value, info.cell, info.itemgrid, cell, item, value parameters
PurposeToggle CSS classes based on cell valueFull control over cell DOM content
Typical useConditional background/text colorsCustom HTML badges, icons, progress bars
Multiple per columnYes (cell decorator applies independently)One per column
Disabled in comparisonYesYes

Complete Example

The following example shows a full custom renderer setup for an FMEA risksheet with severity badge rendering, RPN color coding via row headers, and a custom risk acceptance indicator. Top panel template (risksheetTopPanel.vm):
<script>
  function renderSeverityCell(grid, cell, item, value) {
    if (!value) return;

    var colors = {
      "catastrophic": "#e53935",
      "critical": "#ff7043",
      "marginal": "#ffb74d",
      "negligible": "#66bb6a"
    };

    var color = colors[value.toLowerCase()] || "#9e9e9e";
    cell.style.backgroundColor = color;
    cell.style.color = "#fff";
    cell.style.fontWeight = "600";
    cell.style.textAlign = "center";
    cell.textContent = value;
  }

  function renderRiskLevel(grid, cell, item, value) {
    if (!value) return;

    var badge = document.createElement("span");
    badge.className = "risk-level-badge risk-" + value.toLowerCase();
    badge.textContent = value;
    cell.innerHTML = "";
    cell.appendChild(badge);
  }
</script>

<style>
  .risk-level-badge {
    padding: 2px 8px;
    border-radius: 3px;
    font-size: 11px;
    font-weight: 600;
    display: inline-block;
  }
  .risk-unacceptable { background: #e53935; color: #fff; }
  .risk-undesirable { background: #ff7043; color: #fff; }
  .risk-acceptable { background: #66bb6a; color: #fff; }
  .risk-negligible { background: #9e9e9e; color: #fff; }
</style>
Configuration in risksheet.json:
{
  "columns": [
    {
      "id": "id",
      "header": "ID",
      "width": 80,
      "readOnly": true
    },
    {
      "id": "title",
      "header": "Failure Mode",
      "width": 200
    },
    {
      "id": "severity",
      "header": "Severity",
      "width": 120,
      "type": "rating:severity",
      "cellRenderer": "renderSeverityCell"
    },
    {
      "id": "rpn",
      "header": "RPN",
      "width": 80,
      "formula": "commonRpn"
    },
    {
      "id": "riskLevel",
      "header": "Risk Level",
      "width": 120,
      "formula": "riskAcceptance",
      "cellRenderer": "renderRiskLevel"
    }
  ],
  "formulas": {
    "commonRpn": "function(info){ var value = info.item['occ']*info.item['det']*info.item['sev']; return value?value:null;}",
    "riskAcceptance": "function(info){ var rpn = info.item['occ']*info.item['det']*info.item['sev']; if(!rpn) return null; if(rpn>350) return 'Unacceptable'; if(rpn>150) return 'Undesirable'; if(rpn>50) return 'Acceptable'; return 'Negligible'; }"
  },
  "cellDecorators": {
    "rpn": "function(info){ var val = info.value; $(info.cell).toggleClass('boldCol', true); $(info.cell).toggleClass('rpn1', val>0 && val<=150); $(info.cell).toggleClass('rpn2', val>150 && val<=350); $(info.cell).toggleClass('rpn3', val>350);}"
  },
  "styles": {
    ".boldCol": "font-weight:600;",
    ".rpn1": "background-color: #eaf5e9 !important; color: #1d5f20 !important;",
    ".rpn2": "background-color: #fff3d2 !important; color: #735602 !important;",
    ".rpn3": "background-color: #f8eae7 !important; color: #ab1c00 !important;"
  },
  "headers": {
    "rowHeader": {
      "renderer": "rowHeaderRpnNew"
    },
    "columnHeader": {
      "height": 32
    },
    "columnGroupHeader": {
      "height": 32
    }
  }
}
Source Code
  • AppConfig.ts
  • WorkItemBasedReview.java
  • DocumentConfigProvider.java
  • CellPreviewFormatter.ts