14 KiB
SAP SAC Custom Widget JSON Schema Reference
Complete reference for the JSON metadata file that defines custom widgets.
Source: SAP Custom Widget Developer Guide - Section 6.1
Table of Contents
- Complete Schema Example
- Root Object
- Webcomponents Array
- Properties Object
- Methods Object
- Events Object
- DataBindings Object
- Custom Types
Complete Schema Example
{
"id": "com.company.advancedwidget",
"version": "1.0.0",
"name": "Advanced Custom Widget",
"description": "A feature-rich custom widget with data binding",
"vendor": "Company Name",
"license": "MIT",
"icon": "[https://example.com/icon.png",](https://example.com/icon.png",)
"newInstancePrefix": "advWidget",
"webcomponents": [
{
"kind": "main",
"tag": "advanced-widget",
"url": "[https://host.com/widget.js",](https://host.com/widget.js",)
"integrity": "sha256-abc123...",
"ignoreIntegrity": false
},
{
"kind": "styling",
"tag": "advanced-widget-styling",
"url": "[https://host.com/styling.js",](https://host.com/styling.js",)
"integrity": "sha256-def456...",
"ignoreIntegrity": false
},
{
"kind": "builder",
"tag": "advanced-widget-builder",
"url": "[https://host.com/builder.js",](https://host.com/builder.js",)
"integrity": "sha256-ghi789...",
"ignoreIntegrity": false
}
],
"properties": {
"title": {
"type": "string",
"default": "Widget Title",
"description": "The widget title"
},
"value": {
"type": "number",
"default": 0,
"description": "Numeric value"
},
"enabled": {
"type": "boolean",
"default": true,
"description": "Enable/disable widget"
},
"color": {
"type": "Color",
"default": "#336699",
"description": "Primary color"
},
"items": {
"type": "string[]",
"default": [],
"description": "List of items"
},
"config": {
"type": "Object<string>",
"default": {},
"description": "Configuration object"
}
},
"methods": {
"refresh": {
"description": "Refresh widget data",
"body": "this._refresh();"
},
"setValue": {
"description": "Set the widget value",
"parameters": [
{
"name": "newValue",
"type": "number",
"description": "The new value"
}
],
"body": "this._setValue(newValue);"
},
"getValue": {
"description": "Get the current value",
"returnType": "number",
"body": "return this._getValue();"
}
},
"events": {
"onSelect": {
"description": "Fired when an item is selected"
},
"onChange": {
"description": "Fired when value changes"
},
"onLoad": {
"description": "Fired when widget loads"
}
},
"dataBindings": {
"myData": {
"feeds": [
{
"id": "dimensions",
"description": "Dimensions",
"type": "dimension"
},
{
"id": "measures",
"description": "Measures",
"type": "mainStructureMember"
}
]
}
}
}
Root Object
| Property | Type | Required | Description |
|---|---|---|---|
id |
string | Yes | Unique identifier using reverse domain notation (e.g., "com.company.widgetname") |
version |
string | Yes | Semantic version (e.g., "1.0.0", "2.1.3") |
name |
string | Yes | Display name shown in SAC widget panel |
description |
string | No | Description shown in widget panel |
vendor |
string | No | Developer or company name |
license |
string | No | License type (MIT, Apache-2.0, proprietary) |
icon |
string | No | URL to widget icon (recommended: 32x32 PNG) |
newInstancePrefix |
string | No | Prefix for auto-generated script variable names |
webcomponents |
array | Yes | Array of web component definitions |
properties |
object | No | Widget properties accessible via script |
methods |
object | No | Methods callable from script |
events |
object | No | Events the widget can fire |
dataBindings |
object | No | Data binding configuration |
ID Best Practices
com.company.widgetname # Standard format
com.github.username.widget # GitHub-hosted
sap.sample.widget # SAP samples only
Webcomponents Array
Each widget can have up to three web components:
Main Component (Required)
{
"kind": "main",
"tag": "my-widget",
"url": "[https://host.com/widget.js",](https://host.com/widget.js",)
"integrity": "sha256-abc123...",
"ignoreIntegrity": false
}
Styling Panel (Optional)
{
"kind": "styling",
"tag": "my-widget-styling",
"url": "[https://host.com/styling.js",](https://host.com/styling.js",)
"integrity": "sha256-def456...",
"ignoreIntegrity": false
}
Builder Panel (Optional)
{
"kind": "builder",
"tag": "my-widget-builder",
"url": "[https://host.com/builder.js",](https://host.com/builder.js",)
"integrity": "sha256-ghi789...",
"ignoreIntegrity": false
}
Webcomponent Properties
| Property | Type | Required | Description |
|---|---|---|---|
kind |
string | Yes | "main", "styling", or "builder" |
tag |
string | Yes | Custom element tag name (lowercase, hyphenated, must contain hyphen) |
url |
string | Yes | URL to JavaScript file (HTTPS required for external hosting) |
integrity |
string | No | SHA256 hash for subresource integrity |
ignoreIntegrity |
boolean | No | Skip integrity check (development only, default: false) |
Tag Naming Rules
- Must be lowercase
- Must contain at least one hyphen (-)
- Cannot start with a hyphen
- Cannot use reserved names (like HTML elements)
Valid: my-widget, company-chart-v2, data-grid-component
Invalid: MyWidget, widget, my_widget
Properties Object
Simple Types
{
"stringProp": {
"type": "string",
"default": "default value",
"description": "A string property"
},
"numberProp": {
"type": "number",
"default": 3.14,
"description": "A floating-point number"
},
"integerProp": {
"type": "integer",
"default": 42,
"description": "An integer"
},
"booleanProp": {
"type": "boolean",
"default": true,
"description": "A boolean flag"
}
}
Array Types
{
"stringArray": {
"type": "string[]",
"default": ["item1", "item2"],
"description": "Array of strings"
},
"numberArray": {
"type": "number[]",
"default": [1, 2, 3],
"description": "Array of numbers"
}
}
Object Types
{
"objectProp": {
"type": "Object<string>",
"default": {},
"description": "Object with string values"
},
"numberObject": {
"type": "Object<number>",
"default": { "a": 1, "b": 2 },
"description": "Object with number values"
}
}
Script API Types
{
"colorProp": {
"type": "Color",
"default": "#336699",
"description": "Color value"
},
"selectionProp": {
"type": "Selection",
"default": {},
"description": "Selection object"
}
}
Note: For detailed information on Color and Selection types, including their JavaScript usage patterns and structure, see Script API Data Types in Advanced Topics.
Property Configuration
| Field | Type | Required | Description |
|---|---|---|---|
type |
string | Yes | Data type |
default |
varies | Yes | Default value matching type |
description |
string | No | Description for documentation |
Methods Object
Methods allow scripts to call functions on the widget.
Method Without Parameters
{
"refresh": {
"description": "Refresh the widget",
"body": "this._refresh();"
}
}
⚠️ Important: The
bodymust call an internal method (prefixed with_) to avoid infinite recursion. When SAC invokesWidget.refresh(), it executes the body code. If the body callsthis.refresh(), it would recursively call itself. Always usethis._refresh()pattern.
Method With Parameters
{
"setTitle": {
"description": "Set the widget title",
"parameters": [
{
"name": "newTitle",
"type": "string",
"description": "The new title text"
}
],
"body": "this._setTitle(newTitle);"
}
}
Method With Return Value
{
"getTotal": {
"description": "Get the total value",
"returnType": "number",
"body": "return this._getTotal();"
}
}
Method With Multiple Parameters
{
"configure": {
"description": "Configure the widget",
"parameters": [
{ "name": "width", "type": "integer", "description": "Width in pixels" },
{ "name": "height", "type": "integer", "description": "Height in pixels" },
{ "name": "title", "type": "string", "description": "Title text" }
],
"body": "this._configure(width, height, title);"
}
}
Method Configuration
| Field | Type | Required | Description |
|---|---|---|---|
description |
string | No | Method description |
parameters |
array | No | Array of parameter definitions |
returnType |
string | No | Return type (if method returns value) |
body |
string | Yes | JavaScript code to execute |
Events Object
Events allow the widget to notify scripts of user interactions or state changes.
Basic Event
{
"onSelect": {
"description": "Fired when an item is selected"
},
"onClick": {
"description": "Fired when widget is clicked"
},
"onDataChange": {
"description": "Fired when data changes"
}
}
Firing Events in Web Component
// Simple event
this.dispatchEvent(new Event("onSelect"));
// Event with data (accessible via getEventInfo in script)
this.dispatchEvent(new CustomEvent("onSelect", {
detail: {
selectedItem: "item1",
selectedIndex: 0
}
}));
Script Event Handler
In Analytics Designer script:
// Event handler
Widget_1.onSelect = function() {
console.log("Item selected");
// Access event data if provided
var eventInfo = Widget_1.getEventInfo();
};
DataBindings Object
Enable widgets to receive data from SAC models.
Basic Data Binding
{
"dataBindings": {
"myBinding": {
"feeds": [
{
"id": "dimensions",
"description": "Dimensions",
"type": "dimension"
},
{
"id": "measures",
"description": "Measures",
"type": "mainStructureMember"
}
]
}
}
}
Feed Types
| Type | Description | Use Case |
|---|---|---|
dimension |
Dimension members | Categories, labels, hierarchies |
mainStructureMember |
Measures/KPIs | Numeric values, calculations |
Feed Configuration
| Field | Type | Required | Description |
|---|---|---|---|
id |
string | Yes | Unique identifier for the feed |
description |
string | Yes | Display name in Builder Panel |
type |
string | Yes | "dimension" or "mainStructureMember" |
Multiple Feeds Example
{
"dataBindings": {
"chartData": {
"feeds": [
{ "id": "category", "description": "Category", "type": "dimension" },
{ "id": "series", "description": "Series", "type": "dimension" },
{ "id": "value", "description": "Value", "type": "mainStructureMember" },
{ "id": "target", "description": "Target", "type": "mainStructureMember" }
]
}
}
}
Accessing Data in JavaScript
// Access via property
const data = this.chartData.data;
const metadata = this.chartData.metadata;
// Iterate rows
this.chartData.data.forEach(row => {
const category = row.category_0.label;
const value = row.value_0.raw;
console.log(`${category}: ${value}`);
});
// Via getDataBinding method
const binding = this.dataBindings.getDataBinding("chartData");
Custom Types
Define reusable complex types for properties.
Defining Custom Type
{
"types": {
"ChartConfig": {
"properties": {
"chartType": { "type": "string", "default": "bar" },
"showLegend": { "type": "boolean", "default": true },
"colors": { "type": "string[]", "default": [] }
}
}
},
"properties": {
"chartConfiguration": {
"type": "ChartConfig",
"default": {
"chartType": "bar",
"showLegend": true,
"colors": ["#336699", "#669933"]
}
}
}
}
Validation Checklist
Before deploying, verify your JSON:
idfollows reverse domain notationversionis semantic version formatnameis concise and descriptive- All
webcomponentshave validtagnames (lowercase, hyphenated) - All URLs are HTTPS (for external hosting)
- All
propertieshavetypeanddefault - All
methodshavebody integrityis set for production (or explicitlyignoreIntegrity: truefor dev)dataBindingsfeeds have uniqueidvalues
Source Documentation:
Last Updated: 2025-11-22