Fix Fiori Elements Controller Extensions
This skill handles Fiori Elements V2 controller extensions during UI5 modernization. There are two cases with different actions:
- Case B (most common): Extensions registered via
controllerNamein manifest → Report only. Do NOT modify the controller files. Leave them as-is and inform the user which files need manual attention. - Case A (rare): Extensions using
registerControllerExtensions→ Perform the full modernization toControllerExtension.extend()+ manifest registration.
Linter Rules Handled
Quick Decision: Which Case Am I?
When to Use
Case B (most common) — Detected when the manifest already has a controllerName entry under a simple key, and the controller file uses either sap.ui.controller() or Controller.extend():
The source controller might look like either of these:
Linter output triggering Case B:
Action for Case B: Do NOT modify these files. Report them to the user and continue with the rest of the modernization.
Case A (rare, older apps only) — Apply when you see linter output like:
Or when an app has patterns like:
Fix Strategy
The action depends on how the extension is registered in the manifest. Determine which case applies before proceeding.
Case Detection
The key differentiator is the manifest registration format:
- Case B (most common):
controllerNamealready in manifest under a simple key (e.g.,"sap.suite.ui.generic.template.ListReport.view.ListReport": { "controllerName": "..." }). Do not modernize these files. Report them and move on. - Case A: No
controllerNamein manifest yet — extension is registered programmatically viaregisterControllerExtensions. The modernization adds a manifest entry with the#stableIdkey format AND usesControllerExtension.extend().
Detection commands:
Case B: Report and Skip (Most Common)
For extensions registered via controllerName in the manifest (simple key without #stableId), do NOT modify the controller files. These require careful manual modernization and are left to the developer.
Steps:
- Identify all controller files referenced by
controllerNameentries in manifest.json (under keys that do NOT contain#) - Report them to the user with this format:
- Do NOT (within this skill):
- Modify the controller .js files to change the controller extension pattern (no plain-object conversion)
- Change the manifest registration
- Add linter disable comments
- Attempt the plain-object modernization pattern
- Other skills CAN still process these files for unrelated fixes (e.g.,
fix-js-globalsreplacingsap.ui.getCore()calls within method bodies,fix-linter-blind-spotsfor namespace patterns). Only thesap.ui.controller()/Controller.extend()structure itself is left untouched. - Continue with the rest of the modernization (other skills, other linter findings)
Case A: Step 1 — Move Registration from JS to manifest.json
Only for Case A (extensions using registerControllerExtensions in JS).
Move controller extension registrations from JavaScript code to the manifest under sap.ui.controllerExtensions.
Key format: <FLOORPLAN_CONTROLLER>#<STABLE_ID_OF_VIEW>
Finding the correct key:
- The key has format:
<FloorplanController>#<StableViewId> - The floorplan controller name matches the view name (e.g.,
sap.suite.ui.generic.template.ListReport.view.ListReport) - The stable view ID is typically:
<AppId>::<FloorplanViewName>::<EntitySet> - Check the app's existing manifest for
sap.ui.generic.app/pagesconfiguration to find entity sets and page IDs
Case A: Step 2 — Restructure Controller Files
⚠️ This step only applies to Case A (extensions using
sap.ui.controller()factory). If the extension already usesController.extend()with manifestcontrollerNameregistration, use Case B below instead.
Convert controller files from sap.ui.controller style to ControllerExtension class.
Before:
After:
Key rules for restructuring:
- Extend
sap/ui/core/mvc/ControllerExtensioninstead of usingsap.ui.controller - Lifecycle methods (
onInit,onExit,onBeforeRendering,onAfterRendering) → insideoverride - Framework callback methods (
onBeforeRebindTable,onBeforeRebindChart,onListNavigationExtension,adaptNavigationParameterExtension, etc.) → insideoverride - Custom action methods (handlers for custom buttons/actions) → OUTSIDE
override - Access
extensionAPIviathis.extensionAPI(the framework injects it into the extension instance)
Case A: Step 3 — Update Handler References
In the manifest and XML annotations, update all event handler references from the old format to the new qualified format.
Before:
After:
Reference format: .extension.<full.controller.name>.<methodName>
Important: Use the dotted module name as declared in ControllerExtension.extend("my.app.ext.ListReportExtension", ...) and in the manifest's controllerName — not the slash-separated path used in sap.ui.define imports (e.g., "my/app/ext/ListReportExtension").
This applies to:
presshandlers in manifest action definitions- Custom column/section handler references
- Any event handler references that previously used just the method name
Implementation Steps
Case B Implementation (Report Only)
- Identify extension controllers registered via
controllerNamein manifest (simple key, no#) - Report them to the user — list each file path and note that they require manual modernization
- Do not modify these files, their manifest entries, or their handler references
- Continue with other modernization tasks
Case A Implementation (registerControllerExtensions → ControllerExtension)
- Identify all
registerControllerExtensionscalls in the codebase (typically in Component.js or helper files) - For each registration:
a. Determine the floorplan controller name and view stable ID
b. Determine the extension controller name/path
c. Add entry to
manifest.jsonundersap.ui5/extends/extensions/sap.ui.controllerExtensions - For each extension controller file:
a. Replace
sap.ui.controller(...)withsap.ui.define([ControllerExtension], ...)b. Move lifecycle/framework methods intooverridesection c. Keep custom methods outsideoverrided. UpdateextensionAPIaccess pattern - For all handler references:
a. Search manifest.json for action
presshandlers using simple method names b. Search XML annotation files for handler references c. Update to.extension.<module>.<method>format - Remove the
registerControllerExtensionscalls from Component.js - Verify by re-running the linter
Example Full Modernization
Before — Component.js:
After — Component.js:
After — manifest.json (additions):
After — ext/ListReportExtension.controller.js:
Notes
- This modernization only applies to Fiori Elements V2 template apps (using
sap.suite.ui.generic.template) - Fiori Elements V4 (using
sap.fe.templates) uses a different extension mechanism — this skill does not apply - Case B is far more common in practice — extensions registered via
controllerNamein the manifest. These are not auto-modernized — the agent reports them and moves on - Case A only appears in older apps that never modernized from
registerControllerExtensions - The stable view ID format varies by floorplan and configuration — check the running app's DOM or the floorplan documentation
- If the app uses
templateSpecific.jsonfor handler references, those must also be updated (Case A only) - After Case A modernization, the extension controller file should be placed under a path matching its module name
Related Skills
- fix-js-globals: For plain
sap.ui.controller()definitions in custom apps (Case 9), or if extension controllers also use global access patterns (sap.ui.getCore(),jQuery.sap.*). Other skills CAN still be applied to Case B controller files for issues unrelated to the controller extension pattern itself (e.g., replacing global API usage within method bodies). - fix-manifest-json: The manifest changes for controller extensions are additive — they don't conflict with version/routing updates from fix-manifest-json
- fix-linter-blind-spots: Can still fix namespace patterns and other blind spots within Case B controller files


