**TITLE**: Controlling the Editability of Child-Entity Sections with UpdateRestrictions

**INTRODUCTION**: This guide shows how to control editability of fields that originate from child entities in SAP Fiori elements (OData V4) using the Capabilities.UpdateRestrictions annotation. It includes XML and CAP CDS examples, explains interaction with NavigationRestrictions and the main entity set, and recommends path-based rules for draft scenarios.

**TAGS**: fiori-elements-framework, OData V4, UpdateRestrictions, NavigationRestrictions, annotations, CAP, XML, editability, draft

**STEP**: Apply UpdateRestrictions to a child entity (XML)
**DESCRIPTION**: Add a local XML annotation to set UpdateRestrictions.Updatable for the target child entity. This makes all fields coming from that entity editable or non-editable as a group. Use this only for child entity sets; UpdateRestrictions on the main entity set is ignored.
**LANGUAGE**: XML
**CODE**:
```xml
<Annotations Target="com.c_salesordermanage_sd.MaterialCategory">
     <Annotation Term="Capabilities.UpdateRestrictions">
          <Record Type="Capabilities.UpdateRestrictionsType">
               <PropertyValue Property="Updatable" Bool="true"/>
          </Record>
     </Annotation>
</Annotations>
```

**STEP**: Apply UpdateRestrictions to a child entity (CAP CDS)
**DESCRIPTION**: CAP CDS equivalent to the XML annotation above. Add this to your .cds file for the target entity.
**LANGUAGE**: CAP CDS
**CODE**:
```
annotate c_salesordermanage_sd.MaterialCategory with @Capabilities : {
UpdateRestrictions : {Updatable : true}
};
```

**STEP**: ABAP CDS availability note
**DESCRIPTION**: No ABAP CDS sample is provided for this topic. Use the local XML annotation instead.
**LANGUAGE**: text
**CODE**:
```
No ABAP CDS annotation sample is available. Please use the local XML annotation.
```

**STEP**: Rules that determine field editability in object and subobject pages
**DESCRIPTION**:
- UpdateRestrictions is ignored for the main entity set.
- Fields that originate from other entity sets can be editable in tables and forms on object and subobject pages only if:
  - The list report entity set is updatable, AND
  - The UI is in an edit state, AND
  - The property field control allows editing.
- If the child entity cannot be updated (UpdateRestrictions.Updatable evaluates to false), the fields coming from that entity cannot be edited regardless of UI state or field control.
- NavigationRestrictions on the parent entity set have priority. If the parent entity set has a NavigationRestrictions entry with RestrictedProperties specifying a NavigationProperty whose UpdateRestrictions.Updatable = false, the child entity records cannot be edited. If NavigationRestrictions.Updatable = true or contains a path, then the child's UpdateRestrictions determines editability.
- See also: Further Features of the Field for field-level control logic.

**STEP**: Example - NavigationRestrictions in XML
**DESCRIPTION**: Use this XML to restrict update capability of a specific navigation property from the parent entity set. This example makes the navigation property _MaterialDetails non-updatable via the parent.
**LANGUAGE**: XML
**CODE**:
```xml
<Annotation Term="Capabilities.NavigationRestrictions">
     <Record Type="Capabilities.NavigationRestrictionsType">
          <PropertyValue Property="RestrictedProperties">
               <Collection>
                    <Record Type="Capabilities.NavigationPropertyRestriction">
                         <PropertyValue Property="NavigationProperty" NavigationPropertyPath="_MaterialDetails"/>
                         <PropertyValue Property="UpdateRestrictions">
                              <Record Type="Capabilities.UpdateRestrictionsType">
                                   <PropertyValue Property="Updatable" Bool="false"/>
                              </Record>
                         </PropertyValue>
                    </Record>
               </Collection>
          </PropertyValue>
     </Record>
</Annotation>
```

**STEP**: Example - NavigationRestrictions in CAP CDS
**DESCRIPTION**: CAP CDS equivalent to the XML NavigationRestrictions above. Add to the parent entity definition.
**LANGUAGE**: CAP CDS
**CODE**:
```
entity SalesOrderItem                                     @(
Capabilities : {
NavigationRestrictions : {RestrictedProperties : [{
NavigationProperty : _MaterialDetails,
UpdateRestrictions     : {Updatable : false}
}]}
});
```

**STEP**: Use a path expression for UpdateRestrictions.Updatable (XML)
**DESCRIPTION**: Instead of a static boolean, use a path so the Updatable flag can evaluate per-record (recommended for draft scenarios). Add this XML to the child entity's annotations pointing to a boolean property (e.g., isUpdatable).
**LANGUAGE**: XML
**CODE**:
```xml
<Annotations Target="com.c_salesordermanage_sd_aggregate.MaterialDetails">
     <Annotation Term="Capabilities.UpdateRestrictions">
          <Record Type="Capabilities.UpdateRestrictionsType">
               <PropertyValue Property="Updatable" Path="isUpdatable"/>
          </Record>
     </Annotation>
</Annotations>
```

**STEP**: Use a path expression for UpdateRestrictions.Updatable (CAP CDS)
**DESCRIPTION**: CAP CDS equivalent: annotate the entity and reference a property name as a path to control per-record editability (isUpdatable).
**LANGUAGE**: CAP CDS
**CODE**:
```
annotate MaterialDetails with @(
    Capabilities.UpdateRestrictions : {
        Updatable : isUpdatable
    }
);
```

**STEP**: Draft behavior and best practice
**DESCRIPTION**:
- Static Updatable=false is applied for both draft and active records. If you set Updatable to a static false, draft copies (not yet activated) will also be non-editable, preventing edits on newly created drafts.
- Best practice: use a path-based Updatable expression that returns true for newly created draft records and false after activation. This allows creating and editing drafts, while preventing edits post-activation.
- Visual examples in the application: images/UpdateRestrictions1_9616035.png and images/UpdateRestrictions2_b3a0021.png demonstrate fields that remain in display mode when their entity's UpdateRestrictions.Updatable evaluates to false.

fiori-elements-framework
OData V4
UpdateRestrictions
NavigationRestrictions
annotations
CAP
XML
editability
draft


**TITLE**: Copy and Paste from External Applications into Editable Fiori Elements Tables

**INTRODUCTION**: This document explains how end users can copy data from external applications (for example, spreadsheets) into editable SAP Fiori elements tables and how application developers can control this behaviour. It covers table-level vs cell-level paste, supported table types, limitations, OData V2 and V4 specifics, data preparation recommendations, and the configuration option to disable paste.

**TAGS**: fiori-elements, paste, copy, table, smart-table, grid-table, responsive-table, odata-v2, odata-v4, inline-creation, enablePaste

STEP: 1 — Paste Modes and When They Apply

DESCRIPTION:
- Two paste modes:
  - Table-level paste: creates new rows from clipboard data. Trigger via browser paste (Ctrl/Cmd+V) or Paste icon in table toolbar. Requirements:
    - Application must be draft-enabled.
    - Table creation mode must be "inline" or "creationRows".
    - New rows are created only in these cases.
  - Cell-level paste: pastes into selected single cell or a group of cells. Replaces values of active/draft rows and can create new rows if an empty row is part of the selection.
    - Supported only for GridTable and ResponsiveTable.
- UI notes:
  - Copy button appears by default in table toolbar.
  - Paste icon shows only if the table supports paste.

LANGUAGE: text

CODE:
```text
Table-level paste: draft-enabled apps + creationMode inline|creationRows
Cell-level paste: supported table types = GridTable, ResponsiveTable
```

STEP: 2 — Data Preparation for Pasting

DESCRIPTION:
- Recommended: export table to spreadsheet using "split cells" mode to get the exact format expected for paste. Maintain placeholders for inline-action columns when required.
- When copying from spreadsheets, omit columns that contain inline actions (these are ignored by paste) and be aware read-only columns are ignored during paste (but will be present in exported spreadsheet format).
- Image assets referenced (for examples and format):
  - images/Copying_Data_from_a_Table_3e5d9c8.png
  - images/Excel_copy_paste_5_db3d9d3.png
  - images/Excel_copy_paste_6_fa98abc.png
  - images/Pasting_in_Excel_with_Inline_Actions_8173bd4.png
  - images/Sample_Data_for_Pasting_in_Exccel_with_Inline_Action_b4c1a5d.png

LANGUAGE: text

CODE:
```text
Export table with split-cells -> edit spreadsheet to match exported columns (omit inline-action columns for paste)
```

STEP: 3 — Supported Fields, Restrictions and Error Handling

DESCRIPTION:
- Supported: simple data fields (primitive values).
- Not supported: complex fields (links, images, connected fields, multi-input fields, field groups) and properties annotated with textArrangement = TextOnly (cannot be pasted).
- If a cell contains both ID and text, the ID property is updated on paste; the text description updates only after saving.
- Cannot paste into cells that contain a navigation property.
- Read-only columns: ignored by paste; still exported in spreadsheet format.
- If validation errors occur during paste, frontend shows an error dialog and the user must correct input.
- If new rows are created during paste, they are sent in a single POST batch call. POST duration grows with number of rows. Order of pasted rows may differ from the spreadsheet order — this is not controlled by Fiori elements.
- Feature is not supported in custom tables.

LANGUAGE: text

CODE:
```text
Supported: primitive/simple fields
Not supported: links, images, connected fields, multi-input, field groups, navigation properties
Validation: front-end checks data types; back-end must enforce editability and fixed-value lists
```

STEP: 4 — Behavior Specific to OData V2

DESCRIPTION:
- Smart table paste is available when the smart table contains inline actions.
- Columns containing inline actions are ignored by the paste operation — omit them from the source spreadsheet.
- Read-only columns are ignored during paste but are included in spreadsheet exports and must be present when preparing pasted data.

LANGUAGE: text

CODE:
```text
OData V2: Inline action columns ignored for paste -> omit these columns when copying from spreadsheet
```

STEP: 5 — Behavior Specific to OData V4

DESCRIPTION:
- Paste is enabled by default on the object page if creationMode is set to inline or empty row.
- End users must preserve placeholders for inline action columns in the spreadsheet (these columns may be empty).
- Front-end verifies pasted values match the field's data type but does not check field editability or fixed-value lists — back-end validation is required.
- Properties with textArrangement = TextOnly cannot be pasted.

LANGUAGE: text

CODE:
```text
OData V4: paste enabled by default for object page when creationMode = inline|emptyRow
Front-end: type validation only. Back-end must enforce editability and business validations.
```

STEP: 6 — Disable Paste via Configuration (enablePaste)

DESCRIPTION:
- Application developers can disable paste by setting enablePaste to false in the tableSettings configuration of the component options.

LANGUAGE: JSON

CODE:
```json
                "SalesOrderManageObjectPageEnableExport": {
                    "type": "Component",
                    "id": "SalesOrderManageObjectPage",
                    "name": "sap.fe.templates.ObjectPage",
                    "options": {
                        "settings": {
                            "controlConfiguration": {
                                _Item/@com.sap.vocabularies.UI.v1.LineItem: {
                                    "tableSettings": {
                                        "type": "GridTable",
                                        "enablePaste": false,
                                        "condensedTableLayout": true,
                                        "personalization": {
                                            "column": true,
                                            "sort": false
                                        },
                                        "creationMode": {
                                            "name": "Inline"
                                        }
                                    }
                                }
                            }

```

STEP: 7 — Copying Multiple Rows and Range Selections

DESCRIPTION:
- End users can copy multiple rows and ranges of rows/columns to the clipboard and paste them according to the rules above.
- For more details about multi-row and range selection copy, see:
  - tables-c0f6592.md#loioc0f6592a592e47f9bb6d09900de47412__section_pth_3mb_dzb

LANGUAGE: text

CODE:
```text
Supports copying multiple rows and ranges; paste behaviour follows table-level or cell-level rules as applicable.
```

fiori-elements paste copy table smart-table grid-table responsive-table odata-v2 odata-v4 inline-creation enablePaste


**TITLE**: Configure Create Mode as External App (Fiori Elements OData V4)

**INTRODUCTION**: Enable the Create button in a Fiori Elements list/table to launch an external SAP Fiori launchpad app. This config uses manifest.json: set creationMode to "External" with an outbound key and define the corresponding outbound entry (semanticObject, action, optional parameters) under sap.app.crossNavigation.outbounds. Applicable only for SAP Fiori elements with OData V4.

**TAGS**: fiori-elements, odata-v4, manifest.json, navigation, create-mode, external-app, sap.fiori, crossNavigation, outbounds

**STEP**: 1 — Applicability
**DESCRIPTION**: Confirm this configuration is only valid for SAP Fiori elements for OData V4.
**LANGUAGE**: JSON
**CODE**:
```json
// Note: This configuration applies only to SAP Fiori elements for OData V4.
// For OData V2, see Handling of the preferredMode Parameter documentation.
```

**STEP**: 2 — Enable Create button to open external app
**DESCRIPTION**: In manifest.json, set the table's creationMode to External and specify an outbound key (here "MyExternalApp"). This instructs the Create button to navigate via the specified outbound target.
**LANGUAGE**: JSON
**CODE**:
```json
"controlConfiguration": {
    "/@com.sap.vocabularies.UI.v1.LineItem": {
        "tableSettings": {
            "creationMode": {
                "name": "External",
                "outbound": "MyExternalApp"
            }
        }
    }
}
```

**STEP**: 3 — Define outbound target and parameters
**DESCRIPTION**: In manifest.json, add the outbound under sap.app.crossNavigation.outbounds. The outbound must contain semanticObject and action (mandatory). The source app's context is passed automatically on navigation. Define additional parameters here to be delivered to the target app. Use "format": "plain" and "value" for static values; dynamic expressions can be used as needed.
**LANGUAGE**: JSON
**CODE**:
```json
"sap.app": {
    "id": "DraftsManage",
    "type": "application",
    ...
    "crossNavigation": {
        "outbounds": {
            "MyExternalApp": {
                "semanticObject": "mySemanticObject",
                "action": "myAction",
                "parameters": {
                    "MyParam": {
                        "value": {
                            "value": "myValue",
                            "format": "plain"
                        }
                    }
                }
            }
        }
    }
}
```

fiori-elements odata-v4 manifest.json navigation create-mode external-app sap.fiori crossNavigation outbounds


**TITLE**: Create Mode Options for Object Page (SAP Fiori elements)

**INTRODUCTION**: This document lists the available create-mode options for tables on the Object Page in SAP Fiori elements, explains when each mode is used, and points to the relevant implementation references. Use these modes to configure how users create new business objects from an object page table.

**TAGS**: fiori-elements-framework, object-page, create-mode, inline-creation, dialog, external, OData-v4

**STEP**: 1 — Overview of Create Modes

**DESCRIPTION**: Summary of available create modes and their high-level behavior. Use these identifiers when configuring table/create behavior or when searching implementation references.

**LANGUAGE**: text

**CODE**:
```text
Available create modes:
- `Inline`
- `InlineCreationRows`
- Create page (default when navigation from the table is available)
- Create dialog (dialog-based object creation; OData V4 only on the Object Page)
- `External` (navigates to an external Fiori launchpad app)
```

**STEP**: 2 — Inline and InlineCreationRows

**DESCRIPTION**: Use these modes to let users create new business objects directly within the table rows on the Object Page without navigation. Refer to the detailed guide to enable inline creation or empty-row creation for table entries.

- Use when you want seamless row-based creation.
- No navigation away from the Object Page is performed.

**LANGUAGE**: text

**CODE**:
```text
Modes: `Inline`, `InlineCreationRows`
Reference: Enabling Inline Creation Mode or Empty Row Mode for Table Entries
File: enabling-inline-creation-mode-or-empty-row-mode-for-table-entries-cfb04f0.md
```

**STEP**: 3 — Create Page (Default when navigation is available)

**DESCRIPTION**: Configure the application to navigate to a dedicated object page for creation when navigation from the table is available. This is the default create mode in scenarios where row navigation is supported and preferred.

- Use when comprehensive creation UI and navigation are needed.
- Default behavior when table row navigation exists.

**LANGUAGE**: text

**CODE**:
```text
Mode: Create page
Behavior: Application navigates to an object page where the user can enter values and create a new object.
Default: Used when navigation from the table is available.
```

**STEP**: 4 — Create Dialog (Object Page only supported for OData V4)

**DESCRIPTION**: Use a dialog to capture creation inputs without leaving the current page. Note: On the Object Page, create dialog support is available only for SAP Fiori elements with OData V4. Refer to the implementation guide for enabling dialog-based creation.

**LANGUAGE**: text

**CODE**:
```text
Mode: Create dialog
Behavior: A dialog opens where the user can enter values and trigger object creation.
Important: On the Object Page, the create dialog is only supported by SAP Fiori elements for OData V4.
Reference: Enabling Object Creation Using the Dialog on the Object Page
File: enabling-object-creation-using-the-dialog-on-the-object-page-7fee938.md
```

**STEP**: 5 — External Create Mode

**DESCRIPTION**: Use the External mode when creation is handled by a separate SAP Fiori launchpad-based application. Clicking Create triggers navigation to the external app that manages object creation.

**LANGUAGE**: text

**CODE**:
```text
Mode: `External`
Behavior: Clicking the Create button navigates to an external Fiori launchpad app for object creation.
Reference: Create Mode as an External App
File: create-mode-as-an-external-app-5c2bc2e.md
```

fiori-elements-framework object-page create-mode inline-creation dialog external OData-v4


**TITLE**: Create a propertyBindingChange for SAP Fiori elements (OData V2)

**INTRODUCTION**: This document explains how to create a property binding change (propertyBindingChange) for SAP Fiori elements (OData V2). Use it when you want a control property (for example visibility) to be data-bound or expression-bound rather than having a static newValue. This is intended for code generation or automated edits of change files produced by the Page Editor.

**TAGS**: fiori-elements-framework, SAPUI5, ui5, change-management, propertyBindingChange, ODataV2, PageEditor

**STEP**: 1 — Preconditions and applicability

**DESCRIPTION**: Ensure this procedure is applicable and model data is already retrieved by the model. This procedure applies only to SAP Fiori elements for OData V2 and is relevant for these UI adaptation use cases: object page — show header content in edit mode; show content parts in the header according to a mode; control visibility of a section.

**LANGUAGE**: text

**CODE**:
```text
Preconditions:
- SAP Fiori elements for OData V2 only.
- The property you bind must have its data available in the model.
- If binding to an OData property, the property must belong to the same node or the root node.
```

**STEP**: 2 — Open the Page Editor and identify the target property

**DESCRIPTION**: Open the Page Editor for the target application/page. Locate the control property you want to change (for example the "visible" property of an ObjectPage section). In the property panel you may either select a binding from the drop-down or compose an expression.

**LANGUAGE**: text

**CODE**:
```text
Action:
- Open your app in Web IDE or Business Application Studio.
- Open the app's Page Editor for the target page.
- Select the control and its property (e.g., visible).
- Choose or enter an expression/binding, e.g. {myProperty} or {= !${ui>/editable}}
```

**STEP**: 3 — Convert an existing propertyChange file to propertyBindingChange

**DESCRIPTION**: If you already have a change file of type propertyChange, modify it programmatically or manually:
- Change "changeType" from "propertyChange" to "propertyBindingChange".
- In "content", remove or replace "newValue" with "newBinding" and set its value to the desired binding string (for example "{myProperty}" or an expression).
- Keep other metadata (reference, selector, namespace, etc.) intact.

Include the original propertyChange file and the resulting propertyBindingChange file examples below. Use these as templates for automated edits or generation.

**LANGUAGE**: json

**CODE**:
```json
{
    "fileName": "id_1460988346969_256_propertyChange",
    "fileType": "change",
    "changeType": "propertyChange",
    "reference": "STTA_MP.Component",
    "packageName": "$TMP",
    "content": {
        "property": "visible",
        "oldValue": true,
        "newValue": false
    },
    "selector": {        "id": "STTA_MP::sap.suite.ui.generic.template.ObjectPage.view.Details::STTA_C_MP_Product--action::STTA_PROD_MAN.STTA_PROD_MAN_Entities::STTA_C_MP_ProductCopywithparams",
        "type": "sap.uxap.ObjectPageHeaderActionButton"
    },
    "layer": "CUSTOMER_BASE",
    "texts": {},
    "namespace": "apps/STTA_MP/changes/",
    "creation": "2016-04-18T14:05:47.149Z",
    "originalLanguage": "EN",
    "conditions": {},
    "context": "",
    "support": {
        "generator": "Change.createInitialFileContent",
        "service": "",
        "user": ""
    }
}
```

```json
{
    "fileName": "id_1460988346969_256_propertyChange",
    "fileType": "change",
    "changeType": "propertyBindingChange",
    "reference": "STTA_MP.Component",
    "packageName": "$TMP",
    "content": {
        "property": "visible",
        "oldValue": true,
        "newBinding": "{myProperty}"
    },
    "selector": {
        "id": "STTA_MP::sap.suite.ui.generic.template.ObjectPage.view.Details::STTA_C_MP_Product--action::STTA_PROD_MAN.STTA_PROD_MAN_Entities::STTA_C_MP_ProductCopywithparams",
        "type": "sap.uxap.ObjectPageHeaderActionButton"
    },
    "layer": "CUSTOMER_BASE",
    "texts": {},
    "namespace": "apps/STTA_MP/changes/",
    "creation": "2016-04-18T14:05:47.149Z",
    "originalLanguage": "EN",
    "conditions": {},
    "context": "",
    "support": {
        "generator": "Change.createInitialFileContent",
        "service": "",
        "user": ""
    }
}
```

**STEP**: 4 — Use expression binding where needed

**DESCRIPTION**: You can use expression binding syntax for transformations (for example negation) in newBinding. The expression must be a valid UI5 expression binding literal.

**LANGUAGE**: text

**CODE**:
```text
Examples of bindings and expressions:
- Simple property binding: "{myProperty}"
- Negation (expression binding): "{= !${myProperty}}"
- Object Page edit mode: "{ui>/editable}"
- Object Page display mode: "{= !${ui>/editable}}"
- Object Page create mode: "{ui>/createMode}"
- Controls enabled: "{ui>/enabled}"
Note: expression binding must be valid UI5 syntax and refer to models available at runtime.
```

**STEP**: 5 — Bind to i18n texts (optional)

**DESCRIPTION**: To bind a property to an i18n text, prefix the binding with the i18n model name. Use the same newBinding field in the change file.

**LANGUAGE**: json

**CODE**:
```json
{
    "content": {
        "property": "tooltip",
        "oldValue": "Move down",
        "newBinding": "{i18n>xtol.MoveDown}"
    }
}
```


**TITLE**: Create a List Report without Variant Management (SAP Fiori Elements)

**INTRODUCTION**: This guide shows how to disable standard variant management for List Report apps in SAP Fiori Elements (OData V2 and V4), and how to display an app-specific subtitle when variant management is hidden. Use these manifest and i18n edits to remove variant UI and show a custom title.

**TAGS**: fiori-elements-framework, sap-fiori, list-report, variant-management, manifest.json, i18n, odata-v2, odata-v4

STEP: V2 — Disable variant management in manifest.json (List Report component)
DESCRIPTION: Add the variantManagementHidden flag under the List Report component settings in sap.ui.generic.app pages. Set smartVariantManagement to true and variantManagementHidden to true to hide page and control variants. If smartVariantManagement is omitted or false, variantManagementHidden will only hide the filter bar variant.
LANGUAGE: JSON
CODE:
```json
"sap.ui.generic.app": {
        "_version":"1.1.0",
        "pages": [
            {
                "entitySet": "XXXXXX_Product",
                "component": {
                    "name": "sap.suite.ui.generic.template.ListReport",
                    "list": true,
                    "settings" : {
                        "gridTable" : false,
                        "smartVariantManagement": true,
                        "variantManagementHidden": true // Hides Variant management
                    }
                },
```

STEP: V2 — Provide an app-specific subtitle when variant management is hidden (i18n)
DESCRIPTION: Add a key in the i18n properties file to supply the subtitle text used when variant management is hidden.
LANGUAGE: properties
CODE:
```properties
#XTIT,40
subTitleIfVariantMgmtHidden = List Report Custom Title
```

STEP: V2 — Bind the subtitle key in manifest.json settings
DESCRIPTION: Reference the i18n key from the List Report settings so the app shows the custom subtitle when variant management is hidden.
LANGUAGE: JSON
CODE:
```json
"sap.ui.generic.app": {
        "_version":"1.1.0",
        "pages": [
            {
                "entitySet": "XXXXXX_Product",
                "component": {
                    "name": "sap.suite.ui.generic.template.ListReport",
                    "list": true,
                    "settings" : {
                        "gridTable" : false,
                        "smartVariantManagement": true,
                        "variantManagementHidden": true,
                        "subTitleIfVariantMgmtHidden": "{{subTitleIfVariantMgmtHidden}}" // Adding Custom Title here
                    }
                },
```

STEP: V2 — Important note
DESCRIPTION: The variantManagementHidden property must be used with smartVariantManagement = true to hide both the page variant and control variant. If used alone, it hides only the filter bar variant.

STEP: V4 — Disable variant management in routing target settings
DESCRIPTION: For OData V4 List Report (FE), set the variantManagement option to "None" in the target settings under sap.ui5.routing.targets to remove standard variant management. If omitted or set to "Page" / "Control", variant management remains available.
LANGUAGE: JSON
CODE:
```json
"sap.ui5": {
            "routing": {
                "targets": {
                    "XXXXXX_List": {
                        "type": "Component",
                        "id": "XXXXXX_List",
                        "name": "sap.fe.templates.ListReport",
                        "options": {
                            "settings" : {
                                "contextPath" : "/XXXXXX",
                                "variantManagement": "None"
                                }
                            }
                        }
                    },
```

STEP: V4 — Provide an app-specific subtitle in i18n
DESCRIPTION: Add a subtitle key to the i18n properties file and set text to display as the app subtitle when variant management is not shown.
LANGUAGE: properties
CODE:
```properties
#XTIT, 40
appSubTitle = List Report Custom Title
```

STEP: V4 — Bind the app subtitle in sap.app section of manifest.json
DESCRIPTION: Reference the i18n subtitle key in sap.app.subTitle so the app displays the custom subtitle.
LANGUAGE: JSON
CODE:
```json
"sap.app": {
            "id": "XXXXXX",
            "type": "application",
            "i18n": "i18n/i18n.properties",
            "title": "{{title}}",
            "subTitle": "{{appSubTitle}}",
            "description": "{{description}}",
```

STEP: V4 — Behavior summary
DESCRIPTION: Setting variantManagement to "None" removes standard variant management and shows the app name (or the app subTitle if provided). Setting variantManagement to "Page" or "Control", or omitting the setting, keeps standard variant management available.


**TITLE**: Creating a SAP Fiori Elements Project with SAP Fiori Tools

**INTRODUCTION**: Step-by-step developer-focused instructions to prepare your environment and generate a SAP Fiori elements application using SAP Fiori tools in SAP Business Application Studio (BAS) or Visual Studio Code (VS Code). Use this when you need to scaffold a new Fiori elements app (list report/object page, overview page, etc.) using the SAP Fiori generator.

**TAGS**: fiori-elements-framework, sap-fiori, sap-fiori-tools, sap-business-application-studio, visual-studio-code, generator

**STEP**: 1 — Verify prerequisites

**DESCRIPTION**: Confirm your environment meets the required prerequisites before creating a Fiori elements app. Open and follow the official prerequisites checklist. Ensure you have either SAP Business Application Studio or Visual Studio Code available.

**LANGUAGE**: Text

**CODE**:
```text
Action items:
- Open and follow the prerequisites checklist:
  prerequisites-for-using-sap-fiori-elements-f2344b5.md

- Ensure you have one of the supported editors:
  - SAP Business Application Studio (recommended for SAP Cloud development)
  - Visual Studio Code

- For SAP Fiori tools installation details (extensions and setup):
  https://help.sap.com/docs/SAP_FIORI_tools/17d50220bcd848aa854c9c182d65b699/e870fcff88b245e9b48a9d9f81715ac0.html
```

**STEP**: 2 — Install SAP Fiori tools in your editor

**DESCRIPTION**: Install the SAP Fiori tools extension set into your chosen editor so you can access the Fiori application generator and other productivity features. Follow the official installation guide for BAS or VS Code.

**LANGUAGE**: Text

**CODE**:
```text
Installation (high level):
- Open your editor (SAP Business Application Studio or Visual Studio Code).
- In Visual Studio Code:
  1. Open Extensions view (Ctrl+Shift+X or View → Extensions).
  2. Search for "SAP Fiori tools".
  3. Install the SAP Fiori tools extensions relevant to Application Generator and App Capabilities.
- In SAP Business Application Studio:
  1. Use the Dev Space that includes SAP Fiori tools (or add the extensions via the SAP Business Application Studio dev space configuration).
- Follow the official installation documentation for exact steps:
  https://help.sap.com/docs/SAP_FIORI_tools/17d50220bcd848aa854c9c182d65b699/e870fcff88b245e9b48a9d9f81715ac0.html
```

**STEP**: 3 — Generate a SAP Fiori elements application

**DESCRIPTION**: Use the SAP Fiori generator (provided by the SAP Fiori tools extension) to scaffold a new Fiori elements application. Launch the generator from your editor, follow the interactive prompts to select project template, data source, OData service, and other app settings. Refer to the official generate-app documentation for platform-specific guidance.

**LANGUAGE**: Text

**CODE**:
```text
Generate app (interactive):
- Open SAP Business Application Studio or Visual Studio Code.
- Launch the Fiori Application Generator:
  - In Visual Studio Code: open Command Palette (Ctrl+Shift+P) → run "Fiori: Open Application Generator"
  - In SAP Business Application Studio: use the Fiori tools menu / command to open the Application Generator
- Follow prompts to:
  1. Choose application type (e.g., SAP Fiori elements - List Report Object Page).
  2. Configure project name and namespace.
  3. Select data source type and specify OData service (URL or local definition).
  4. Configure annotations, pages, navigation, and deployment options.
- For full, editor-specific guidance and screenshots:
  https://help.sap.com/docs/SAP_FIORI_tools/17d50220bcd848aa854c9c182d65b699/db44d45051794d778f1dd50def0fa267.html
```

fiori-elements-framework sap-fiori sap-fiori-tools sap-business-application-studio visual-studio-code generator


**TITLE**: Extension Points to Modify Navigation Context (OData V2 & V4)

**INTRODUCTION**: Use controller extensions to add/remove/modify properties in the navigation context immediately before external outbound navigation is triggered (semantic links, related apps, DataFieldForIntentBasedNavigations). Includes registration in manifest.json and example implementations for OData V2 (adaptNavigationParameterExtension) and OData V4 (adaptNavigationContext).

**TAGS**: fiori-elements, extension, navigation, selectionVariant, odata-v2, odata-v4, intent-based-navigation, manifest, controller-extension, adaptNavigationContext

STEP: Caution and best practices

DESCRIPTION: Use app extensions only when manifest settings or annotations cannot achieve the required behavior. Integrate with SAP Fiori elements by using only the extensionAPI. Do not access or manipulate internal controls, properties, models, or other internal objects created by the SAP Fiori elements framework. See security guidance as needed.

LANGUAGE: Text

CODE:
```text
Caution:
Use app extensions with caution and only if you cannot produce the required behavior by other means, such as manifest settings or annotations. To correctly integrate your app extension coding with SAP Fiori elements, use only the extensionAPI of SAP Fiori elements. After you've created an app extension, its display (for example, control placement and layout) and system behavior (for example, model and binding usage, busy handling) lies within the application's responsibility. SAP Fiori elements provides support only for the official extensionAPI functions. Don't access or manipulate controls, properties, models, or other internal objects created by the SAP Fiori elements framework.

For more security-related information, see Security Configuration documentation.
```

STEP: Register controller extensions in manifest.json (OData V2)

DESCRIPTION: Register your controller extension for List Report and Object Page controllers in the manifest so SAP Fiori elements will load your custom controller implementations. Add the snippet under the appropriate manifest root (e.g., inside "sap.ui5" or as applicable to your project structure).

LANGUAGE: JSON

CODE:
```json
"extends": {
   "extensions": {
      ...
      "sap.ui.controllerExtensions": {
         ...
         "sap.suite.ui.generic.template.ListReport.view.ListReport": {
            ...
            "controllerName": "MY_APP.ext.controller.ListReportExtension",
            ...
         },
         "sap.suite.ui.generic.template.ObjectPage.view.Details": {
            ...
            "controllerName": "MY_APP.ext.controller.DetailsExtension",
            ...
         }
      }
      ...
```

STEP: Create controller extension files

DESCRIPTION: Create the controller files referenced by the manifest controllerName values. For example, with namespace "MY_APP.ext.controller.ListReportExtension" create a file at webapp/ext/controller/ListReportExtension.controller.js and similarly for DetailsExtension. Implement extension methods in these files. Keep code scoped to the extensionAPI and avoid manipulating internal framework objects.

LANGUAGE: Text

CODE:
```text
Example controller file locations (match your namespace):
- webapp/ext/controller/ListReportExtension.controller.js  (namespace: MY_APP.ext.controller.ListReportExtension)
- webapp/ext/controller/DetailsExtension.controller.js     (namespace: MY_APP.ext.controller.DetailsExtension)
```

STEP: Implement adaptNavigationParameterExtension (OData V2)

DESCRIPTION: In your controller extension (List Report, Object Page, or Analytical List Page), implement adaptNavigationParameterExtension(oSelectionVariant, oObjectInfo). Use SelectionVariant API to add/remove parameters or selection options. Do not remove required properties such as the semanticObject for semantic links. SelectionVariant API reference: https://ui5.sap.com/#/api/sap.ui.generic.app.navigation.service.SelectionVariant/overview

LANGUAGE: JavaScript

CODE:
```javascript
adaptNavigationParameterExtension: function(oSelectionVariant, oObjectInfo) {
  // This is an example! Please create your own code!!
  // This is an example to remove the parameter 'Currency' from the parameters
  oSelectionVariant.removeParameter("Currency");
  // This is an example to remove the property 'Price' from the selection option
  oSelectionVariant.removeSelectOption("Price");
  // This is an example to remove all properties which starts with 'D'
  oSelectionVariant.getSelectOptionsPropertyNames().forEach(function(sSelectOptionName){
    if (sSelectOptionName.startsWith('D')) {
       oSelectionVariant.removeSelectOption(sSelectOptionName);
    }
  });
},
```

STEP: Restriction for adaptNavigationParameterExtension (OData V2)

DESCRIPTION: Note that you cannot remove every property required for a navigation link; required properties (for example, the semantic object property) must remain. The method is invoked just before outbound navigation.

LANGUAGE: Text

CODE:
```text
Note:
You cannot remove all properties for each navigation link. For example, the property of the semantic object is required for the semantic object link on the object page.
```

STEP: Register controller extensions in manifest.json (OData V4)

DESCRIPTION: For OData V4 (SAP Fiori elements V4 / SAP Fiori elements for OData V4), register controller extensions using the "sap.ui5" -> "extends" -> "extensions" -> "sap.ui.controllerExtensions" path. Provide controllerName values that point to your extension controllers.

LANGUAGE: JSON

CODE:
```json
"sap.ui5": {
    "extends": {
        "extensions": {
            "sap.ui.controllerExtensions": {
                "sap.fe.templates.ListReport.ListReportController": {
                    "controllerName": "SalesOrder.ext.LRExtend"
                },
                "sap.fe.templates.ObjectPage.ObjectPageController": {
                    "controllerName": "SalesOrder.ext.OPExtend"
                }
            }
        }
    }
}
```

STEP: Implement adaptNavigationContext (OData V4)

DESCRIPTION: In the controller extension (e.g., SalesOrder.ext.OPExtend), override intentBasedNavigation.adaptNavigationContext to modify the passed selection variant (oSelectionVariant) and inspect oTargetInfo (semanticObject and action). oSelectionVariant contains all properties passed to the target app (sensitive info already excluded and object mappings applied). This method is called once when an external outbound navigation is triggered. Use SelectionVariant APIs to remove or modify selection options.

LANGUAGE: JavaScript

CODE:
```javascript
override: {
    intentBasedNavigation: {
        adaptNavigationContext: function(oSelectionVariant, oTargetInfo) {
            Log.info("adaptNavigationContext extension called with semantic object: " + oTargetInfo .semanticObject + " and action: " + oTargetInfo .action);
            oSelectionVariant.removeSelectOption("HasDraftEntity");
        }
    }
}
```

STEP: Restriction and invocation behavior (OData V4)

DESCRIPTION: The adaptNavigationContext extension is invoked only once when you click a field displayed as a link, even if that link opens multiple navigation links. It cannot be invoked by clicking second-level navigation links.

LANGUAGE: Text

CODE:
```text
Restriction:
When you click a field that is displayed as a link, the call to the adaptNavigationContext extension method is invoked only once even if the link opens more than one navigation link. You cannot invoke this method by clicking the navigation links at the second level.
```

fiori-elements extension navigation selectionVariant odata-v2 odata-v4 intent-based-navigation manifest controller-extension adaptNavigationContext


**TITLE**: Configure "Add Card to Insights" Option for My Home (SAP S/4HANA Cloud & On-Premise)

**INTRODUCTION**: This guide shows how to enable/disable the "Add Card to Insights" option that appears in the overflow toolbar of tables (List Report) and charts (Analytical List Page) so end users can create cards for the Insights section of My Home. It includes prerequisites, supported/unsupported column types for card creation, restrictions, and exact manifest.json snippets for SAP Fiori elements OData V2 and V4 scenarios.

**TAGS**: fiori-elements-framework, sap-s4hana, manifest.json, list-report, analytical-list-page, odata-v2, odata-v4, my-home, insights, cards

STEP: Prerequisites

DESCRIPTION: Ensure the administrator has enabled My Home in SAP S/4HANA Cloud (Public Edition) or My Home in SAP S/4HANA. Once enabled, the "Add Card to Insights" option appears automatically in:
- the overflow toolbar of the table in list report applications
- the overflow toolbar of the chart in analytical list page applications

Images (for reference in UI):
- images/Add_Cards_to_Insights_New_fe526c6.png
- images/Add_Cards_to_Insights_ALP_401e0b0.png

LANGUAGE: Text

CODE:
```text
Prerequisite: Administrator must enable My Home in SAP S/4HANA Cloud Public Edition and/or My Home in SAP S/4HANA.
UI placement: Overflow toolbar of table (List Report) and overflow toolbar of chart (Analytical List Page)
```

STEP: Supported and Unsupported Columns for Card Creation

DESCRIPTION: Card creation dialog supports only single-valued DataField-based columns and some link/navigation flavors. Use columns that map to these supported DataField types to ensure fields appear in the card creation dialog.

LANGUAGE: Text

CODE:
```text
Supported column types (card creation dialog shows):
- Single-valued DataField
- DataFieldWithUrl
- Semantic links
- DataField with QuickViewFacets
- (OData V4 only) DataFieldWithIntentBasedNavigation
- (OData V4 only) DataFieldWithNavigationPath

Unsupported column types (will NOT appear in card creation dialog):
- Image
- Multi-valued columns
- FieldGroup-based columns
- Columns with inline action
- Columns with navigation button
- DataFieldForAnnotation-based columns (e.g., contact or address)
- Custom columns
```

STEP: Hide "Add Card to Insights" in SAP Fiori Elements (OData V2) — List Report

DESCRIPTION: To hide the Add Card to Insights option from the table overflow toolbar in a List Report app, add the addCardtoInsightsHidden property under tableSettings in your manifest.json for the specific page entry.

LANGUAGE: JSON

CODE:
```json
"sap.ui.generic.app": {
    "pages": [{
        "entitySet": "Zfarvd_Bs_Hd_Bo",
        "component": {
            "name": "sap.suite.ui.generic.template.ListReport",
            "list": true,
            "settings": {
                "tableSettings": {
                    "addCardtoInsightsHidden": "true" //default value false
                }
            }
        }
    }]
}
```

STEP: Hide "Add Card to Insights" in SAP Fiori Elements (OData V2) — Analytical List Page

DESCRIPTION: To hide the Add Card to Insights option from the chart overflow toolbar in an Analytical List Page app, add the addCardtoInsightsHidden property under chartSettings in your manifest.json for the specific page entry.

LANGUAGE: JSON

CODE:
```json
"sap.ui.generic.app": {
    "pages": [{
        "entitySet": "Zfarvd_Bs_Hd_Bo",
        "component": {
            "name": "sap.suite.ui.generic.template.AnalyticalListPage",
            "list": true,
            "settings": {
               "chartSettings": {
                    "addCardtoInsightsHidden": "true" //default value false
               }
            }
        }
    }]
}
```

STEP: Hide "Add Card to Insights" in SAP Fiori Elements (OData V4) — Table Toolbar

DESCRIPTION: For OData V4 List Report apps (single view or single-entity multi-view with ResponsiveTable), disable the Add Card to Insights option by configuring controlConfiguration for the LineItem annotation specifying type ResponsiveTable and enableAddCardToInsights: false in manifest.json.

LANGUAGE: JSON

CODE:
```json
"controlConfiguration": {
     "@com.sap.vocabularies.UI.v1.LineItem": {
         "tableSettings": {
             "type": "ResponsiveTable",
             "enableAddCardToInsights": false
         }
     }
}
```

STEP: Hide "Add Card to Insights" in SAP Fiori Elements (OData V4) — Chart Toolbar

DESCRIPTION: For OData V4 Analytical List Page charts, disable the Add Card to Insights option by adding a controlConfiguration for the Chart annotation in manifest.json.

LANGUAGE: JSON

CODE:
```json
"controlConfiguration": {
    "@com.sap.vocabularies.UI.v1.Chart": {
        enableAddCardToInsights: false
    }
}
```

STEP: Restrictions When Creating Integration Cards

DESCRIPTION: Be aware of known limitations when creating integration cards from List Report tables:
- Removed filter fields or table columns and changes to their positions are not retained when navigating back from the created card.
- Cards do not retain the same unit-of-measure formatting as the list report table.

LANGUAGE: Text

CODE:
```text
Restrictions:
- Removed filter fields or table columns and changes in their positions are NOT retained when navigating back from the card.
- Cards do NOT retain the same unit-of-measure formatting as shown in the list report table.
```

STEP: Related Documentation Links

DESCRIPTION: Reference the official My Home documentation for Cloud Public Edition and On-Premise S/4HANA.

LANGUAGE: Text

CODE:
```text
Related:
- My Home in SAP S/4HANA Cloud Public Edition:
  https://help.sap.com/docs/SAP_S4HANA_CLOUD/4fc8d03390c342da8a60f8ee387bca1a/8a60279e8d2041b5ad8d3455fab0f3ef.html

- My Home in SAP S/4HANA:
  https://help.sap.com/docs/ABAP_PLATFORM_NEW/a7b390faab1140c087b8926571e942b7/8a60279e8d2041b5ad8d3455fab0f3ef.html
```


**TITLE**: Creating Custom Cards for Fiori Overview Pages

**INTRODUCTION**: Step-by-step action guide to create and integrate a custom overview page card in a SAP Fiori Elements (OVP) application. Shows required file structure, component extension, view fragment, controller, manifest linking, and extension APIs for refresh and filter application.

**TAGS**: fiori-elements-framework, sapui5, ovp, custom-card, overview-page, extension-api, manifest, JavaScript, XML

**STEP**: 1 — Create extension folder

**DESCRIPTION**: Create a new folder under your app's webapp/ext to contain the custom card. Example uses webapp/ext/myCustomCard.

**LANGUAGE**: Bash

**CODE**:
```bash
# from project root
mkdir -p webapp/ext/myCustomCard
```

**STEP**: 2 — Create required files

**DESCRIPTION**: Create the component, controller, and fragment files in the new folder. The header fragment is optional (only required if you want to customize the card header).

Required files:
- Component.js (or component.js as referenced in later steps)
- MyCustomCard.controller.js
- MyCustomCard.fragment.xml
- MyCustomCardHeader.fragment.xml (optional)

**LANGUAGE**: Bash

**CODE**:
```bash
touch webapp/ext/myCustomCard/Component.js
touch webapp/ext/myCustomCard/MyCustomCard.controller.js
touch webapp/ext/myCustomCard/MyCustomCard.fragment.xml
touch webapp/ext/myCustomCard/MyCustomCardHeader.fragment.xml  # optional
```

**STEP**: 3 — Extend the custom card component

**DESCRIPTION**: Implement the custom card component by extending the OVP custom card component. Place this file in webapp/ext/myCustomCard (filename shown in snippet).

Keep the sample component code intact and adapt the names (namespace, default fragments, dependencies) to your project. The metadata properties define which fragment and controller will be used by the card.

**LANGUAGE**: JavaScript

**CODE**:
```javascript
sap.ui.define(["sap/ovp/cards/custom/Component"],
    function (CustomCardComponent) {
        "use strict";
         return CardComponent.extend("test.testovp.ext.myCustomCard.Component", {

            metadata: {
                properties: {
                    "contentFragment": {
                        "type": "string",
                        "defaultValue": "test.testovp.ext.myCustomCard.MyCustomCard"
                    },
                    customizing: {
                        "sap.ui.controllerExtensions": {
                             "sap.ovp.cards.generic.Card": {
                                  controllerName: "test.testovp.ext.myCustomCard.MyCustomCard"
                     }
                 }
             }
                     "annotationPath": {
                         "type": "string",
                         "defaultValue": "com.sap.vocabularies.UI.v1.LineItem"
                     },
                     "countHeaderFragment": {
                         "type": "string",
                         "defaultValue": "sap.ovp.cards.generic.CountHeader"
                     },
                     "headerExtensionFragment": {
                         "type": "string",
                         "defaultValue": "sap.ovp.cards.generic.KPIHeader"
                     }
                 },
                  version: "${version}",
                  library: "sap.ovp",
                  includes: [],
                  dependencies: {
                     libs: ["sap.suite.ui.microchart"],
                     components: []
                 },
                 config: {}
             }
         });
     }
);
```

**STEP**: 4 — Define the card view fragment

**DESCRIPTION**: Implement the content area of your custom card using a UI5 fragment. Place this file as webapp/ext/myCustomCard/MyCustomCard.fragment.xml. Use ovp controls and binding as needed.

**LANGUAGE**: XML

**CODE**:
```xml
<core:FragmentDefinition
         xmlns="sap.m"
         xmlns:core="sap.ui.core"
         xmlns:ovp="sap.ovp.ui"
         xmlns:template="http://schemas.sap.com/sapui5/extension/sap.ui.core.template/1">
     <!-- Here you can put your Card's Content Area -->
</core:FragmentDefinition>
```

**STEP**: 5 — Implement the card controller

**DESCRIPTION**: Add lifecycle and extension methods to the custom card controller. Place this file as webapp/ext/myCustomCard/MyCustomCard.controller.js. Implement onInit, onAfterRendering, and other hooks (onRefresh, setRelevantFilters) as required.

**LANGUAGE**: JavaScript

**CODE**:
```javascript
 (function () {
     "use strict";
     /*global sap, jQuery */

     sap.ui.define([], function() {
         return {
             onInit: function () {
                 ...
             },

             onAfterRendering: function () {
                ...
            }
        }
    });
 })();
```

**STEP**: 6 — Link the custom card component in manifest.json

**DESCRIPTION**: Register the custom card in the application's manifest so the OVP runtime uses your component. Add a card entry that references your component template and settings (title, entitySet, model). Example shows a card key entry snippet.

Place changes in webapp/manifest.json under sap.ovp/config or the card area your app uses.

**LANGUAGE**: JSON

**CODE**:
```json
"card008_HereIsMyCustomCard": {
   "model": "myModel",
   "template": "test.testovp.ext.myCustomCard",
   "settings": {
     "title": "Custom Card Title",
     "entitySet": "MyEntity",
     ...
 	...
```

**STEP**: 7 — Enable Refresh action via onRefresh extension

**DESCRIPTION**: To allow end users to refresh card data (action on the card), implement the onRefresh extension in the controller. Add onRefresh to your MyCustomCard.controller.js and perform re-binding or data reload logic there.

**LANGUAGE**: JavaScript

**CODE**:
```javascript
     (function () {
         "use strict";
         /*global sap, jQuery */

         sap.ui.define([], function() {
             return {
                 onInit: function () {
                     ...
                 },
                 onAfterRendering: function () {
                    ...
                 },
                 onRefresh: function () {
                    ...
                 }
            }
        });
     })();
```

**STEP**: 8 — Apply relevant filters via setRelevantFilters extension

**DESCRIPTION**: Use setRelevantFilters in the custom card controller to receive and apply OVP-provided relevant filters to your card's bindings. The sample shows checking filter arrays and applying them to the card's list/items binding. Place this method in MyCustomCard.controller.js.

**LANGUAGE**: JavaScript

**CODE**:
```javascript
(function () {
    "use strict";
    /*global sap, jQuery */
    sap.ui.define([], function () {
        return {
            onInit: function () { },
            onAfterRendering: function () {},
            /**
             * Extension function to receive card relevant filters
             * @param {sap.ui.model.Filter} oFilters - Relevant filters
             * @returns {void}
             */
            setRelevantFilters: function (oFilters) {
                var oView = this.getView().byId("cardView");
                if (oFilters[0] && oFilters[0].aFilters && oFilters[0].aFilters.length > 0) {
                    // Apply filters to the card
                    oView.getBinding("items").filter(oFilters);
                } else {
                    oView.getBinding("items").filter([]);
                }
            }
        });
})();
```

**STEP**: 9 — Notes and conventions

**DESCRIPTION**: Use these rules and notes when implementing custom cards:
- The header fragment (MyCustomCardHeader.fragment.xml) is optional—create it only if you want a custom header.
- Card templates that begin with "sap.ovp.cards" are reserved for standard OVP cards. Use your own namespace for custom templates (e.g., test.testovp.ext.myCustomCard).
- Confirm file paths:
  - Component: webapp/ext/myCustomCard/Component.js (or component.js depending on naming)
  - Controller: webapp/ext/myCustomCard/MyCustomCard.controller.js
  - Fragment: webapp/ext/myCustomCard/MyCustomCard.fragment.xml
  - Optional header: webapp/ext/myCustomCard/MyCustomCardHeader.fragment.xml
- Update webapp/manifest.json to reference your template/component under the cards configuration.

fiori-elements-framework sapui5 ovp custom-card overview-page extension-api manifest JavaScript XML


**TITLE**: Creating Custom Filters for SAP Fiori Elements (OData V2)

**INTRODUCTION**: This document shows concise, actionable steps to add custom compact filters, visual filter customizations, and KPI tag filter modifications in SAP Fiori elements (Analytical List Page) for OData V2. It includes manifest extension snippets, XML fragment for custom controls, controller extension methods, visual filter hooks, and KPI extension samples ready to paste into your app.

**TAGS**: fiori-elements-framework, sapui5, analytical-list-page, filters, visual-filters, kpi, extension, odata-v2

**STEP**: 1 — Add manifest extensions to include custom filter fragment and controller extension

**DESCRIPTION**: Extend the application manifest (sap.ui5) to register:
- controller extension for the AnalyticalListPage (ALP) view,
- view extension that inserts an XML fragment as a custom filter ControlConfiguration into the SmartFilterBar (key: SmartFilterBarControlConfigurationExtension|<EntitySet>).
Place the extended controller and fragment in your application namespace.

**LANGUAGE**: JSON

**CODE**:
```JSON

                        "sap.ui5": {
    "_version": "1.1.0",
    "extends": {
        "extensions": {
             "sap.ui.controllerExtensions": { // Controller extension
                 "sap.suite.ui.generic.template.AnalyticalListPage.view.AnalyticalListPage": { // ALP app view to be extended with controller
                   "controllerName": "my_app.ext.controller.AnalyticalListPageExt", // extended Controller declared using namespace
                       ... // Other custom controllers
                    ...
                  } // End of ALP controller extensions
             }, // End of controller extensions
             "sap.ui.viewExtensions": { // View Extension
                 "sap.suite.ui.generic.template.AnalyticalListPage.view.AnalyticalListPage": { // ALP app view to be extended with filter fragment
                    "SmartFilterBarControlConfigurationExtension|CZ_EASILINEITEMS_SADL": { // <Filter Bar Extension>|<Entity Set>
                    "className": "sap.ui.core.Fragment",
                    "fragmentName": "analytics2.alr.ext.fragments.CustomFilters", // extended Fragment declared using namespace
                    "type": "XML"
                },
                ... // Other view extensions
                ...
            } // End of ALP view extensions
        } // End of view extensions
      }
   }
}
```

**STEP**: 2 — Create the XML fragment for custom compact filter

**DESCRIPTION**: Add an XML fragment that defines a SmartFilterBar ControlConfiguration entry. Use visibleInAdvancedArea, a custom key, and embed any custom control (example uses ComboBox). Save fragment at the namespace path referenced in manifest (e.g., analytics2/alr/ext/fragments/CustomFilters.fragment.xml).

**LANGUAGE**: XML

**CODE**:
```XML
<core:FragmentDefinition xmlns="sap.m" xmlns:smartfilterbar="sap.ui.comp.smartfilterbar" xmlns:core="sap.ui.core">
    <smartfilterbar:ControlConfiguration key="CustomFilters" index="99" visibleInAdvancedArea="true" label="Custom Filter" groupId="_BASIC">
        <smartfilterbar:customControl>
            <ComboBox id="CustomFilters-combobox">
                <core:Item key="0" text="Item1"/>
                <core:Item key="1" text="Item2"/>
                <core:Item key="2" text="Item3"/>
            </ComboBox>
        </smartfilterbar:customControl>
    </smartfilterbar:ControlConfiguration>
</core:FragmentDefinition>
```

**STEP**: 3 — Implement controller extension methods for SmartFilterBar lifecycle and state persistence

**DESCRIPTION**: Implement the extension controller (registered in manifest) to:
- attach event handlers during onInitSmartFilterBarExtension,
- influence table/chart bindings in onBeforeRebindTableExtension and onBeforeRebindChartExtension,
- persist and restore custom field values using getCustomAppStateDataExtension and restoreCustomAppStateDataExtension.

Paste this code into your controller file (e.g., my_app/ext/controller/AnalyticalListPageExt.js).

**LANGUAGE**: JavaScript

**CODE**:
```JavaScript

sap.ui.define([], function() {
    return {
        onInitSmartFilterBarExtension: function(oEvent) {
        // the custom field in the filter bar might have to be bound to a custom data model
        // if a value change in the field shall trigger a follow up action, this method is the
        // place to define and bind an event handler to the field
        // Example:
        var oSmartFilterBar = oEvent.getSource();
        oSmartFilterBar.getControlByKey("CustomFilters").attachSelectionChange(function(oChangeEvent){
        //code
        },this);
        jQuery.sap.log.info("onInitSmartFilterBarExtension initialized");
        },
        onBeforeRebindTableExtension: function(oEvent) {
        // usually the value of the custom field should have an effect on the selected data in the table.
        // So this is the place to add a binding parameter depending on the value in the custom field.
        },
        onBeforeRebindChartExtension: function(oEvent) {
            // usually the value of the custom field should have an effect on the selected data in the chart.
            // So this is the place to add a binding parameter depending on the value in the custom field.
        },
        getCustomAppStateDataExtension : function(oCustomData) {
            // the content of the custom field shall be stored in the app state, so that it can be restored
            // later again e.g. after a back navigation. The developer has to ensure that the content of the
            // field is stored in the object that is returned by this method.
            // Example:
            var oComboBox = this.byId("CustomFilters-combobox");
                if (oComboBox){
            oCustomData.CustomPriceFilter = oComboBox.getSelectedKey();
        }
            },
        restoreCustomAppStateDataExtension : function(oCustomData) {
            // in order to to restore the content of the custom field in the filter bar e.g. after a
            // back navigation, an object with the content is handed over to this method and the developer
            // has to ensure, that the content of the custom field is set accordingly
            // also, empty properties have to be set
            // Example:
            if ( oCustomData.CustomPriceFilter !== undefined ){
                if ( this.byId("CustomFilters-combobox") ) {
                    this.byId("CustomFilters-combobox").setSelectedKey(oCustomData.CustomPriceFilter);
                }
            }
        }
    }
});
```

**STEP**: 4 — Implement onClearFilterExtension to clear custom filter controls

**DESCRIPTION**: ALP triggers onClearFilterExtension when the user clears filters. Implement logic to clear your custom controls (ComboBox, etc.) so they are reset when Clear is invoked.

**LANGUAGE**: JavaScript

**CODE**:
```JavaScript
onClearFilterExtension: function(oEvent) {
        // Logic for clearing extended filters
        'use strict';
        if ( this.byId("CustomFilters-combobox") ) {
             this.byId("CustomFilters-combobox").setSelectedKey(null);
        }
}
```

**STEP**: 5 — Notes and behaviors for compact filters

**DESCRIPTION**: Keep these important behavioral notes in mind and implement required logic accordingly:
- Custom filters do not appear in visual filters.
- Add logic in onBeforeRebindChartExtension or onBeforeRebindTableExtension to apply custom filter values to table/chart queries; these values refresh automatically when the chart/table area refreshes to keep custom filters synchronized when filter mode changes.
- Ensure getCustomAppStateDataExtension and restoreCustomAppStateDataExtension persist/restore values for navigation/back flows.

**LANGUAGE**: Text

**CODE**:
```Text
- Custom filters do not show up in visual filters.
- If you define logic in onBeforeRebindChartExtension or onBeforeRebindTableExtension to handle values that come from the custom filter fields, then these values are refreshed when the table or chart area is refreshed. This ensures that custom filters are synchronized when the filter mode changes.
- When you choose Clear, ALP triggers onClearFilterExtension, which clears all filter dimensions. This means that you need to define the logic to handle the clear event for custom filters in the application controller extension.
```

**STEP**: 6 — Customize visual filters via onBeforeRebindVisualFilterExtension

**DESCRIPTION**: Use onBeforeRebindVisualFilterExtension to:
- modify visual filter filters/parameters,
- add custom queryParameters for the visual filter call,
- influence sorting,
- access incoming navigation context via this.extensionAPI.getNavigationContext().

Include date/time formatting rules when manipulating date values in SelectionVariant.

**LANGUAGE**: JavaScript

**CODE**:
```JavaScript
onBeforeRebindVisualFilterExtension: function(sEntityType, sDimension, sMeasure, oContext){     // oContext has filters, queryParameters, sorters, entityParameters applicable for this specific visual filter
    'use strict';
    var oNavigationContext = this.extensionAPI.getNavigationContext();                          //getting incoming navigation context through extension API
    if (sDimension === "CostCenter") {
        oContext.queryParameters.Type = "Cost";                                                 //adding custom query parameter (It will be included in visual filter query as "?Type="Cost")

        if (oContext.entityParameters.P_DisplayCurrency === "USD") {                            //Influencing applied parameters / filters
            oContext.queryParameter.Country = "USA";
            oContext.filters.push(new sap.ui.model.Filter("Product", "EQ", "HT-1000"));
        }
    }
}
```

**STEP**: 7 — Visual filter date/time format notes

**DESCRIPTION**: Use these exact formats when setting date/datetime values in SelectionVariant or query parameters to ensure correct parsing by back-end and runtime:

**LANGUAGE**: Text

**CODE**:
```Text
- Date-only format: YYYY-MM-DDT00:00:00Z, e.g., 2018-10-15T00:00:00Z.
- SelectionVariant date/time formats:
  - UTC with milliseconds: YYYY-MM-DDT00:00:00.000Z (e.g., 2018-09-03T12:46:00.000Z)
  - Local with offset: YYYY-MM-DDTHH:MM:SS.fff-HH:MM (e.g., 2018-09-03T12:46:12:123-7:00)
```

**STEP**: 8 — Modify Filterable KPI parameters via onBeforeRebindFilterableKPIExtension

**DESCRIPTION**: Implement onBeforeRebindFilterableKPIExtension to change or add filters/parameters for Filterable KPIs. You can inspect sEntityType and sKPIId to target specific KPI tags. Use the SelectionVariant API to add select options.

Place this code into an extension controller (sap.ui.define) used by the ALP.

**LANGUAGE**: JavaScript

**CODE**:
```JavaScript
sap.ui.define(["sap/base/Log"], function(Log) {
    onBeforeRebindFilterableKPIExtension: function(oSelectionVariant, sEntityType, sKPIId) {
        'use strict';
        // using this extension app can modify the existing filters and parameters
        // and also add/remove/modify the custom filters applied to FilterableKPIs
        if (sKPIId === "alp.tech.app::sap.suite.ui.generic.template.AnalyticalListPage.view.AnalyticalListPage::SEPMRA_C_ALP_SlsOrdItemCubeALPResults--template::KPITag::kpi::KPINetProductPriceByCategory") {
            oSelectionVariant.addSelectOption("Product", "I", "EQ", "HT-1502", null);
        }
        Log.info("onBeforeRebindFilterableKPIExtension called!");
    }
});
```

**STEP**: 9 — Related reference

**DESCRIPTION**: For more advanced ALP configurations and extensions, consult the application extension guide.

**LANGUAGE**: Text

**CODE**:
```Text
Related Information:
- Configuring Analytical List Page App Extensions (see app-specific documentation)
```

fiori-elements-framework sapui5 analytical-list-page filters visual-filters kpi extension odata-v2


**TITLE**: Creating Key Performance Indicator (KPI) Tags for Analytical List Page (ALP)

**INTRODUCTION**: Practical, code-focused guide to configure KPI tags for SAP Fiori elements Analytical List Page (ALP). Includes manifest settings (OData V2/V4), annotation examples (XML, ABAP CDS, CAP CDS) for UI.KPI, DataPoint, SelectionVariant, PresentationVariant, Chart, KPI detail/navigation, number formatting, unit of measure, and filterable KPI configuration. Use these snippets directly in annotation files, CDS sources, or manifest.json.

**TAGS**: KPI, ALP, AnalyticalListPage, manifest.json, UI.KPI, DataPoint, SelectionVariant, PresentationVariant, Chart, CDS, CAP, ODataV2, ODataV4, filterable

STEP: 1 - Configure manifest.json for SAP Fiori elements (OData V2)
DESCRIPTION: Define KPI mapping in manifest.json for ALP (OData V2). Map qualifier to UI.KPI annotation, specify model, entitySet, qualifier, and optional detailNavigation and filterable flags.
LANGUAGE: JSON
CODE:
```json
"sap.ui.generic.app":{
   "pages":[
      {
         "entitySet":"SEPMRA_C_ALP_SlsOrdItemCube",
         "component":{
            "name":"sap.suite.ui.generic.template.AnalyticalListPage",
            "list":true,
            "settings":{
               "keyPerformanceIndicators":{
                  "KPIRevenue":{
                     "model":"kpi",
                     "entitySet":"SEPMRA_C_ALP_TotalSalesKPI",
                     "qualifier":"KPIQuantity",
                     "detailNavigation":"EPMProduct"
                  }
            }
      }
},
```

STEP: 2 - Configure manifest.json for SAP Fiori elements (OData V4 / FE)
DESCRIPTION: Define KPI mapping in sap.ui5 routing target options for Fiori Elements (OData V4 / FE). Map keyPerformanceIndicators with entitySet, qualifier, and optional detailNavigation.
LANGUAGE: JSON
CODE:
```json
"sap.ui5": {
    "routing": {
        "targets": {
            "BusinessPartnersALP": {
                "type": "Component",
                "id": "BusinessPartnersList",
                "name": "sap.fe.templates.ListReport",
                "options": {
                    "settings": {
                        "keyPerformanceIndicators": {
                            "KPIRevenue": {
                                "entitySet": "BusinessPartners",
                                "qualifier": "KPIQuantity"
                            },
                            "KPIVolume": {
                                "entitySet": "BusinessPartners",
                                "qualifier": "Volume",
                                "detailNavigation": "PartnerSales"
                            }
                        }
                    }
                }
            }
        }
    }
}
```

STEP: 3 - UI.KPI annotation (XML) with qualifier KPIQuantity
DESCRIPTION: XML annotation for UI.KPI mapping DataPoint, SelectionVariant and Detail. Required fields: DataPoint path, SelectionVariant path, ID string, and Detail specifying semantic object, action, and default presentation variant.
LANGUAGE: XML
CODE:
```xml
<Annotation Term="UI.KPI" Qualifier="KPIQuantity">
   <Record>
      <PropertyValue Property="DataPoint" Path="@UI.DataPoint#DPForQuantity" />
      <PropertyValue Property="SelectionVariant" Path="@UI.SelectionVariant#SVForQuantity" />
      <PropertyValue Property="ID" String="ActualCostByGLAccountNameKPI" />
      <PropertyValue Property="Detail">
         <Record Type="UI.KPIDetailType">
            <PropertyValue Property="SemanticObject" String="EPMProduct" />
            <PropertyValue Property="Action" String="manage_stta" />
            <PropertyValue Property="DefaultPresentationVariant" Path="@UI.PresentationVariant#PVForQuantity" />
         </Record>
      </PropertyValue>
   </Record>
</Annotation>
```

STEP: 4 - UI.KPI annotation (ABAP CDS)
DESCRIPTION: ABAP CDS inline KPI annotation example mapping selection variant qualifier, ID, datapoint, criticality, detail and qualifier. Use in CDS view definitions.
LANGUAGE: ABAP CDS
CODE:
```abap
@UI.KPI: [
  {
    selectionVariantQualifier: 'SVForQuantity',
    id: 'ActualCostByGLAccountNameKPI',
    dataPoint.title: 'Define datapoint inline',
    datapoint.minimumValue: 2,
    detail: {
      semanticObject: 'EPMProduct',
      semanticObjectAction: 'manage_stta',
      defaultPresentationVariantQualifier: 'PVForQuantity'
    },
    qualifier: 'KPIQuantity'
  }
]
DPForQuantity;
```

STEP: 5 - UI.KPI annotation (CAP CDS)
DESCRIPTION: CAP CDS representation for UI.KPI using qualifier and references to DataPoint, SelectionVariant and PresentationVariant. Use in .cds files when annotating entities.
LANGUAGE: CDS
CODE:
```cds
UI.KPI #KPIQuantity : {
    DataPoint : ![@UI.DataPoint#DPForQuantity],
    SelectionVariant : ![@UI.SelectionVariant#SVForQuantity],
    ID : 'ActualCostByGLAccountNameKPI',
    Detail : {
        $Type : 'UI.KPIDetailType',
        SemanticObject : 'EPMProduct',
        Action : 'manage_stta',
        DefaultPresentationVariant : ![@UI.PresentationVariant#PVForQuantity]
    }
},
```

STEP: 6 - KPIDetailType (XML)
DESCRIPTION: Define KPI detail navigation metadata. SemanticObject and Action enable launching target app. DefaultPresentationVariant links to visualization.
LANGUAGE: XML
CODE:
```xml
<PropertyValue Property="Detail">
   <Record Type="UI.KPIDetailType">
      <PropertyValue Property="SemanticObject" String="EPMProduct" />
      <PropertyValue Property="Action" String="manage_stta" />
      <PropertyValue Property="DefaultPresentationVariant" Path="@UI.PresentationVariant#PVForQuantity" />
   </Record>
</PropertyValue>
```

STEP: 7 - DataPoint annotation (XML) with qualifier DPForQuantity
DESCRIPTION: DataPoint defines title, description, value path and criticality. This datapoint is referenced by UI.KPI for KPI value and color logic.
LANGUAGE: XML
CODE:
```xml
<Annotation Term="com.sap.vocabularies.UI.v1.DataPoint" Qualifier="DPForQuantity">
   <Record Type="com.sap.vocabularies.UI.v1.DataPointType">
      <PropertyValue Property="Title" String="Quantity by Customer Company Name" />
      <PropertyValue Property="Description" String="About NumberOfSalesOrders" />
      <PropertyValue Property="Value" Path="Quantity" />
      <PropertyValue Property="Criticality" EnumMember="com.sap.vocabularies.UI.v1.CriticalityType/Neutral" />
   </Record>
</Annotation>
```

STEP: 8 - SelectionVariant annotation (XML)
DESCRIPTION: Configure default filter parameters and select options used by the KPI (overrides Common.FilterDefaultValue). Provide Parameters and SelectOptions to seed KPI backend requests.
LANGUAGE: XML
CODE:
```xml
<Annotation Term="UI.SelectionVariant" Qualifier="SVForQuantity">
   <Record>
      <PropertyValue Property="Parameters">
         <Collection>
            <Record Type="UI.Parameter">
               <PropertyValue Property="PropertyName" PropertyPath="CompanyCurrency" />
               <PropertyValue Property="PropertyValue" String="EUR" />
            </Record>
         </Collection>
      </PropertyValue>
      <PropertyValue Property="SelectOptions">
         <Collection>
            <Record Type="UI.SelectOptionType">
               <PropertyValue Property="PropertyName" PropertyPath="MainProductCategory" />
               <PropertyValue Property="Ranges">
                  <Collection>
                     <Record Type="UI.SelectionRangeType">
                        <PropertyValue EnumMember="UI.SelectionRangeSignType/I" Property="Sign" />
                        <PropertyValue EnumMember="UI.SelectionRangeOptionType/EQ" Property="Option" />
                        <PropertyValue Property="Low" String="Computer Systems" />
                     </Record>
                  </Collection>
               </PropertyValue>
            </Record>
         </Collection>
      </PropertyValue>
   </Record>
</Annotation>
```

STEP: 9 - SelectionVariant annotation (ABAP CDS)
DESCRIPTION: CDS-style selectionVariant qualifier for use in ABAP CDS sources when defining KPI selection defaults.
LANGUAGE: ABAP CDS
CODE:
```abap
@UI.selectionVariant: [
  {
    qualifier: 'SVForQuantity',
    parameters: [{name: 'PropertyName', value: 'CompanyCurrency' },{ name: 'PropertyValue', value: 'EUR'}]
  }
]
```

STEP: 10 - SelectionVariant annotation (CAP CDS)
DESCRIPTION: CAP CDS equivalent of SelectionVariant with Parameters and SelectOptions arrays. Use in CAP .cds annotations.
LANGUAGE: CDS
CODE:
```cds
UI.SelectionVariant #SVForQuantity : {
    Parameters : [
        {
            $Type : 'UI.Parameter',
            PropertyName : CompanyCurrency,
            PropertyValue : 'EUR'
        },
    ],
    SelectOptions : [
        {
            $Type : 'UI.SelectOptionType',
            PropertyName : MainProductCategory,
            Ranges : [
                {
                    $Type : 'UI.SelectionRangeType',
                    Sign : #I,
                    Option : #EQ,
                    Low : 'Computer Systems'
                }
            ]
        }
    ]
}
```

STEP: 11 - PresentationVariant annotation (XML) with qualifier PVForQuantity
DESCRIPTION: PresentationVariant defines SortOrder and Visualizations. The first visualization renders the KPI value. Link PresentationVariant qualifier to UI.KPI Detail.DefaultPresentationVariant.
LANGUAGE: XML
CODE:
```xml
<Annotation Term="com.sap.vocabularies.UI.v1.PresentationVariant" Qualifier="PVForQuantity">
   <Record>
      <PropertyValue Property="SortOrder">
         <Collection>
            <Record Type="Common.SortOrderType">
               <PropertyValue Property="Property" PropertyPath="Quantity" />
               <PropertyValue Property="Descending" Bool="true" />
            </Record>
         </Collection>
      </PropertyValue>
      <PropertyValue Property="Visualizations">
         <Collection>
            <AnnotationPath>@com.sap.vocabularies.UI.v1.Chart#QuantityChart</AnnotationPath>
         </Collection>
      </PropertyValue>
   </Record>
</Annotation>
```

STEP: 12 - PresentationVariant annotation (ABAP CDS)
DESCRIPTION: ABAP CDS PresentationVariant with SortOrder and Visualizations qualifier for CDS views.
LANGUAGE: ABAP CDS
CODE:
```abap
@UI.PresentationVariant: [
  {
    sortOrder: [
      {
        by: 'QUANTITY',
        direction: #DESC
      }
    ],
    visualizations: [
      {
        type: #AS_CHART,
        qualifier: 'QuantityChart'
      }
    ],
    qualifier: 'PVForQuantity'
  }
]
annotate view VIEWNAME with {

}
```

STEP: 13 - PresentationVariant annotation (CAP CDS)
DESCRIPTION: CAP CDS PresentationVariant with SortOrder and Visualizations linking to UI.Chart qualifier.
LANGUAGE: CDS
CODE:
```cds
UI.PresentationVariant #PVForQuantity : {
    SortOrder : [
        {
            $Type : 'Common.SortOrderType',
            Property : Quantity,
            Descending : true
        },
    ],
    Visualizations : [
        '@UI.Chart#QuantityChart'
    ]
}
```

STEP: 14 - Chart annotation (XML) with qualifier QuantityChart
DESCRIPTION: Define chart visualization for KPI presentation. Include MeasureAttributes, DimensionAttributes, ChartType and Description. First visualization entry in PresentationVariant is used by KPI rendering.
LANGUAGE: XML
CODE:
```xml
<Annotation Term="com.sap.vocabularies.UI.v1.Chart" Qualifier="QuantityChart">
   <Record>
      <PropertyValue Property="Title" String="NumberOfSalesOrders" />
      <PropertyValue Property="MeasureAttributes">
         <Collection>
            <Record Type="com.sap.vocabularies.UI.v1.ChartMeasureAttributeType">
               <PropertyValue Property="Measure" PropertyPath="Quantity" />
               <PropertyValue Property="Role" EnumMember="com.sap.vocabularies.UI.v1.ChartMeasureRoleType/Axis1" />
            </Record>
         </Collection>
      </PropertyValue>
      <PropertyValue Property="DimensionAttributes">
         <Collection>
            <Record Type="com.sap.vocabularies.UI.v1.ChartDimensionAttributeType">
               <PropertyValue Property="Dimension" PropertyPath="SoldToPartyCompanyName" />
               <PropertyValue Property="Role" EnumMember="com.sap.vocabularies.UI.v1.ChartDimensionRoleType/Category" />
            </Record>
         </Collection>
      </PropertyValue>
      <PropertyValue Property="ChartType" EnumMember="UI.ChartType/Bar" />
      <PropertyValue Property="Description" String="NumberOfSalesOrders by Customer Company Name" />
   </Record>
</Annotation>
```

STEP: 15 - Chart annotation (ABAP CDS)
DESCRIPTION: ABAP CDS chart annotation mapping measure/dimension/ chartType with qualifier for CDS views.
LANGUAGE: ABAP CDS
CODE:
```abap
@UI.Chart: [
  {
    title: 'NumberOfSalesOrders',
    measureAttributes: [
      {
        measure: 'Quantity',
        role: #AXIS_1
      }
    ],
    dimensionAttributes: [
      {
        dimension: 'SoldToPartyCompanyName',
        role: #CATEGORY
      }
    ],
    chartType: #BAR,
    description: 'NumberOfSalesOrders by Customer Company Name',
    qualifier: 'QuantityChart'
  }
]
annotate view VIEWNAME with {

}
```

STEP: 16 - Chart annotation (CAP CDS)
DESCRIPTION: CAP CDS chart definition referencing measure/dimension and chart type. Use in CAP .cds.
LANGUAGE: CDS
CODE:
```cds
UI.Chart #QuantityChart : {
    Title : 'NumberOfSalesOrders',
    MeasureAttributes : [
        {
            $Type : 'UI.ChartMeasureAttributeType',
            Measure : Quantity,
            Role : #Axis1
        },
    ],
    DimensionAttributes : [
        {
            $Type : 'UI.ChartDimensionAttributeType',
            Dimension : SoldToPartyCompanyName,
            Role : #Category
        },
    ],
    ChartType : #Bar,
    Description : 'NumberOfSalesOrders by Customer Company Name'
}
```

STEP: 17 - KPI Title Abbreviation Rules (plaintext)
DESCRIPTION: Rules used to abbreviate KPI Title displayed in KPI tag. Title is taken from DataPoint.Title.
LANGUAGE: Plaintext
CODE:
```text
If KPI name is:
- One word: abbreviation = first three letters. Example: TargetMargin -> TAR
- Two words: abbreviation = first letter of each word. Example: Actual Cost -> AC
- Three or more words: abbreviation = first letter of first three words. Example: Actual Margin Relative -> AMR
```

STEP: 18 - KPI Value and Color: DataPoint properties and criticality (plaintext)
DESCRIPTION: Actionable rules to determine KPI color and value rendering. The first visualization in PresentationVariant renders KPI value and color. Use DataPoint.Value and DataPoint.ValueFormat for percent and number formatting. Use CriticalityCalculation and Criticality to set thresholds.
LANGUAGE: Plaintext
CODE:
```text
- KPI value and color rendered from first DataPoint visualization in PresentationVariant.
- Percent-based KPIs display '%' with value (use ValueFormat).
- Define thresholds using DataPoint properties:
  - CriticalityCalculation: static thresholds or path-based values.
  - Criticality: server-side complex logic (overrides CriticalityCalculation if both present).
- ImprovementDirection (Maximizing / Minimizing / Range/Target) determines color logic:
  - Use appropriate threshold configuration for Target, Maximizing, or Minimizing measures.
- If thresholds are missing/insufficient, ALP chooses closest color match.
- KPI ID is passed as EvaluationId to target app when navigating (KPI Detail must include SemanticObject and Action).
```

STEP: 19 - Number formatting and NumberOfFractionalDigits (XML)
DESCRIPTION: Override OData metadata NumberOfFractionalDigits using DataPoint.ValueFormat.NumberOfFractionalDigits. Up to 2 decimals are shown by default; higher values add to 2.
LANGUAGE: XML
CODE:
```xml
<Annotation Term="com.sap.vocabularies.UI.v1.DataPoint" Qualifier="Price">
    <Record Type="com.sap.vocabularies.UI.v1.DataPointType">
        <PropertyValue Property="Value" Path="Price"/>
        <PropertyValue Property="ValueFormat">
            <Record Type="com.sap.vocabularies.UI.v1.NumberFormat">
                <PropertyValue Property="NumberOfFractionalDigits" Int="1"/>
            </Record>
        </PropertyValue>
    </Record>
</Annotation>
```

STEP: 20 - Number formatting (ABAP CDS)
DESCRIPTION: CDS annotation example overriding number of fractional digits for price field.
LANGUAGE: ABAP CDS
CODE:
```abap
@UI.dataPoint: {
   valueFormat.numberOfFractionalDigits: 1
}
price;
```

STEP: 21 - Number formatting (CAP CDS)
DESCRIPTION: CAP CDS DataPoint with ValueFormat.NumberOfFractionalDigits set to control fraction digits.
LANGUAGE: CDS
CODE:
```cds
UI.DataPoint #Price : {
    $Type : 'UI.DataPointType',
    Value : Price,
    ValueFormat : {
        $Type : 'UI.NumberFormat',
        NumberOfFractionalDigits : 1
    }
}
```

STEP: 22 - Units of Measure (XML) - display KPI with currency or unit
DESCRIPTION: Attach Org.OData.Measures.V1.ISOCurrency or Org.OData.Measures.V1.Unit to KPI property to show unit/currency. Use Path to use entity property or String to hardcode.
LANGUAGE: XML
CODE:
```xml
<Annotations Target="CZ_PROJECTKPIS_CDS.CZ_PROJECTKPISType/ActualCost">
        <Annotation Term="Org.OData.Measures.V1.ISOCurrency" Path="CompanyCodeCurrency"/>
</Annotations>
<Annotations Target="CZ_PROJECTKPIS_CDS.CZ_PROJECTKPISType/TargetMargin">
        <Annotation Term="Org.OData.Measures.V1.ISOCurrency" String="EUR"/>
</Annotations>
<Annotations Target="CZ_PROJECTKPIS_CDS.CZ_PROJECTKPISType/ActualMarginRelative">
        <Annotation Term="Org.OData.Measures.V1.Unit" String="%"/>
</Annotations>
<Annotations Target="CZ_PROJECTKPIS_CDS.CZ_PROJECTKPISType/NetWeight">
        <Annotation Term="Org.OData.Measures.V1.Unit" Path="WeightUnit"/>
</Annotations>
```

STEP: 23 - Units of Measure (CAP CDS)
DESCRIPTION: CAP CDS example annotating entity type with ISOCurrency measure mapping.
LANGUAGE: CDS
CODE:
```cds
annotate CZ_PROJECTKPIS_CDS.CZ_PROJECTKPISType with {
  @Measures.ISOCurrency : CompanyCodeCurrency
  ActualCost
};
```

STEP: 24 - Override unit of measure (XML)
DESCRIPTION: Example to override backend unit/currency mapping and force a specific unit (e.g., '%').
LANGUAGE: XML
CODE:
```xml
<Annotations Target="CZ_PROJECTKPIS_CDS.CZ_PROJECTKPISType/ActualCost">
     <Annotation Term="Org.OData.Measures.V1.Unit" String="%"/>
</Annotations>
```

STEP: 25 - Configure filterable KPIs (OData V2 manifest)
DESCRIPTION: Enable filterable KPIs by setting "filterable": true in manifest.json keyPerformanceIndicators entry. Filterable KPIs react to filter bar changes when technical names/fields match between KPI entity set and ALP filter bar.
LANGUAGE: JSON
CODE:
```json
"sap.ui.generic.app":{
   "pages":[
      {
         "entitySet":"SEPMRA_C_ALP_SlsOrdItemCube",
         "component":{
            "name":"sap.suite.ui.generic.template.AnalyticalListPage",
            "list":true,
            "settings":{
               "keyPerformanceIndicators":{
                  "KPIRevenue":{
                     "model":"kpi",
                     "entitySet":"SEPMRA_C_ALP_TotalSalesKPI",
                     "qualifier":"KPIRevenue",
                     "filterable":true,
                     "detailNavigation":"OverviewPage"
                  }
            }
      }
},
```

STEP: 26 - Filterable KPIs behavior and semantic coloring (plaintext)
DESCRIPTION: Operational notes and restrictions for filterable KPIs and semantic coloring.
LANGUAGE: Plaintext
CODE:
```text
- Filterable KPIs are only available for SAP Fiori elements OData V2.
- If SelectionVariant default values overlap with filter bar fields:
  - filter bar values override SelectionVariant defaults.
  - otherwise SelectionVariant defaults are applied in addition.
- ALP ignores UI.Hidden fields on filter selection for filterable KPIs if KPI entity set marks the filter field as UI.Hidden.
- If showGoButtonOnFilterBar is true, filterable KPIs are hidden until Go is clicked.
- Semantic coloring requires path-based CriticalityCalculation values (only path-based supported for filterable KPIs).
- For KPI navigation, define SemanticObject, Action and KPI ID in UI.KPI; KPI ID is passed as EvaluationId to target application.
```

STEP: 27 - Chart type restrictions for OData V4 (plaintext)
DESCRIPTION: Supported chart types and limited PresentationVariant parameters considered by ALP when using OData V4.
LANGUAGE: Plaintext
CODE:
```text
For OData V4 ALP:
- Supported chart types: line, column, bar, stacked bar, stacked column, vertical_bullet, scatter, combination, donut, bubble.
- PresentationVariant: only SortOrder and MaxItems parameters are considered by ALP.
```

STEP: 28 - References and related files
DESCRIPTION: Use these internal docs for additional ALP title area and variant configuration.
LANGUAGE: Plaintext
CODE:
```text
Related:
- Configuring the Title Area: configuring-the-title-area-ebdb5da.md
- Managing Variants: managing-variants-8ce658e.md
```

KPI ALP AnalyticalListPage manifest.json UI.KPI DataPoint SelectionVariant PresentationVariant Chart CDS CAP ODataV2 ODataV4 filterable


**TITLE**: Creating Key Performance Indicators (KPI) in SAP Fiori elements (OData V4, manifest-based)

**INTRODUCTION**: This guide shows how to add manifest-based KPI tags in SAP Fiori elements for OData V4. Use the manifest.json keyPerformanceIndicators section to register KPI fragments and create an XML fragment using the KPITag building block (sap.fe.macros.KPITag). If needed, wire a press handler via an extension controller. Use this for KPI tags that do not require an analytical service.

**TAGS**: fiori-elements, OData V4, KPI, manifest.json, KPITag, sap.fe.macros, UI5, fragment, extension

**STEP**: 1 — Register KPI fragments in manifest.json

**DESCRIPTION**: Add a keyPerformanceIndicators section under targets -> <yourTarget> -> options -> settings in manifest.json. Each KPI entry name (e.g., "myKPITag") maps to a fragment template module name. The template value must be the UI5 module name for the fragment that contains your KPI definition (e.g., sap.fe.core.fpmExplorer.customKPIContent.CustomKPITag maps to file sap/fe/core/fpmExplorer/customKPIContent/CustomKPITag.fragment.xml in the project).

**LANGUAGE**: JSON

**CODE**:
```json
{
  "targets": {
    "mainPage": {
      "type": "Component",
      "id": "Default",
      "name": "sap.fe.templates.ListReport",
      "options": {
        "settings": {
          "contextPath": "/RootEntity",
          "variantManagement": "None",
          "initialLoad": true,
          "keyPerformanceIndicators": {
            "myKPITag": {
              "template": "sap.fe.core.fpmExplorer.customKPIContent.CustomKPITag"
            },
            "myKPIWithPress": {
              "template": "sap.fe.core.fpmExplorer.customKPIContent.CustomKPITagWithPress"
            }
          }
        }
      }
    }
  }
}
```

**STEP**: 2 — Create the KPI XML fragment using sap.fe.macros.KPITag

**DESCRIPTION**: Implement the fragment file whose module name matches the template in manifest.json. Use the KPITag macro to match the standard KPI design (number, unit, status, showIcon, press). Example fragment module name sap.fe.core.fpmExplorer.customKPIContent.CustomKPITag corresponds to file path sap/fe/core/fpmExplorer/customKPIContent/CustomKPITag.fragment.xml.

**LANGUAGE**: XML

**CODE**:
```xml
<core:FragmentDefinition
  xmlns="sap.m"
  xmlns:core="sap.ui.core"
  xmlns:macros="sap.fe.macros">

  <macros:KPITag
    number="0"
    unit="Days"
    status="Error"
    showIcon="true"
    press=".extension.sap.fe.core.fpmExplorer.customKPIContent.LRExtend.onKPIPressed"
  />

</core:FragmentDefinition>
```

**STEP**: 3 — Implement the extension controller handler (optional, if press is used)

**DESCRIPTION**: If the KPI fragment defines a press event that points to an extension controller method (see press=".extension.<module>.<ControllerName>.<method>"), implement the extension controller at the corresponding module path. Example module sap.fe.core.fpmExplorer.customKPIContent.LRExtend maps to file sap/fe/core/fpmExplorer/customKPIContent/LRExtend.controller.js. The method receives the UI5 event and can navigate or open a dialog.

**LANGUAGE**: JavaScript

**CODE**:
```javascript
sap.ui.define([
  "sap/ui/core/mvc/Controller"
], function (Controller) {
  "use strict";

  return Controller.extend("sap.fe.core.fpmExplorer.customKPIContent.LRExtend", {
    onKPIPressed: function (oEvent) {
      // oEvent contains the press event from the KPITag
      // Implement navigation, dialog, or custom logic here
      var oSource = oEvent.getSource();
      // Example: simple log
      /* eslint-disable no-console */
      console.log("KPI pressed:", oSource);
      /* eslint-enable no-console */
    }
  });
});
```

**STEP**: 4 — Notes, properties and references

**DESCRIPTION**: Use properties on KPITag such as number, unit, status, showIcon, and press. You can reuse any fragment content, but using sap.fe.macros.KPITag keeps UI consistent with analytical-service KPIs. For API and live examples see the KPITag documentation: https://ui5.sap.com/#/api/sap.fe.macros.KPITag and the sample floorplan page: https://ui5.sap.com/test-resources/sap/fe/core/fpmExplorer/index.html#/topic/floorplanListReport/customKPI.

**LANGUAGE**: JSON

**CODE**:
```json
{
  "notes": [
    "Template module name -> fragment file path mapping: replace dots with slashes and append .fragment.xml",
    "Example: sap.fe.core.fpmExplorer.customKPIContent.CustomKPITag -> sap/fe/core/fpmExplorer/customKPIContent/CustomKPITag.fragment.xml",
    "press attribute can reference extension controllers using the .extension.<module>.<Controller>.<method> syntax"
  ]
}
```

fiori-elements
OData V4
KPI
manifest.json
KPITag
sap.fe.macros
UI5
fragment
extension