11 KiB
SAP SAC Custom Widget Integration and Migration
Coverage of script integration, content transport, story compatibility, and planning features.
Sources:
Table of Contents
- Script Integration
- Content Transport and Migration
- Story Compatibility
- Planning Integration
- API Methods Reference
Script Integration
Global Script Objects
Custom widgets can interact with SAC's global script objects.
Script Object Structure:
- Script objects act as containers for reusable functions
- Functions not tied to events, invoked directly
- Accessible from all scripts in the story
Invoking Script Functions:
// In SAC script
ScriptObjectName.ScriptFunctionName();
// Example
Utils.formatCurrency(1000, "USD"); // Returns "$1,000.00"
Script Variables
Global Variables:
- Defined at story level
- Accessible from all script blocks
- Can receive values from URL parameters
Using with Custom Widgets:
// In SAC script
var myValue = GlobalVariable_1;
CustomWidget_1.setValue(myValue);
// Widget method receives value
class MyWidget extends HTMLElement {
setValue(val) {
this._props.value = val;
this._render();
}
}
Script Object Integration Pattern
// Custom widget firing events for script handling
class MyWidget extends HTMLElement {
_handleUserAction(data) {
// Fire event that SAC script can handle
this.dispatchEvent(new CustomEvent("onUserAction", {
detail: { actionData: data }
}));
}
}
// In SAC script (event handler)
CustomWidget_1.onUserAction = function() {
var eventData = CustomWidget_1.getEventInfo();
// Process event, call other script objects
DataProcessor.handleAction(eventData.actionData);
};
Content Transport and Migration
Transport Methods
1. Content Network (Same Region)
- Source and destination on same region
- Same or +1 quarterly version
- Access: Main Menu > Transport > Export/Import > Content Network Storage
2. Import/Export (Any Region)
- No region restriction
- Version constraints apply
- More flexible but manual
Custom Widget Transport
Supported Scenarios:
- Cloud Foundry to Cloud Foundry tenants
- Same hosting configuration required
Not Supported:
- Cloud Foundry to Neo platform
- Different hosting configurations may cause issues
Common Transport Issue
Error: "The system couldn't load the custom widget"
Causes:
- Widget JSON transported but resource files not accessible
- Different hosting URLs between source/target
- Integrity hash mismatch after transport
Solution:
// Ensure resource URLs are accessible from target tenant
{
"webcomponents": [
{
"kind": "main",
"tag": "my-widget",
"url": "[https://globally-accessible-host.com/widget.js",](https://globally-accessible-host.com/widget.js",)
"integrity": "sha256-...",
"ignoreIntegrity": false
}
]
}
Transport Best Practices
- Use globally accessible hosting (GitHub Pages, CDN, SAC-hosted)
- Verify URLs before transport - Ensure target can reach resource files
- Re-upload JSON if hosting changes - Update URLs post-transport
- Test in target before production use
CTMS Integration
Cloud Transport Management Service (CTMS) provides automated transport:
- Integrate CTMS with SAC
- Define transport routes
- Upload packages via SAC interface
- CTMS handles deployment to destination
Limitation: CTMS is basic - no destination location selection like native Content Network.
Story Compatibility
Story Types
| Type | Custom Widgets | Scripting | CSS/Themes |
|---|---|---|---|
| Classic Story | Limited | No | Limited |
| Optimized Story (Classic Responsive) | Yes | Limited | Limited |
| Optimized Story (Advanced Responsive) | Full | Full | Full |
Optimized Story Experience (QRC Q2 2023+)
Advanced Responsive Layout features:
- Full custom widget support
- Complete scripting capabilities
- CSS and theme customization
- Device preview
- Data binding
Classic Story Conversion
Conversion Status Types:
- Ready to convert - No issues, direct conversion
- Feature limitation - Some features not supported in optimized
- Blocked - Issues must be resolved first
Conversion Notes:
- Conversion is permanent
- Save as copy recommended
- Converted stories use Classic Responsive Layout initially
Custom Widget Compatibility
In Optimized Stories:
{
"id": "com.company.widget",
"dataBindings": {
"myData": {
"feeds": [...]
}
}
}
- Full data binding support
- Script integration
- Builder/Styling panels
In Classic Stories:
- Limited support
- No data binding
- Basic property configuration only
Planning Integration
⚠️ Important Limitations
Before implementing planning widgets, review these constraints:
- Builder Panel + Data Binding Conflict: Cannot combine custom Builder Panel with data binding in the same widget
- Hierarchies Not Supported: Data binding works with flat data only; select "flat" representation in SAC
See details in Data Binding Limitations below.
Custom Widgets for Planning
Custom widgets can support SAP Analytics Cloud Planning scenarios:
Use Cases:
- Custom input controls
- Specialized data entry forms
- Planning workflow visualization
- Custom approval interfaces
Data Binding Limitations
Known Limitations:
-
Builder Panel + Data Binding Conflict:
- Cannot combine custom Builder Panel with data binding
- Builder Panel overrides data binding functionality
- Choose one approach per widget
-
Hierarchies Not Supported:
- Data binding works with flat data only
- Select "flat" representation in SAC properties
- Hierarchical dimensions require alternative approach
Planning API Integration
Available through Script:
// In SAC script
var ds = Table_1.getDataSource();
// Planning operations (via DataSource)
ds.setUserInput(selection, value); // Write data
ds.submitData(); // Commit changes
ds.revertData(); // Rollback
Custom Widget Access:
// Widget receives DataSource via method
class PlanningWidget extends HTMLElement {
async setDataSource(dataSource) {
this._ds = dataSource;
// Can now call dataSource methods
}
}
Input Control Pattern
class CustomInputWidget extends HTMLElement {
constructor() {
super();
this._setupInputHandlers();
}
_setupInputHandlers() {
this._shadowRoot.getElementById("input").addEventListener("change", (e) => {
// Fire event with new value
this.dispatchEvent(new CustomEvent("onValueChange", {
detail: { newValue: e.target.value }
}));
});
}
}
// SAC script handles the planning write-back
CustomInputWidget_1.onValueChange = function() {
var info = CustomInputWidget_1.getEventInfo();
var selection = { "Account": "Forecast", "Time": "2024.Q1" };
Table_1.getDataSource().setUserInput(selection, info.newValue);
};
API Methods Reference
DataSource Methods (via Script)
| Method | Description | Parameters |
|---|---|---|
getData(selection) |
Get data cell value | Selection object |
getResultSet() |
Get current result set | None |
getMembers(dimension) |
Get dimension members | Dimension name |
getResultMember(dim, selection) |
Get member info | Dimension, Selection |
getDimensionFilters(dimension) |
Get filter values | Dimension name |
setDimensionFilter(dim, member) |
Set filter | Dimension, MemberInfo |
removeDimensionFilter(dimension) |
Clear filter | Dimension name |
Variable Methods
| Method | Description | Parameters |
|---|---|---|
setVariableValue(name, value) |
Set variable | Variable name, value |
getVariableValues() |
Get all variables | None |
Performance Tip: Group setVariableValue() calls together for automatic request merging.
Custom Widget Data Binding Methods
// Access data binding
const binding = this.dataBindings.getDataBinding("myBinding");
// Get result set (async)
const resultSet = await binding.getResultSet();
// Direct property access
const data = this.myBinding.data;
const metadata = this.myBinding.metadata;
Event Info Pattern
// In custom widget
this.dispatchEvent(new CustomEvent("onSelect", {
detail: {
selectedId: "item-123",
selectedValue: 100
}
}));
// In SAC script
Widget_1.onSelect = function() {
var info = Widget_1.getEventInfo();
// info.selectedId = "item-123"
// info.selectedValue = 100
};
Migration Checklist
Before Transport
- Verify resource file hosting is globally accessible
- Update URLs if changing hosting strategy
- Regenerate integrity hashes if files changed
- Test widget in source tenant
- Document any script dependencies
After Transport
- Verify widget loads in target tenant
- Test all functionality
- Check script object references still work
- Verify data binding if applicable
- Test in view mode (not just edit mode)
Troubleshooting
| Symptom | Likely Cause | Solution |
|---|---|---|
| Widget won't load | URL not accessible | Verify hosting, CORS |
| Integrity warning | Hash mismatch | Regenerate hash |
| Script errors | Missing script objects | Recreate in target |
| No data | Data binding lost | Reconfigure binding |
| Styling broken | CSS not loaded | Check styling panel config |
Resources
- Analytics Designer API Reference
- Custom Widget Developer Guide
- SAC Content Transport
- Optimized Story Experience
Last Updated: 2025-11-22