Help us improve
Share bugs, ideas, or general feedback.
SAP Analytics Cloud (SAC) Custom Widget development. Use when building custom visualizations, extending SAC with Web Components, or creating Widget Add-Ons. Covers JSON metadata, JavaScript Web Components, lifecycle functions, data binding with feeds, styling/builder panels, property/event/method definitions, third-party library integration, hosting, security, performance, and debugging. Includes Widget Add-On feature (QRC Q4 2023+) and templates for widgets, charts, and KPI cards.
npx claudepluginhub andreafusar/https-github.com-secondsky-sap-skills --plugin sap-sac-custom-widgetHow this skill is triggered — by the user, by Claude, or both
Slash command
/sap-sac-custom-widget:sap-sac-custom-widgetThis skill is limited to the following tools:
The summary Claude sees in its skill listing — used to decide when to auto-load this skill
- [Overview](#overview)
README.mdreferences/advanced-topics.mdreferences/best-practices-guide.mdreferences/echarts-integration.mdreferences/integration-and-migration.mdreferences/json-schema-reference.mdreferences/script-api-reference.mdreferences/widget-addon-guide.mdreferences/widget-templates.mdtemplates/basic-widget.jstemplates/data-bound-chart.jstemplates/styling-panel.jstemplates/widget.json-completetemplates/widget.json-minimalGenerates Angular code and provides architectural guidance for projects, components, services, signals, forms, DI, routing, SSR, accessibility, animations, styling, testing, and CLI tooling.
Share bugs, ideas, or general feedback.
This skill enables development of custom widgets for SAP Analytics Cloud (SAC). Custom widgets are Web Components that extend SAC stories and applications with custom visualizations, interactive elements, and specialized functionality.
Use this skill when:
Requirements:
This plugin provides specialized agents, commands, and validation hooks for comprehensive widget development support.
| Agent | Color | Purpose | Trigger Examples |
|---|---|---|---|
| widget-architect | Blue | Design widget structure, metadata, and integration patterns | "design custom widget", "plan widget architecture" |
| widget-debugger | Yellow | Troubleshoot loading, data binding, CORS, and runtime issues | "widget won't load", "CORS error", "data not binding" |
| widget-api-assistant | Green | Write JavaScript widget code, lifecycle functions, API integrations | "write widget code", "implement lifecycle functions" |
| Command | Usage | Description |
|---|---|---|
/widget-validate | /widget-validate [file] | Validate widget.json schema and widget.js structure |
/widget-generate | /widget-generate | Interactively generate widget scaffold with JSON + JS |
/widget-lint | /widget-lint [file] | Performance, security, and best practices analysis |
Automatic quality checks triggered on Write/Edit operations:
Ready-to-use scaffolds in templates/ directory:
basic-widget.js - Minimal Web Component with all lifecycle functionsdata-bound-chart.js - ECharts widget with data bindingstyling-panel.js - Runtime customization panelwidget.json-minimal - Bare-minimum metadatawidget.json-complete - Full-featured metadata with all optionsA custom widget requires two files:
1. widget.json (Metadata)
{
"id": "com.company.mywidget",
"version": "1.0.0",
"name": "My Custom Widget",
"description": "A simple custom widget",
"vendor": "Company Name",
"license": "MIT",
"icon": "",
"webcomponents": [
{
"kind": "main",
"tag": "my-custom-widget",
"url": "[https://your-host.com/widget.js",](https://your-host.com/widget.js",)
"integrity": "",
"ignoreIntegrity": true
}
],
"properties": {
"title": {
"type": "string",
"default": "My Widget"
}
},
"methods": {},
"events": {}
}
2. widget.js (Web Component)
(function() {
const template = document.createElement("template");
template.innerHTML = `
<style>
:host {
display: block;
width: 100%;
height: 100%;
}
.container {
padding: 16px;
font-family: Arial, sans-serif;
}
</style>
<div class="container">
<h3 id="title">My Widget</h3>
<div id="content"></div>
</div>
`;
class MyCustomWidget extends HTMLElement {
constructor() {
super();
this._shadowRoot = this.attachShadow({ mode: "open" });
this._shadowRoot.appendChild(template.content.cloneNode(true));
this._props = {};
}
connectedCallback() {
// Called when element is added to DOM
}
onCustomWidgetBeforeUpdate(changedProperties) {
// Called BEFORE properties are updated
this._props = { ...this._props, ...changedProperties };
}
onCustomWidgetAfterUpdate(changedProperties) {
// Called AFTER properties are updated - render here
if (changedProperties.title !== undefined) {
this._shadowRoot.getElementById("title").textContent = changedProperties.title;
}
}
onCustomWidgetResize() {
// Called when widget is resized
}
onCustomWidgetDestroy() {
// Cleanup when widget is removed
}
// Property getter/setter (required for SAC framework)
get title() {
return this._props.title;
}
set title(value) {
this._props.title = value;
this.dispatchEvent(new CustomEvent("propertiesChanged", {
detail: { properties: { title: value } }
}));
}
}
customElements.define("my-custom-widget", MyCustomWidget);
})();
⚠️ Production Note: The ignoreIntegrity: true setting above is development only. For production deployments, generate a SHA256 integrity hash and set ignoreIntegrity: false.
SAP provides 15+ ready-to-use custom widget samples:
Repository: SAP-samples/SAC_Custom_Widgets
| Category | Widgets |
|---|---|
| Charts | Funnel, Pareto, Sankey, Sunburst, Tree, Line, UI5 Gantt |
| KPI/Gauge | KPI Ring, Gauge Grade, Half Donut, Nested Pie, Custom Pie |
| Utilities | File Upload, Word Cloud, Bar Gradient, Widget Add-on Sample |
Requirements: Optimized View Mode (OVM) enabled, data binding support
Note: Check third-party library licenses before production use.
Essential functions called by SAC framework:
onCustomWidgetBeforeUpdate(changedProperties) - Pre-update hookonCustomWidgetAfterUpdate(changedProperties) - Post-update (render here)onCustomWidgetResize() - Handle resize eventsonCustomWidgetDestroy() - Cleanup resourcesConfigure in widget.json to receive SAC model data:
{
"dataBindings": {
"myDataBinding": {
"feeds": [
{
"id": "dimensions",
"description": "Dimensions",
"type": "dimension"
},
{
"id": "measures",
"description": "Measures",
"type": "mainStructureMember"
}
]
}
}
}
Access data in JavaScript:
// Get data binding
const dataBinding = this.dataBindings.getDataBinding("myDataBinding");
// Access result set
const data = this.myDataBinding.data;
const metadata = this.myDataBinding.metadata;
// Iterate over rows
this.myDataBinding.data.forEach(row => {
const dimensionValue = row.dimensions_0.label;
const measureValue = row.measures_0.raw;
});
1. SAC-Hosted (Recommended, QRC Q2 2023+)
"/path/to/widget.js""integrity": "" and "ignoreIntegrity": true2. GitHub Pages
[https://username.github.io/repo/widget.js](https://username.github.io/repo/widget.js`)3. External Web Server
Access-Control-Allow-Origin: *For production, generate SHA256 hash:
# Generate hash
openssl dgst -sha256 -binary widget.js | openssl base64 -A
# Update JSON
"integrity": "sha256-abc123...",
"ignoreIntegrity": false
| Error | Cause | Solution |
|---|---|---|
| "The system couldn't load the custom widget" | Incorrect URL or hosting issue | Verify URL is accessible, check CORS |
| "Integrity check failed" | Hash mismatch | Regenerate hash after JS changes |
| Widget not appearing | Missing connectedCallback render | Call render in onCustomWidgetAfterUpdate |
| Properties not updating | Missing propertiesChanged dispatch | Use dispatchEvent with propertiesChanged |
| Data not displaying | Data binding misconfigured | Verify feeds in JSON match usage |
onCustomWidgetAfterUpdate(changedProperties) {
console.log("Widget updated:", changedProperties);
console.log("Current props:", this._props);
console.log("Data binding:", this.myDataBinding?.data);
this._render();
}
Widget Add-Ons extend built-in SAC widgets without building from scratch.
Use Cases:
Supported Charts: Bar/Column, Stacked Bar/Column, Line, Stacked Area, Numeric Point
Key Differences:
main and builder components (no styling)tooltip, plotArea, numericPoint)See references/widget-addon-guide.md for complete implementation.
templates/basic-widget.js - Minimal Web Component scaffold (~60 lines)templates/data-bound-chart.js - ECharts widget with SAC data binding (~120 lines)templates/styling-panel.js - Styling panel for runtime customization (~150 lines)templates/widget.json-minimal - Bare-minimum metadata (~25 lines)templates/widget.json-complete - Full-featured metadata (~100 lines)references/json-schema-reference.md - Complete JSON schema documentationreferences/widget-templates.md - Additional widget template patterns (6 templates)references/echarts-integration.md - ECharts library integration guidereferences/widget-addon-guide.md - Widget Add-On development (QRC Q4 2023+)references/best-practices-guide.md - Performance, security, and development guidelinesreferences/advanced-topics.md - Custom types, script API types, installationreferences/integration-and-migration.md - Script integration, content transportreferences/script-api-reference.md - DataSource, Selection, MemberInfo APIsPrimary References (for skill updates):
Sample Widgets:
v2.0.0 (2025-12-27)
v1.2.0 (2025-11-26)
v1.1.0 (2025-11-22)
v1.0.0 (2025-11-22)
Last Verified: 2025-12-27 | SAC Version: 2025.21 | Skill Version: 2.0.0