**TITLE**: Custom State Handling for Extended SAP Fiori Elements Apps (OData V2 & V4)

**INTRODUCTION**: Action-oriented guide for implementing custom app-state handling in SAP Fiori Elements (OData V2 and OData V4). Includes required extension hooks, lifecycle definitions, reuse-component signatures, ViewState controller-extension examples, manifest registration, and how to trigger app-state updates from custom controls.

**TAGS**: fiori-elements-framework, odata-v2, odata-v4, viewstate, extensionapi, sapui5, controller-extension, object-page, app-state

**STEP**: 1 — Call ExtensionAPI.onCustomStateChange when custom UI state changes (OData V2)

**DESCRIPTION**: When your custom UI element changes a persistable state, call the Object Page ExtensionAPI method onCustomStateChange() so the framework knows to collect and persist state. This method has no parameters.

**LANGUAGE**: JavaScript

**CODE**:
```javascript
// Example: Call when custom control changes its persistable state
onCustomControlChange: function() {
    // notify framework that custom state changed and should be collected
    this.extensionAPI.onCustomStateChange();
}
```

**STEP**: 2 — Implement provideCustomStateExtension(oState) to supply state (OData V2)

**DESCRIPTION**: Override provideCustomStateExtension in your object page controller. The framework passes an empty oState object. Add properties whose values are objects with two required keys:
- data: any JSON-serializable object (state payload)
- lifecycle: object with boolean lifecycle flags (session, permanent, page, pagination)

Provide example structure and usage.

**LANGUAGE**: JavaScript

**CODE**:
```javascript
// Example: provideCustomStateExtension override in object page controller
provideCustomStateExtension: function(oState) {
    // Add a named state "myControlState" with data and lifecycle
    oState.myControlState = {
        data: {
            selectedKey: this.byId("mySelect").getSelectedKey(),
            filter: { foo: "bar" }
        },
        lifecycle: {
            session: true,      // survives cross-app navigation during session
            permanent: false,   // persists beyond session if configured
            page: false,
            pagination: false
        }
    };
}
```

**STEP**: 3 — Implement applyCustomStateExtension(oState, bIsSameAsLast) to restore state (OData V2)

**DESCRIPTION**: Override applyCustomStateExtension in the object page controller. The oState contains properties added previously; each property value corresponds to the earlier data object (may have been serialized/deserialized). The lifecycle details are not provided here; evaluate oState and restore controls. If bIsSameAsLast is truthy, skip applying UI changes (page should already be in same state).

**LANGUAGE**: JavaScript

**CODE**:
```javascript
// Example: applyCustomStateExtension override in object page controller
applyCustomStateExtension: function(oState, bIsSameAsLast) {
    if (bIsSameAsLast) {
        // No UI changes required when revisiting the same instance
        return;
    }
    if (oState && oState.myControlState) {
        var sKey = oState.myControlState.selectedKey;
        this.byId("mySelect").setSelectedKey(sKey);
        // restore other parts of the state as needed
    }
}
```

**STEP**: 4 — Define lifecycle object semantics and example (OData V2)

**DESCRIPTION**: Each state item’s lifecycle object controls whether that piece of state is preserved across:
- session: survive cross-app navigation during same browser session (hash in URL)
- permanent: survive sessions (requires front-end persistence configuration; stored in URL hash)
- page: apply when user navigates to same page for different instance
- pagination: similar to page but only when instance changes by pagination UI

Provide an explicit example of a state entry with lifecycle flags.

**LANGUAGE**: JSON

**CODE**:
```json
{
  "myControlState": {
    "data": {
      "scrollPosition": 120,
      "selectedKey": "A"
    },
    "lifecycle": {
      "session": true,
      "permanent": false,
      "page": false,
      "pagination": false
    }
  }
}
```

**STEP**: 5 — Reuse components: implement stGetCurrentState() and stApplyState(oState, bIsSameAsLast) signatures

**DESCRIPTION**: Reuse components cannot override controller extension methods. Implement these two methods inside the reuse component to participate in state handling:
- stGetCurrentState(): return a state object matching the { data, lifecycle } structure (no wrapper oState parameter).
- stApplyState(oState, bIsSameAsLast): apply the passed state.data to the component.

**LANGUAGE**: JavaScript

**CODE**:
```javascript
// Example reuse component API methods
stGetCurrentState: function() {
    return {
        myReuseState: {
            data: {
                collapsed: this._isCollapsed,
                selectedTab: this._selectedTab
            },
            lifecycle: {
                session: true,
                permanent: false,
                page: false,
                pagination: false
            }
        }
    };
},

stApplyState: function(oState, bIsSameAsLast) {
    if (bIsSameAsLast) {
        return;
    }
    if (oState && oState.myReuseState && oState.myReuseState.collapsed !== undefined) {
        this._setCollapsed(oState.myReuseState.collapsed);
        this._selectTab(oState.myReuseState.selectedTab);
    }
}
```

**STEP**: 6 — Implement a control state handler for ViewState (OData V4)

**DESCRIPTION**: Control state handlers must expose retrieve(oControl) and apply(oControl, oControlState, oNavParameters) functions. Use adaptControlStateHandler to attach handlers for custom controls (e.g., ObjectPageLayout).

**LANGUAGE**: JavaScript

**CODE**:
```javascript
{
  retrieve: function(oOPLayout) {
    return {
      selectedSection: oOPLayout.getSelectedSection()
    };
  },
  apply: function(oOPLayout, oControlState, oNavParameters) {
    oControlState && oOPLayout.setSelectedSection(oControlState.selectedSection);
  }
}
```

**STEP**: 7 — Override the default ViewState controller extension (OData V4)

**DESCRIPTION**: Create a ControllerExtension that overrides the viewState extension functions: adaptControlStateHandler, adaptStateControls, retrieveAdditionalStates, applyAdditionalStates, and any before/after hooks. Register the controller extension in manifest.json under sap.ui5 > extends > extensions > sap.ui.controllerExtensions.

**LANGUAGE**: JavaScript

**CODE**:
```javascript
return ControllerExtension.extend("Custom.LRControllerExtension", {
	override: {
		viewState: {
			adaptControlStateHandler: function(oControl, aControlHandlers) {
				if (oControl.isA("sap.f.DynamicPage")) {
					aControlHandlers.push({
						retrieve: function(oControl) {
							return {
								headerExpanded: oControl.getHeaderExpanded()
							};
						},
						apply: function(oControl, mControlState) {
							if ("headerExpanded" in mControlState) {
								oControl.setHeaderExpanded(mControlState.headerExpanded);
							}
						}
					});
				}
			},
			adaptStateControls: function(aControls) {
				aControls.push(this.getView().byId("My::DynamicePage::Control"));
			},
			retrieveAdditionalStates: function(mAdditionalStates) {
				mAdditionalStates.lastVisit = new Date().toString();
			},
			applyAdditionalStates: function(mAdditionalStates) {
				if (mAdditionalStates.lastVisit) {
					MessageToast.show("Applying view state from " + mAdditionalStates.lastVisit);
				}
			}
		}
	}
});
```

**STEP**: 8 — Register the controller extension in manifest.json (OData V4)

**DESCRIPTION**: Add the controller extension registration to sap.ui5.extends.extensions.sap.ui.controllerExtensions for the template controller.

**LANGUAGE**: JSON

**CODE**:
```json
{
    "sap.ui5": {
        "extends": {
            "extensions": {
                "sap.ui.controllerExtensions": {
                    "sap.fe.templates.ListReport.ListReportController": {
                        "controllerName": "Custom.LRControllerExtension"
                    }
                }
            }
        }
    }
}
```

**STEP**: 9 — Trigger app-state update when view state changes (OData V4 & general)

**DESCRIPTION**: When custom view/control state changes, notify the framework so it will compute and persist the new app state. Use the ExtensionAPI method updateAppState (or the object-page onCustomStateChange for OData V2). Call this from your controller/extension when a persistable change occurs.

**LANGUAGE**: JavaScript

**CODE**:
```javascript
// Example: trigger full app-state update via ExtensionAPI
onCustomControlChange: function() {
    // Inform framework to update the overall app state (V4)
    this.extensionAPI.updateAppState();

    // For OData V2 Object Page: call onCustomStateChange() instead
    // this.extensionAPI.onCustomStateChange();
}
```

fiori-elements-framework odata-v2 odata-v4 viewstate extensionapi sapui5 controller-extension object-page app-state


**TITLE**: Customizing List Card — Smart Links, Text Arrangement, Filters, Sorting

**INTRODUCTION**: This guide shows how to customize list cards in Fiori Elements using OData/UI annotations and application descriptor properties. It includes exact code examples for XML annotations, ABAP CDS, and CAP CDS. Use these snippets to add semantic object (smart links), control text arrangement in list items, add filters, and configure sorting/grouping.

**TAGS**: fiori-elements-framework, annotations, OData, CDS, CAP, ABAP, smart-links, text-arrangement, filters, sorting, list-card

**STEP**: 1 — Add Smart Links (Semantic Object)
**DESCRIPTION**: Define a semantic object for the entity set property so the list card can render smart links (navigation to semantic actions). Add these annotations to your service metadata (XML) or model (ABAP CDS / CAP CDS).
**LANGUAGE**: XML
**CODE**:
```xml
<Annotations Target="GWSAMPLE_BASIC.SalesOrder/SalesOrderID">
<Annotation Term="com.sap.vocabularies.Common.v1.SemanticObject" String="OVP" />
</Annotations>

```

**LANGUAGE**: ABAP CDS
**CODE**:
```

annotate view SALESORDER with {
  @Consumption.semanticObject: 'OVP'
  salesorderid;
}

```

**LANGUAGE**: CAP CDS
**CODE**:
```

annotate GWSAMPLE_BASIC.SalesOrder with {
  @Common.SemanticObject : 'OVP'
  SalesOrderID
};

```

**STEP**: 2 — Text Arrangement in List Area
**DESCRIPTION**: Use Text and TextArrangement annotations to control how a main value and its descriptive text are displayed in the list area. Apply annotations on the property target (XML) or in the CDS model (ABAP / CAP). The Text annotation binds a descriptive property; TextArrangement chooses display order.
**LANGUAGE**: XML
**CODE**:
```xml
<Annotations xmlns="http://docs.oasis-open.org/odata/ns/edm" Target="GWSAMPLE_BASIC.SalesOrder/CustomerID">
<Annotation Term="com.sap.vocabularies.Common.v1.Text" Path="Supplier_Name"/>
<Annotation Term="com.sap.vocabularies.UI.v1.TextArrangement" EnumMember="com.sap.vocabularies.UI.v1.TextArrangementType/TextLast" />
</Annotation>
</Annotations>

```

**LANGUAGE**: ABAP CDS
**CODE**:
```

annotate view SALESORDER with {
  @UI.TextArrangement: #TEXT_LAST
  customerid;
}

```

**LANGUAGE**: CAP CDS
**CODE**:
```

annotate GWSAMPLE_BASIC.SalesOrder with {
  @Common.Text : Supplier_Name
  @UI.TextArrangement : #TextLast
  CustomerID
};

```

**DESCRIPTION (continued)**: Text arrangement rendering examples (when main property is ContractID and descriptive text is Customer):
- TextLast -> ContractID (Customer)
- TextFirst -> Customer (ContractID)
- TextOnly -> Customer

Use the appropriate EnumMember or CDS annotation constant (#TEXT_LAST / #TextLast) depending on platform.

**STEP**: 3 — Filtering the List Card
**DESCRIPTION**: Add filters in two ways:
- Use the annotation term com.sap.vocabularies.UI.v1.SelectionVariant in your OData/UI annotations to define filter fields and defaults.
- Pass filter parameters in the card URL (query string) to apply dynamic filters at runtime.
See the referenced configuration document for advanced filter mapping: configuring-card-filters-ecde99f.md

**LANGUAGE**: XML (annotation term reference)
**CODE**:
```xml
<!-- Use com.sap.vocabularies.UI.v1.SelectionVariant in your annotations to define filters and defaults -->
<!-- Example structure (add specific properties and values per your model): -->
<Annotations Target="YourService.EntitySet">
  <Annotation Term="com.sap.vocabularies.UI.v1.SelectionVariant">
    <!-- SelectionVariant details here -->
  </Annotation>
</Annotations>
```

**STEP**: 4 — Sorting or Grouping
**DESCRIPTION**: Configure default sort and grouping for list cards via the application descriptor (manifest.json). Use the properties:
- sortBy — property name to sort by
- sortOrder — "asc" or "desc"

For details and examples, see: configuring-sort-properties-41af842.md

**LANGUAGE**: JSON (manifest example placeholder)
**CODE**:
```json
{
  "sap.card": {
    "content": {
      "sortBy": "CreatedAt",
      "sortOrder": "desc"
    }
  }
}
```

fiori-elements-framework annotations OData CDS CAP ABAP smart-links text-arrangement filters sorting list-card


**TITLE**: Customizing Table Card (Smart Links, Text Arrangement, Filtering, Sorting/Grouping)

**INTRODUCTION**: This guide shows how to customize the table area of an SAP Fiori Elements table card. It covers adding smart links (semantic objects), configuring text arrangement for display formatting, applying filters, and controlling sorting/grouping via manifest.json. Use the provided annotation examples for XML OData metadata, ABAP CDS, and CAP CDS.

**TAGS**: fiori-elements-framework, annotations, smart-links, text-arrangement, filtering, sorting, grouping, manifest.json, ABAP, CAP, OData, XML, CDS

**STEP**: 1 — Adding Smart Links

**DESCRIPTION**: Define a semantic object for an entity set property so that the table cell is rendered as a smart link. Implement this by adding the SemanticObject annotation on the property target. Examples provided for XML OData annotations, ABAP CDS, and CAP CDS.

**LANGUAGE**: XML

**CODE**:
```xml
<Annotations Target="GWSAMPLE_BASIC.SalesOrder/SalesOrderID">
  <Annotation Term="com.sap.vocabularies.Common.v1.SemanticObject" String="OVP" />
</Annotations>
```

**LANGUAGE**: ABAP CDS

**CODE**:
```abap
annotate view SALESORDER with {
 @Consumption.semanticObject: 'OVP'
 salesorderid;
}
```

**LANGUAGE**: CDS

**CODE**:
```cds
annotate GWSAMPLE_BASIC.SalesOrder with {
  @Common.SemanticObject : 'OVP'
  SalesOrderID
};
```

**STEP**: 2 — Text Arrangement in Table Area

**DESCRIPTION**: Use the Text and TextArrangement annotations to bind and format display text for a property in the table area. Examples below show how to bind a text property and set text arrangement (TextLast/TextFirst/TextOnly) for XML, ABAP CDS, and CAP CDS.

**LANGUAGE**: XML

**CODE**:
```xml
<Annotations xmlns="http://docs.oasis-open.org/odata/ns/edm" Target="GWSAMPLE_BASIC.SalesOrder/CustomerID">
  <Annotation Term="com.sap.vocabularies.Common.v1.Text" Path="Supplier_Name"/>
  <Annotation Term="com.sap.vocabularies.UI.v1.TextArrangement" EnumMember="com.sap.vocabularies.UI.v1.TextArrangementType/TextLast" />
</Annotations>
```

**LANGUAGE**: ABAP CDS

**CODE**:
```abap
annotate view SALESORDER with {
 @UI.TextArrangement: #TEXT_LAST
 customerid;
}
```

**LANGUAGE**: CDS

**CODE**:
```cds
annotate GWSAMPLE_BASIC.SalesOrder with {
  @Common.Text : Supplier_Name,
  @UI.TextArrangement : #TextLast,
  CustomerID
};
```

**DESCRIPTION**: Text arrangement rendering results (choose the arrangement that matches your UX requirement):
- TextLast => ContractID (Customer)
- TextFirst => Customer (ContractID)
- TextOnly => Customer

**STEP**: 3 — Filtering

**DESCRIPTION**: Add filters to the table card using:
- The com.sap.vocabularies.UI.v1.SelectionVariant annotation term in your metadata/annotations.
- Or by passing filter parameters in the card URL.

See the Configuring Card Filters reference for examples and selection variant patterns:
- configuring-card-filters-ecde99f.md

**LANGUAGE**: (conceptual)
**CODE**:
```text
// Use com.sap.vocabularies.UI.v1.SelectionVariant in your annotations
// Or append OData filter query parameters to the card URL for runtime filtering
```

**STEP**: 4 — Sorting or Grouping

**DESCRIPTION**: Control sorting and grouping of table card entries via manifest.json using the sortBy and sortOrder properties. Define the property name for sortBy and "asc" or "desc" for sortOrder. See the Configuring Sort Properties reference for additional options.

**LANGUAGE**: JSON

**CODE**:
```json
{
  "sap.card": {
    "content": {
      "data": {
        "sortBy": "SalesOrderID",
        "sortOrder": "asc"
      }
    }
  }
}
```

Reference for detailed configuration:
- configuring-sort-properties-41af842.md

fiori-elements-framework annotations smart-links text-arrangement filtering sorting grouping manifest.json ABAP CAP OData XML CDS


**TITLE**: Data Points — UI.DataPoint, UI.ReferenceFacet, and NumberFormat overrides

**INTRODUCTION**: This document shows how to define and render data points in Fiori Elements object page headers using UI.DataPoint and UI.ReferenceFacet annotations. It includes XML, ABAP CDS, and CAP CDS examples, plus how to control decimal places for numerical data points using NumberFormat.NumberOfFractionalDigits.

**TAGS**: fiori-elements, annotations, UI.DataPoint, UI.ReferenceFacet, NumberFormat, CDS, CAP, ABAP, XML

**STEP**: 1 — Render DataPoint in Header via UI.ReferenceFacet

**DESCRIPTION**: Add UI.ReferenceFacet entries that point to UI.DataPoint qualifiers so the data point title and value render in the object page header. The XML example shows ReferenceFacet entries that reference a DataPoint qualifier or a navigation property with a DataPoint qualifier. The ABAP CDS and CAP CDS examples show how to declare header facets with DATAPOINT_REFERENCE / ReferenceFacet pointing to qualifiers.

**LANGUAGE**: XML

**CODE**:
```xml
<Annotation Term="UI.HeaderFacets">
    <Collection>
        ...
        <Record Type="UI.ReferenceFacet">
            <PropertyValue Property="Target" AnnotationPath="@UI.DataPoint#Price" />
        </Record>
        ...
        <Record Type="UI.ReferenceFacet">
            <PropertyValue Property="Target" AnnotationPath="to_StockAvailability/@UI.DataPoint#StockAvailability" />
        </Record>
        ...
    </Collection>
</Annotation>
```

**LANGUAGE**: ABAP CDS

**CODE**:
```abap
@UI.Facet: [
  {
    label: '{@i18n>@TechnicalData}',
    targetQualifier: 'TechnicalData',
    type: #FIELDGROUP_REFERENCE,
    purpose: #HEADER
  },
  {
    targetQualifier: 'Price',
    type: #DATAPOINT_REFERENCE,
    purpose: #HEADER
  },
  {
    targetQualifier: 'ProductCategory',
    type: #DATAPOINT_REFERENCE,
    purpose: #HEADER
  },
  {
    label: 'Employee',
    targetElement: 'TO_SUPPLIER',
    type: #CONTACT_REFERENCE,
    purpose: #HEADER
  }
]
product;
```

**LANGUAGE**: CAP CDS

**CODE**:
```cap
UI.HeaderFacets : [
    {
        $Type : 'UI.ReferenceFacet',
        Label : '{@i18n>@TechnicalData}',
        Target : '@UI.FieldGroup#TechnicalData'
    },
    {
        $Type : 'UI.ReferenceFacet',
        Target : '@UI.DataPoint#Price'
    },
    {
        $Type : 'UI.ReferenceFacet',
        Target : '@UI.DataPoint#ProductCategory'
    },
    {
        $Type : 'UI.ReferenceFacet',
        Label : 'Employee',
        Target : 'to_Supplier/@Communication.Contact'
    }
]
```

**STEP**: 2 — Define UI.DataPoint annotations

**DESCRIPTION**: Define UI.DataPoint annotations with qualifiers. Each UI.DataPoint must specify a qualifier and typically includes Value and Title. Optionally include Criticality or other properties. Examples below show XML annotations for Price and StockAvailability, plus ABAP CDS and CAP CDS declaration patterns.

**LANGUAGE**: XML

**CODE**:
```xml
<Annotation Term="UI.DataPoint" Qualifier="Price">
    <Record>
        <PropertyValue Property="Value" Path="Price" />
        <PropertyValue Property="Title" String="Price" />
    </Record>
</Annotation>

<Annotations Target="STTA_PROD_MAN.STTA_C_MP_StockAvailabilityType">
    <Annotation Term="UI.DataPoint" Qualifier="StockAvailability">
        <Record>
            <PropertyValue Property="Value" Path="StockAvailability" />
            <PropertyValue Property="Title" String="Availability" />
            <PropertyValue Property="Criticality" Path="StockAvailability" />
        </Record>
    </Annotation>
</Annotations>
```

**LANGUAGE**: ABAP CDS

**CODE**:
```abap
@UI.dataPoint: {
  title: 'Price'
}
Price;

@UI.dataPoint: {
  title: 'Category'
}
ProductCategory;
```

**LANGUAGE**: CAP CDS

**CODE**:
```cap
UI.DataPoint #Price : {
    Value : Price,
    Title : 'Price'
},
UI.DataPoint #ProductCategory : {
    Value : ProductCategory,
    Title : 'Category'
}
```

**STEP**: 3 — Numerical Data Points: control decimal places with NumberFormat.NumberOfFractionalDigits

**DESCRIPTION**: For numerical data points, override metadata scale/precision display using NumberFormat.NumberOfFractionalDigits (annotation ValueFormat -> NumberFormat). The NumberOfFractionalDigits determines decimal places shown in the UI; the following concrete examples illustrate behavior (metadata: Scale = 3, Precision = 15):

- NumberOfFractionalDigits undefined -> UI shows 3 decimal places
- NumberOfFractionalDigits = 5 -> UI shows 5 decimal places
- NumberOfFractionalDigits = 1 -> UI shows 1 decimal place
- NumberOfFractionalDigits = 20 -> UI shows 14 decimal places
- NumberOfFractionalDigits = 0 -> UI shows 3 decimal places

Define NumberOfFractionalDigits within the DataPoint's ValueFormat (NumberFormat) as shown in the examples below.

**LANGUAGE**: XML

**CODE**:
```xml
<Annotation Term="UI.DataPoint" Qualifier="Weight">
    <Record Type="com.sap.vocabularies.UI.v1.DataPointType">
        <PropertyValue Property="Value" Path="Weight" />
        <PropertyValue Property="Title" String="Weight" />
        <PropertyValue Property="ValueFormat">
            <Record Type="com.sap.vocabularies.UI.v1.NumberFormat">
                <PropertyValue Property="NumberOfFractionalDigits" Int="5"/>
            </Record>
        </PropertyValue>
    </Record>
</Annotation>
```

**LANGUAGE**: ABAP CDS

**CODE**:
```abap
@UI.dataPoint: {
  title: 'Weight',
  valueFormat: {
    numberOfFractionalDigits: 5
  }
}
Weight;
```

**LANGUAGE**: CAP CDS

**CODE**:
```cap
UI.DataPoint #Weight : {
    $Type : 'UI.DataPointType',
    Value : Weight,
    Title : 'Weight',
    ValueFormat : {
        $Type : 'UI.NumberFormat',
        NumberOfFractionalDigits : 5
    }
}
```

fiori-elements annotations UI.DataPoint UI.ReferenceFacet NumberFormat CDS CAP ABAP XML


**TITLE**: Defining Actions in the Chart Toolbar (UI.Chart Annotation)

**INTRODUCTION**: How to add action buttons to a chart toolbar by defining the Actions property in the UI.Chart annotation. Includes XML, ABAP CDS, and CAP CDS code samples and required properties for visibility and enablement. Use this when you want chart-level actions (triggering backend actions or navigation intents) in SAP Fiori Elements charts.

**TAGS**: UI.Chart, chart-toolbar, actions, DataFieldForAction, DataFieldForIntentBasedNavigation, ODataV2, ODataV4, CDS, CAP, ABAP

STEP: 1 — Requirements for Adding Actions to Chart Toolbar

DESCRIPTION:
- The UI.Chart Actions property must be a collection containing items of types UI.DataFieldForAction and/or UI.DataFieldForIntentBasedNavigation.
- To make a button visible in the chart toolbar, ensure the properties Determining and Inline on UI.DataFieldForAction/UI.DataFieldForIntentBasedNavigation are either false or not defined (omit them).
- UI.DataFieldForAction-based chart actions do not support passing a selected context (no context parameter is passed).
- For intent-based navigation (UI.DataFieldForIntentBasedNavigation), use RequiresContext to require a chart selection; default is true (selection required). Set RequiresContext = false to always enable the button.
- When controlling visibility via path-based settings:
  - OData V2: the path must be based on a property from the parent entity set (not from the chart entity set). See filename: using-action-control-for-context-dependent-actions-5b0b686.md for context-dependent control.
  - OData V4: when using OperationAvailable, the property must also be from the parent entity set (not the chart entity set).

LANGUAGE: Text

CODE:
```text
Notes:
- Actions collection must contain UI.DataFieldForAction and/or UI.DataFieldForIntentBasedNavigation.
- To display toolbar buttons: Determining and Inline must be false or omitted.
- DataFieldForAction does NOT pass context.
- For intent-based navigation enablement: use RequiresContext (default true).
- Path-based visibility settings must reference properties of the parent entity set (not chart entity set).
- Related docs:
  - using-action-control-for-context-dependent-actions-5b0b686.md
  - adding-actions-to-tables-b623e0b.md (Enablement of Operations for OData V4)
- Image references in original docs:
  - images/Actions_in_Smart_Chart_Toolbar_067d5d8.png
  - images/ChartActions_NavProps_9111386.png
```

STEP: 2 — XML Annotation Example (UI.Chart with Actions)

DESCRIPTION:
- Add Actions collection to the UI.Chart annotation.
- Example shows a UI.DataFieldForAction and a UI.DataFieldForIntentBasedNavigation entry.
- Ensure Determining and Inline are false or omitted. Set InvocationGrouping if needed.

LANGUAGE: XML

CODE:
```xml
<Annotation Term="UI.Chart">
    <Record>
        <PropertyValue Property="ChartType" EnumMember="UI.ChartType/Column"/>
        <PropertyValue Property="Dimensions">
            <Collection>
                <PropertyPath>product</PropertyPath>
            </Collection>
        </PropertyValue>
        <PropertyValue Property="Measures">
            <Collection>
                <PropertyPath>sales</PropertyPath>
            </Collection>
        </PropertyValue>
        <PropertyValue Property="Actions">
            <Collection>
                <Record Type="UI.DataFieldForAction">
                    <PropertyValue Property="Label" String="provide_label"/>
                    <PropertyValue Property="Action" String="provide_action_name"/>
                    <PropertyValue Property="InvocationGrouping" EnumMember="UI.OperationGroupingType/Isolated"/>
                </Record>
                <Record Type="UI.DataFieldForIntentBasedNavigation">
                    <PropertyValue Property="Label" String="provide_label"/>
                    <PropertyValue Property="SemanticObject" String="provide_semantic_object"/>
                    <PropertyValue Property="Action" String="provide_action_name"/>
                </Record>
            </Collection>
        </PropertyValue>
    </Record>
</Annotation>
```

STEP: 3 — ABAP CDS Annotation Example

DESCRIPTION:
- Annotate a CDS view with UI.Chart and Actions (UI.DataFieldForAction and UI.DataFieldForIntentBasedNavigation).
- The ABAP CDS sample shows the dataAction with a PUSHDOWN qualifier and invocationGrouping mapping.

LANGUAGE: ABAP

CODE:
```abap
@UI.Chart: [
  {
    chartType: #COLUMN,
    dimensions: [
      'PRODUCT'
    ],
    measures: [
      'SALES'
    ],
    actions: [
      {
        label: 'provide_label',
        dataAction: 'PUSHDOWN:provide_action_name',
        invocationGrouping: #ISOLATED,
        type: #FOR_ACTION
      },
      {
        label: 'provide_label',
        semanticObjectAction: 'provide_action_name',
        type: #FOR_INTENT_BASED_NAVIGATION
      }
    ]
  }
]
annotate view STTA_C_MP_PRODUCTSALESDATA with {

}
```

STEP: 4 — CAP CDS Annotation Example

DESCRIPTION:
- CAP CDS representation of UI.Chart with Actions. Use $Type to specify UI.DataFieldForAction or UI.DataFieldForIntentBasedNavigation.
- Keep InvocationGrouping/Invocation grouping and SemanticObject as required.

LANGUAGE: CDS

CODE:
```cds
UI.Chart : {
    ChartType : #Column,
    Dimensions : [
        product
    ],
    Measures : [
        sales
    ],
    Actions : [
        {
            $Type : 'UI.DataFieldForAction',
            Label : 'provide_label',
            Action : 'provide_action_name',
            InvocationGrouping : #Isolated
        },
        {
            $Type : 'UI.DataFieldForIntentBasedNavigation',
            Label : 'provide_label',
            SemanticObject : 'provide_semantic_object',
            Action : 'provide_action_name'
        }
    ]
}
```

STEP: 5 — Controlling Enablement of Actions (OData V2)

DESCRIPTION:
- For UI.DataFieldForAction-based enable/disable (context-dependent), use the approach documented in "Using Action Control for Context-Dependent Actions" (using-action-control-for-context-dependent-actions-5b0b686.md).
- For UI.DataFieldForIntentBasedNavigation, use RequiresContext:
  - RequiresContext = true (default) → user must select a chart item to enable the button.
  - RequiresContext = false → button always enabled.
- If using path-based applicable-path to control visibility, ensure the path property belongs to the parent entity set (not the chart entity set).

LANGUAGE: Text

CODE:
```text
OData V2 enablement guidance:
- DataFieldForAction: use action-control approach (see using-action-control-for-context-dependent-actions-5b0b686.md).
- DataFieldForIntentBasedNavigation: set RequiresContext to true/false.
- Path-based applicable-path must reference parent entity set property.
```

STEP: 6 — Controlling Enablement of Actions (OData V4)

DESCRIPTION:
- Use the same enablement strategy as Tables (see Adding Actions to Tables => Enablement of Operations in adding-actions-to-tables-b623e0b.md).
- Use OperationAvailable path-based setting to control visibility; the referenced property must be from the parent entity set (not the chart entity set).

LANGUAGE: Text

CODE:
```text
OData V4 enablement guidance:
- Use enablement logic from "Adding Actions to Tables" (Enablement of Operations).
- OperationAvailable path must reference a property from the parent entity set.
```

UI.Chart chart-toolbar actions DataFieldForAction DataFieldForIntentBasedNavigation ODataV2 ODataV4 CDS CAP ABAP


**TITLE**: Defining and Adapting Object Page Sections (UI.Facets)

**INTRODUCTION**: Action-oriented reference for defining, structuring, and adapting sections and subsections on SAP Fiori Object Pages using com.sap.vocabularies.UI.v1.Facets annotations (XML, ABAP CDS, CAP CDS) and related manifest.json settings. Includes patterns for reference vs collection facets, table rendering, dynamic visibility, stable IDs, and SmartForm layout configuration.

**TAGS**: fiori-elements-framework, OData V2, OData V4, annotations, UI.Facets, manifest.json, CDS, CAP, ABAP, XML

STEP: 1 — Create top-level sections and subsections using UI.Facets

DESCRIPTION: Use UI.ReferenceFacet and UI.CollectionFacet under UI.Facets to define sections (top-level) and subsections (second-level via a collection facet with nested facets). Do not create collection facets beyond second level (third level and above ignored). Avoid using a UI.CollectionFacet under UI.Facets that contains only one UI.ReferenceFacet — use UI.ReferenceFacet directly to prevent rendering issues. Note differences: in OData V2 reference facets outside second-level collection facets are ignored; in OData V4 they are considered as separate subsections.

LANGUAGE: XML

CODE:
```xml
<Annotation Term="UI.Facets">
    <Collection>
        <Record Type="UI.ReferenceFacet">
            <PropertyValue Property="Label" String="{@i18n>@GeneralInfoFacetLabel}"/>
            <PropertyValue Property="Target" AnnotationPath="@UI.FieldGroup#GeneralInformation" />
        </Record>
        <Record Type="UI.CollectionFacet">
            <PropertyValue Property="ID" String="FurtherData"/>
            <PropertyValue Property="Label" String="{@i18n>@FurtherData}"/>
            <PropertyValue Property="Facets">
                <Collection>
                    <Record Type="UI.CollectionFacet">
                    </Record>
                </Collection>
            </PropertyValue>
        </Record>
    </Collection>
</Annotation>
```

STEP: 2 — Equivalent definitions in ABAP CDS and CAP CDS

DESCRIPTION: Same section/subsection structure can be expressed in ABAP CDS or CAP CDS. For ABAP CDS use @UI.Facet; for CAP CDS use UI.Facets. Ensure IDs are unique and meaningful (camelCase, no spaces).

LANGUAGE: ABAP CDS

CODE:
```
@UI.Facet: [
  {
    label: '{@i18n>@GeneralInfoFacetLabel}',
    targetQualifier: 'GeneralInformation',
    type: #FIELDGROUP_REFERENCE,
    purpose: #STANDARD
  },
  {
    id: 'FurtherData',
    label: '{@i18n>@FurtherData}',
    type: #COLLECTION,
    purpose: #STANDARD
  },
  {
    parentId: 'FurtherData',
    purpose: #STANDARD
  }
]
product;
```

LANGUAGE: CAP CDS

CODE:
```
UI.Facets : [
    {
        $Type : 'UI.ReferenceFacet',
        Label : '{@i18n>@GeneralInfoFacetLabel}',
        Target : '@UI.FieldGroup#GeneralInformation',
    },
    {
        $Type : 'UI.CollectionFacet',
        ID : 'FurtherData',
        Label : '{@i18n>@FurtherData}',
        Facets : [
            {
                $Type : 'UI.CollectionFacet'
            }
        ]
    }
]
```

STEP: 3 — Reference facet examples and mapping to field groups/line items/charts

DESCRIPTION: Reference facets point at annotations such as UI.FieldGroup, UI.LineItem, UI.Chart, UI.Identification. When a reference facet points to a LineItem, a list/table is rendered in the section. Ensure the annotation path is correct.

LANGUAGE: XML

CODE:
```xml
<Annotation Term="UI.Facets">
  <Collection>
    <Record Type="UI.CollectionFacet">
      <PropertyValue Property="ID" String="FacetIdentifier1"/>
      <PropertyValue Property="Label" String="Section 1"/>
      <PropertyValue Property="Facets">
        <Collection>
          <Record Type="UI.ReferenceFacet">
            <PropertyValue Property="ID" String="FacetIdentifier2"/>
            <PropertyValue Property="Target" AnnotationPath=_Child/@UI.LineItem/>
          </Record>
        </Collection>
      </PropertyValue>
    </Record>

    <Record Type="UI.CollectionFacet">
      <PropertyValue Property="ID" String="FacetIdentifier2"/>
      <PropertyValue Property="Label" String="Section 2"/>
      <PropertyValue Property="Facets">
        <Collection>
          <Record Type="UI.ReferenceFacet">
            <PropertyValue Property="ID" String="FacetIdentifier2"/>
            <PropertyValue Property="Target" AnnotationPath=_Child/@UI.SelectionPresentationVariant#mySPV/>
          </Record>
        </Collection>
      </PropertyValue>
    </Record>
  </Collection>
</Annotation>
```

LANGUAGE: CAP CDS

CODE:
```
Facets                              : [
  {
    $Type : 'UI.CollectionFacet',
    ID    : 'FacetIdentifier1',
    Label : 'Section 1',
    Facets: [{
      $Type : 'UI.ReferenceFacet',
      ID    : 'FacetIdentifier2',
      Target: '_Child/@UI.LineItem'
    }]
  },
  {
    $Type : 'UI.CollectionFacet',
    ID    : 'FacetIdentifier2',
    Label : 'Section 2',
    Facets: [{
      $Type : 'UI.ReferenceFacet',
      ID    : 'FacetIdentifier2',
      Target: '_Child/@UI.SelectionPresentationVariant#mySPV'
    }]
  }
]
```

STEP: 4 — Hide or show sections dynamically using UI.Hidden

DESCRIPTION: Apply UI.Hidden on a ReferenceFacet (or other facets) to bind visibility to an entity property. Use the same pattern across XML, ABAP CDS, and CAP CDS.

LANGUAGE: XML

CODE:
```xml
<Record Type="UI.ReferenceFacet">
   <Annotation Term="UI.Hidden" Path="IsActiveEntity"/>
   <PropertyValue Property="Label" String="{@i18n>@SalesData}" />
   <PropertyValue Property="Target" AnnotationPath="to_ProductSalesData/@UI.Chart" />
</Record>
```

LANGUAGE: ABAP CDS

CODE:
```
@UI.facet: [
 {
  label: '{@i18n>@SalesData}',
  type:         #DATAPOINT_REFERENCE,
  targetElement: '_PRODUCTSALESDATA',
  purpose: #STANDARD
 }
]
product;
```

LANGUAGE: CAP CDS

CODE:
```
UI.Facets : {
    $Type : 'UI.ReferenceFacet',
    Label : '{@i18n>@SalesData}',
    Target : 'to_ProductSalesData/@UI.Chart',
    ![@UI.Hidden] : IsActiveEntity
}
```

STEP: 5 — Rendering tables in sections and enabling creation

DESCRIPTION: To render a table inside a section: reference UI.LineItem or a PresentationVariant/SelectionPresentationVariant that contains UI.LineItem as the first visualization. For inline creation or create button, ensure Org.OData.Capabilities.V1.InsertRestrictions/Insertable/Bool is true on the target entity set (server-side capability). Use SelectionPresentationVariant only if it contains a PresentationVariant with UI.LineItem first.

LANGUAGE: XML (example already shown in Step 3 above)

CODE:
```xml
        <Annotation Term="UI.Facets">
          <Collection>
            <Record Type="UI.CollectionFacet">
              <PropertyValue Property="ID" String="FacetIdentifier1"/>
              <PropertyValue Property="Label" String="Section 1"/>
              <PropertyValue Property="Facets">
                <Collection>
                  <Record Type="UI.ReferenceFacet">
                    <PropertyValue Property="ID" String="FacetIdentifier2"/>
                    <PropertyValue Property="Target" AnnotationPath=_Child/@UI.LineItem/>
                  </Record>
                </Collection>
              </PropertyValue>
            </Record>

            <Record Type="UI.CollectionFacet">
              <PropertyValue Property="ID" String="FacetIdentifier2"/>
              <PropertyValue Property="Label" String="Section 2"/>
              <PropertyValue Property="Facets">
                <Collection>
                  <Record Type="UI.ReferenceFacet">
                    <PropertyValue Property="ID" String="FacetIdentifier2"/>
                    <PropertyValue Property="Target" AnnotationPath=_Child/@UI.SelectionPresentationVariant#mySPV/>
                  </Record>
                </Collection>
              </PropertyValue>
            </Record>
          </Collection>
        </Annotation>
```

STEP: 6 — Stable IDs for Collection Facets (mandatory) and Reference Facets (optional)

DESCRIPTION: Define ID for UI.CollectionFacet to enable stable view/control IDs used for extensions, personalization, and automated testing. Use meaningful unique camelCase IDs without spaces. If no ID for a UI.ReferenceFacet is defined, the runtime derives it from the annotation path by replacing "/@" with "::". Avoid adding IDs post-delivery because stable IDs are used to build control IDs.

LANGUAGE: XML

CODE:
```xml
<Annotation Term="UI.Facets">
  <Collection>
    <Record Type="UI.CollectionFacet">
      <PropertyValue Property="ID" String="GeneralInformation"/>
    </Record>
  </Collection>
</Annotation>
```

LANGUAGE: ABAP CDS

CODE:
```
@UI.Facet: [
  {
    id: 'GeneralInformation',
    type: #COLLECTION,
    purpose: #STANDARD
  }
]
```

LANGUAGE: CAP CDS

CODE:
```
UI.Facets : [
    {
        $Type : 'UI.CollectionFacet',
        ID : 'GeneralInformation'
    }
]
```

STEP: 7 — Section layout mode: Page vs Tabs (manifest.json configuration)

DESCRIPTION: Choose section layout by setting "sectionLayout" in the component options under sap.ui.generic.app settings: "Page" (default; all sections on same page with anchor navigation) or "Tabs" (each top-level section as a separate tab). Use "Tabs" for better UX with UI.Table (grid/table).

LANGUAGE: JSON

CODE:
```json
"SalesOrderManageObjectPage":{
    "type": "Component",
    "id": "SalesOrderManageObjectPage",
    "name": "sap.fe.templates.ObjectPage",
    "options":{
        "settings":{
            "contextPath": "/SalesOrderManage",
            "navigation":{
                "_Item":{
                    "detail":{
                        "route": "SalesOrderItemObjectPage"
                    }
                },
                "SalesOrderManage":{
                    "detail":{
                        "route": "SalesOrderManageObjectPage",
                        "parameters":{
                            "key": "{_ReferencedSalesOrder/ID}"
                        }
                    }
                }
            }, // End of navigation
            "sectionLayout": "Tabs"    // Default value: Page. Possible values: Page (all sections are shown on same page) and Tabs (each top-level section is shown in an own tab)
        }
    }
}
```

STEP: 8 — SmartForm column layout and responsive layout settings (manifest.json)

DESCRIPTION: Change default SmartForm column layout (six columns on XL screens) to four columns using objectPageColumns.screenSizeXL, or switch SmartForm from column layout to responsive grid using useColumnLayoutForSmartForm = false.

LANGUAGE: JSON

CODE:
```json
"sap.ui.generic.app": {
        "settings": {
            "objectPageColumns": {
                "screenSizeXL": 4
            }
        },
```

LANGUAGE: JSON

CODE:
```json
"sap.ui.generic.app": {
                              "_version": "1.3.0",
                              "settings": {
                                             "useColumnLayoutForSmartForm": false
                              }
```

STEP: 9 — Additional behavior notes and best practices (no code)

DESCRIPTION: Keep these operational rules and tips when implementing facets and sections:

- UI.CollectionFacet at third level and beyond are ignored.
- Do not use UI.CollectionFacet under UI.Facets if it contains only one UI.ReferenceFacet; use UI.ReferenceFacet directly to avoid rendering issues.
- Do not include commas (,) in section or subsection titles — commas act as delimiters in Fiori elements.
- Icon tab bar: section title is not displayed in content area; Anchor bar: first section title hidden in content area.
- Page layout mode: if a section/subsection contains only a table or chart, the section title is hidden and control title is replaced by the section/subsection title (Tabs mode: applies to subsections only). In OData V2, special logic is not invoked if the section/subsection has multiple controls and at runtime a single visible control appears due to dynamic visibility.
- When the object page contains only one section with one table: ui.table expands to use full page height; sap.m.Table expands to show 20 rows.
- When using a chart or table as a UI.ReferenceFacet, ensure it is the only content (no peer ReferenceFacet) to avoid rendering issues (OData V4).
- For OData V2 additional hierarchy level behavior: a top-level collection facet can contain several reference facets arranged underneath.
- For large tables: consider condensed table layout and MultiSelectionPlugin configuration (see project docs).
- SmartForm: do not include layout or container controls (or views) inside GroupElement — breaks visual layout and accessibility.
- If UI.FieldGroup contains only one UI.MultiLineText property and no other controls, the TextArea label is hidden; provide a meaningful TextArea label for screen reader compatibility.
- Facet annotation label is used twice: header facet and section title.

Use these rules to ensure consistent rendering, stable IDs, and predictable behavior across OData V2 and V4 applications.

fiori-elements-framework
OData V2
OData V4
annotations
UI.Facets
manifest.json
CDS
CAP
ABAP
XML


**TITLE**: Defining Custom Actions for Quick View Cards and Smart Filter Bar

**INTRODUCTION**: This guide explains how to add custom actions (buttons) to quick view cards shown in stack card object streams, and how to add global actions to the Smart Filter Bar. It provides the exact controller/fragment files and manifest.json entries to register press handlers and wire UI fragments to extension controllers.

**TAGS**: fiori-elements-framework, sap.ovp, manifest.json, quick-view, custom-actions, smart-filter-bar, controller-extension, fragment

**STEP**: 1 — Create a custom controller file for quick view actions

**DESCRIPTION**: Create a JavaScript controller file in your project (example name: customConfiguration.controller.js). Define an onCustomActionPress hook that maps the press handler name (string from manifest customActions.press) to the actual handler function implemented in the controller. Implement the press handlers to perform desired actions (for example, open a URL or show a message).

**LANGUAGE**: JavaScript

**CODE**:
```javascript
sap.ui.define([], function () {
    "use strict";
    return {
        /*
        The following Hook function "onCustomActionPress" accepts only one argument name of the press handler as a string and return the press handler function defined in the custom controller.
        */
        onCustomActionPress: function(sCustomAction) {
            if (sCustomAction === "press1") {
                return this.press1;
            } else if (sCustomAction === "press2") {
                return this.press2;
            }
        },
        /*
        The following Press Handler contains the custom actions to be performed on click of the button in quickview action footer.
        */
        press1: function(oEvent) {
            window.open("https://www.google.co.in");
        },
        press2: function(oEvent) {
            window.open("http://www.sap.com/index.html");
        }
    };
});
```

**STEP**: 2 — Register the controller extension in manifest.json

**DESCRIPTION**: In the manifest.json, add your controller extension under the "extends" -> "extensions" -> "sap.ui.controller.Extensions" section so the OVP app will use your custom controller. Use the controllerName fully-qualified module path that points to your custom controller file.

**LANGUAGE**: JSON

**CODE**:
```json
"extends": {
        "extensions": {
             "sap.ui.controller.Extensions": {
                     "sap.ovp.app.Main": {
                                 "controllerName": "my_app.ext.controller.OverViewPageExt"
                      }
              }
        }
}
```

**STEP**: 3 — Define customActions in the stack card objectStreamCardsSettings

**DESCRIPTION**: For each stack card that should show custom quick view footer actions, add the "objectStreamCardsSettings.customActions" array inside the card settings in manifest.json. Each action object must include:
- text (string shown on the button)
- press (name of press handler defined in your controller; mapped via onCustomActionPress)
- position (numeric ordering of actions in the footer)

The example below shows multiple custom actions and the "showFirstActionInFooter" option.

**LANGUAGE**: JSON

**CODE**:
```json
"card007_ProductsOutOfStock": {
  "model": "salesOrder",
  "template": "sap.ovp.cards.stack",
  "settings": {
    "itemText": "{{stackCard_itemText}}",
    "title": "Products Out of Stock",
    "subTitle": "SalesOrderSet Stack Card",
    "requireAppAuthorization": "#Action-toappnavsample",
    "entitySet": "SalesOrderSet",
    "identificationAnnotationPath": "com.sap.vocabularies.UI.v1.Identification,com.sap.vocabularies.UI.v1.Identification#item2",
    "objectStreamCardsSettings": {
      "showFirstActionInFooter": false,
      "customActions": [
        {
          "text": "text1",
          "press": "press1",
          "position": 1
        },
        {
          "text": "text2",
          "press": "press2",
          "position": 10
        },
        {
          "text": "text3",
          "press": "press1",
          "position": 3
        },
        {
          "text": "text4",
          "press": "press2",
          "position": 8
        },
        {
          "text": "text5",
          "press": "press1",
          "position": 5
        },
        {
          "text": "text6",
          "press": "press2",
          "position": 6
        }
      ]
    }
  }
},
```

**STEP**: 4 — Add global actions to the Smart Filter Bar (manifest configuration)

**DESCRIPTION**: To add global actions to the Smart Filter Bar, extend sap.ui5 in manifest.json to:
- Register a controller extension (custom controller path)
- Register view extensions that include fragment references for both filter bar control configuration and global action fragment(s)

Add the following sap.ui5 snippet inside your manifest.json. Ensure the fragmentName and controllerName match the files you will create.

**LANGUAGE**: JSON

**CODE**:
```json
"sap.ui5": {
   "_version": "1.1.0",
       "dependencies": {
         "libs": {
           "sap.ovp": {}
         }
       },
   "models": {
      "i18n": {
         "type": "sap.ui.model.resource.ResourceModel",
         "uri": "i18n/i18n.properties"
      },
      "salesOrder": {
         "dataSource": "salesOrder",
         "settings": {}
      }
       },
       "extends": {
         "extensions": {
           "sap.ui.controllerExtensions": {
             "sap.ovp.app.Main": {
               "controllerName": "sap.ovp.demo.ext.customFilter"
             }
           },
           "sap.ui.viewExtensions": {
             "sap.ovp.app.Main": {
               "SmartFilterBarControlConfigurationExtension|GlobalFilters": {
                 "className": "sap.ui.core.Fragment",
                 "fragmentName": "sap.ovp.demo.ext.customFilter",
                 "type": "XML"
               },
               "SmartFilterBarGlobalActionExtension": {
                 "className": "sap.ui.core.Fragment",
                 "fragmentName": "sap.ovp.demo.ext.customAction",
                 "type": "XML"
               }
             }

           }
         }
       }
   },
```

**STEP**: 5 — Create the fragment for the Smart Filter Bar global action

**DESCRIPTION**: Create an XML fragment (example filename: customAction.fragment.xml) that defines the UI for the global action. The press event name should match the handler implemented in the controller extension.

**LANGUAGE**: XML

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

    <Button text="Action" press="handleCustomAction" type="Transparent"></Button>

</core:FragmentDefinition>
```

**STEP**: 6 — Create the controller extension for the Smart Filter Bar global action

**DESCRIPTION**: Create the controller file (example name: customFilter.controller.js) that implements the event handler referenced by the fragment (handleCustomAction). Use MessageToast or other UI responses per your needs. Ensure the controller module name matches the controllerName used in manifest.json (sap.ovp.demo.ext.customFilter).

**LANGUAGE**: JavaScript

**CODE**:
```javascript
sap.ui.define("sap.ovp.demo.ext.customFilter", [
    "sap/ui/model/Filter",
    "sap/m/MessageToast"
], function (Filter, MessageToast) {
    "use strict";

    // Extension controller for OVP demo app
    return {
        /**
         * This is for Custom Global Action
         */
        handleCustomAction: function() {
            var msg = 'Custom Global Action clicked';
            MessageToast.show(msg);
        }
    };
});
```

fiori-elements-framework sap.ovp manifest.json quick-view custom-actions smart-filter-bar controller-extension fragment


**TITLE**: Defining Custom Actions for Analytical List Page (ALP) — SAP Fiori elements (OData V2)

**INTRODUCTION**: How to declare custom actions for Analytical List Page (ALP) in the app manifest and implement their handlers in controller extensions. Applies to SAP Fiori elements for OData V2. Covers manifest entries (sap.ui.commands, controllerExtensions → sap.ui.generic.app → <EntitySet> → Actions), keyboard shortcuts, getSelectedContexts usage, and invoking back-end actions via the extensionAPI.

**TAGS**: fiori-elements-framework, analytical-list-page, ALP, manifest.json, extensionAPI, custom-actions, OData V2, sap.ui5, controllerExtensions, keyboard-shortcuts

**STEP**: 1 — Where to place definitions

**DESCRIPTION**: Add custom actions in your app's manifest.json under sap.ui5 → extends → extensions. Define:
- sap.ui.commands: keyboard shortcuts (commands mapped to actions).
- sap.ui.controllerExtensions: controller name and under sap.ui.generic.app define the EntitySet and Actions mapping.

Specify the manifest path explicitly: manifest.json → "sap.ui5" → "extends" → "extensions".

**LANGUAGE**: Text

**CODE**:
```text
Place custom actions under manifest.json:
"sap.ui5" -> "extends" -> "extensions" -> {
  "sap.ui.commands": { ... },
  "sap.ui.controllerExtensions": {
    "sap.suite.ui.generic.template.AnalyticalListPage.view.AnalyticalListPage": {
      "controllerName": "my_app.ext.controller.AnalyticalListPageExt",
      "sap.ui.generic.app": {
        "<EntitySet>": {
          "EntitySet": "<EntitySet>",
          "Actions": { ... }
        }
      }
    }
  }
}
```

**STEP**: 2 — Action properties (what each manifest property means)

**DESCRIPTION**: Use the following properties when declaring each Action under an EntitySet. Action names are keys under "Actions".

- <entity set>: EntitySet shown on the ALP (e.g., ZCostCenterCostQuery0020). If multiple views with different entity sets exist, define Actions only for the main entity set.
- <Action 1>, <Action 2>: Action logical names (object keys).
- id: ID used for the action button.
- text: Button text (typically i18n binding).
- press: Handler function name in your custom controller extension.
- global (required): true/false — whether action is global. Default false. If determining is set it takes precedence (renders as global).
- filter: "chart" | "table" | "global" — where the action appears.
- requiresSelection (optional, table toolbar only): true/false — whether action requires selection. Default true.
- determining (optional): true/false — display action in the footer. Default false.
- command: Name of the command mapped to a keyboard shortcut under sap.ui.commands. Note: adding command changes the oEvent parameter passed to the event handler; update handler code if it depends on oEvent.

**LANGUAGE**: Text

**CODE**:
```text
Use properties: id, text, press, global, filter, requiresSelection, determining, command
Define them under: "sap.ui5" -> "extends" -> "extensions" -> "sap.ui.controllerExtensions" -> "...AnalyticalListPage" -> "sap.ui.generic.app" -> "<EntitySet>" -> "Actions"
```

**STEP**: 3 — Sample manifest.json snippet (commands + controllerExtensions + Actions)

**DESCRIPTION**: Copy this manifest fragment into your manifest.json (under sap.ui5). It shows sap.ui.commands mapping and a set of Actions for EntitySet ZCostCenterCostQuery0020. Keep this snippet intact when inserting into your manifest.

**LANGUAGE**: JSON

**CODE**:
```json
"sap.ui5": {
    "_version": "1.1.0",
        "extends": {
        "extensions": {
            "sap.ui.commands": {
                "sap.suite.generic.template.AnalyticalListPage#sap.suite.generic.template.AnalyticalListPage::ZCostCenterCostQuery0020": {
                    "GlobalActionCommand": {
                        "shortcut": "Ctrl+B"
                    }
                }
            },
            "sap.ui.controllerExtensions": {
                "sap.suite.ui.generic.template.AnalyticalListPage.view.AnalyticalListPage": {
                    "controllerName": "my_app.ext.controller.AnalyticalListPageExt",
                    "sap.ui.generic.app": {
                        "ZCostCenterCostQuery0020": {
                            "EntitySet": "ZCostCenterCostQuery0020",
                            "Actions": {
                                "Action A": {
                                    "id": "ActionA",
                                    "text": "{{Action A}}",
                                    "press": "onClickActionA",
                                    "global": true,
                                    "command": "GlobalActionCommand"
                                },
                                "Action B": {
                                    "id": "ActionB_requiresSelection",
                                    "text": "{{Action B}}",
                                    "press": "onClickActionB",
                                    "filter": "table",
                                    "requiresSelection":true
                                }
                                "Action C": {
                                    "id": "ActionC_requiresSelection",
                                    "text": "{{Action C}}",
                                    "press": "onClickActionC",
                                    "filter": "chart",
                                    "requiresSelection":true
                                }
                                "Action D": {
                                    "id": "ActionD",
                                    "text": "{{Action D}}",
                                    "press": "onClickActionD",
                                    "filter": "table"
                                }
                                "Action E": {
                                    "id": "ActionE",
                                    "text": "{{Action E}}",
                                    "press": "onClickActionE",
                                    "filter": "chart"
                                }
                            } //End of Custom Actions
                        } // End of entity type ZCostCenterCostQuery0020
                    }
                } // End of ALP controllerExtensions
            } // End of controllerExternsions
        }
    },
    ...
}
```

**STEP**: 4 — Implement controller extension handlers (sample controller)

**DESCRIPTION**: Implement handler functions referenced by "press" in a controller extension. Use this sample controller as-is. Important: call this.extensionAPI.getSelectedContexts() synchronously (cache results before async dialogs). For chart toolbar buttons, pass the event ID into getSelectedContexts(oEvent.ID).

Place this controller in the path referenced by "controllerName" in manifest (example: my_app/ext/controller/AnalyticalListPageExt.js).

**LANGUAGE**: JavaScript

**CODE**:
```javascript
sap.ui.define([], function () {
    return {
        onBeforeRebindTableExtension: function (oEvent) {
            console.log('onBeforeRebindTableExtension called!');
        },
        onBeforeRebindChartExtension: function (oEvent) {
            console.log('onBeforeRebindChartExtension called!');
        },
        onClickActionA() {
            console.log('Global Action Shortcut Key triggers');
            alert('Button A shows up only in table toolbar and is clicked toolbar!');
        },
        onClickActionB() {
            // The "getSelectedContexts" should be invoked from synchronous code block.
            //
            // The results of "getSelectedContexts" is cached on "aContexts" and
            // passed as a parameter to the callback function "onActionConfirm".
            var aContexts = this.extensionAPI.getSelectedContexts();
            sap.m.MessageBox.confirm("Would you like to perform the action", {
                title: "Confirm",
                actions: [sap.m.MessageBox.Action.OK, sap.m.MessageBox.Action.CANCEL],
                emphasizedAction: sap.m.MessageBox.Action.OK,
                onClose: this.onActionConfirm.bind(this, aContexts)
            });
        },
        onActionConfirm(aContexts, sAction) {
            if (sAction === sap.m.MessageBox.Action.OK) {
                this.extensionAPI.invokeActions("/ActionB", aContexts).then(function () {
                    ///
                });
            }
        },
        onClickActionC() {
            var contexts = this.extensionAPI.getSelectedContexts(oEvent.ID);
            alert('Button C which shows up in chart toolbar only is clicked!');
        },
        onClickActionD() {
            alert('Button D which shows up in table toolbar only is clicked!');
        },
        onClickActionE() {
            alert('Button E which shows up in chart toolbar only is clicked!');
        }
    }
})
```

**STEP**: 5 — Invoke backend actions from controller (invokeActions example)

**DESCRIPTION**: Use extensionAPI.invokeActions to call an OData action/function on the back end. Provide parameters and contexts array. Example shows calling a specific action with parameters.

**LANGUAGE**: JavaScript

**CODE**:
```javascript
onClickActionSTTA_C_SO_SalesOrder_ND1: function(oEvent) {
  var oApi = this.extensionAPI;
  var mParameters = {
        "SalesOrderID": "500000052"
     };
  oApi.invokeActions("STTA_SALES_ORDER_ND_SRV_01/AFF8CCF97ACESave_stta_i_so_salesorder_nd", [], mParameters);
}
```

**STEP**: 6 — Runtime notes & best practices

**DESCRIPTION**: Action-oriented runtime rules to follow when implementing and wiring custom actions:

- Use only the extensionAPI of SAP Fiori elements for integration in controller extensions.
- getSelectedContexts must be called from synchronous code to cache selection before opening async dialogs; store result (aContexts) and pass to confirm callbacks or invokeActions.
- For chart toolbar buttons, call getSelectedContexts(oEvent.ID) to get the chart-specific selection.
- Defining a "command" in manifest maps keyboard shortcut (sap.ui.commands) to the action. When adding command settings to an existing action, the oEvent parameter passed to the event handler may change; update handler code if it relies on oEvent.
- requiresSelection applies only to table toolbar actions; default is true.
- determining=true will render action in the footer; if both determining and global are set, determining takes precedence (renders as global).
- This documentation applies to SAP Fiori elements for OData V2. For OData V4 use extension points (see Adding Custom Actions Using Extension Points).

**LANGUAGE**: Text

**CODE**:
```text
Best practices:
- Call this.extensionAPI.getSelectedContexts() synchronously and cache results before async operations.
- For chart toolbar actions use getSelectedContexts(oEvent.ID).
- Update event handler code if a command mapping changes the oEvent signature.
- Place controller extension file at the path defined in manifest "controllerName".
- Use this.extensionAPI.invokeActions(actionPath, aContexts, mParameters) to call backend actions.
```

fiori-elements-framework
analytical-list-page
ALP
manifest.json
extensionAPI
custom-actions
OData V2
sap.ui5
controllerExtensions
keyboard-shortcuts


**TITLE**: Defining Custom Navigation Parameters for Intent-Based Navigation (OVP / Fiori Elements)

**INTRODUCTION**: This guide shows how to define and return custom URL/navigation parameters when performing intent-based navigation from an SAPUI5/Fiori Elements application (e.g., OVP). Implement the custom parameter functions in a controller extension, register the extension in manifest.json, and reference the function in the card definition to include parameters during navigation.

**TAGS**: fiori-elements-framework, sapui5, ovp, navigation, selection-variant, manifest.json, controller-extension, custom-params

**STEP**: 1 — Implement onCustomParams and custom parameter functions in the controller extension

**DESCRIPTION**: Add an onCustomParams dispatcher in your controller extension which returns a named function that will produce the custom parameters. Implement the returned functions to either build a selectionVariant-style array of filter objects or mutate and return a navigation params object. Use the configuration properties path, operator, value1, value2, sign for selectionVariant entries.

**LANGUAGE**: JavaScript

**CODE**:
```javascript
onCustomParams: function(sCustomParams) {
    if (sCustomParams === "getParameters") {
        return this.getParameters;
    } else if (sCustomParams === "param2") {
        return this.param2;
    }
},
```

Configuration properties for each selectionVariant entry (use exactly these names when building selectionVariant objects):
- path: Defines the property name
- operator: One of EQ, NE, LE, GE, LT, GT, BT, CP
- value1: First value for the operator
- value2: Second value for range operators (e.g., BT). Set to null if unused
- sign: "I" to include, "E" to exclude

Example functions that return selectionVariant-style filters or modify navigation params:

**LANGUAGE**: JavaScript

**CODE**:
```javascript
getParameters: function(oNavigateParams) {
    var aCustomSelectionVariant = [];
    var oCustomSelectionVariant = {
        path: "TaxTarifCode",
        operator: "EQ",
        value1: 5,
        value2: null,
        sign: "I"
    };
    aCustomSelectionVariant.push(oCustomSelectionVariant);
    return aCustomSelectionVariant;
},

param2: function(oNavigateParams) {
    oNavigateParams.TaxTarifCode = '3';
    return oNavigateParams;
}
```

Advanced example: build aSelectionVariant and remove empty filters by returning selectionVariant and ignoreEmptyString (deprecated names shown; see note below about replacements):

**LANGUAGE**: JavaScript

**CODE**:
```javascript
getParameters: function(oNavigateParams,oSelectionVariantParams) {

            // to get the select option property names, make use of this to check what values are available to modify
            var aSelectOptionNames = oSelectionVariantParams.getSelectOptionsPropertyNames();

            var oFilter1 = oSelectionVariantParams.getSelectOption("Filter1");
            var oFilter2 = oSelectionVariantParams.getSelectOption("Filter2");

             ///
                Your logic to extract values from oFilter1 and oFilter2
             ///

             /// logic to remove Filter1 and Filter2
             /// assigning empty values to Filter1 and Filter2, with ignoreEmptyString as true, this will be removed from the Selection Variant

                  var Filter1 = {
                     path: "Filter1",
                     operator: "EQ",
                     value1: "",
                     value2: null,
                     sign: "I"
                 };

                 var Filter2 = {
                     path: "Filter2",
                     operator: "EQ",
                     value1: "",
                     value2: null,
                     sign: "I"
                 };

             /// logic to remove Filter1 and Filter2

             var aCustomSelectionVariant = [];
             var oFilter3 = {
                 path: "Filter3PropertyName",
                 operator: "EQ",
                 value1: "< Value you want to include >",
                 value2: null,
                 sign: "I"
             };
             aCustomSelectionVariant.push(oFilter3);
             aCustomSelectionVariant.push(oFilter2);
             aCustomSelectionVariant.push(oFilter1);
             return {
                 selectionVariant: aCustomSelectionVariant,
                 ignoreEmptyString: true
             };
        },
```

Note: As of SAPUI5 1.54, selectionVariant/ignoreEmptyString are deprecated. Use the replacements:
- selectionVariant -> aSelectionVariant
- ignoreEmptyString -> bIgnoreEmptyString

Return shape (preferred current names):
- return { aSelectionVariant: <array-of-filter-objects>, bIgnoreEmptyString: true/false }

**STEP**: 2 — Register the controller extension in manifest.json

**DESCRIPTION**: Add a controller extension entry under "sap.ui.controllerExtensions" in manifest.json and set controllerName to your extension controller path. If a controllerExtensions block already exists, add the new extension within the same file.

**LANGUAGE**: JSON

**CODE**:
```json
"extends": {
    "extensions": {
        "sap.ui.controllerExtensions": {
            "sap.ovp.app.Main": {
                "controllerName": "my_app.ext.controller.OverViewPageExt"
            }
        }
    }
}
```

**STEP**: 3 — Reference the custom parameter function in the card definition (manifest.json)

**DESCRIPTION**: In the card configuration in manifest.json, set the settings.customParams value to the name of the function returned by onCustomParams (the key passed to onCustomParams, e.g., "getParameters" or "param2"). The framework will call onCustomParams with that name and expect the returned function to provide parameters.

**LANGUAGE**: JSON

**CODE**:
```json
"card002_ReorderSoon": {
  "model": "purchaseOrder",
  "template": "sap.ovp.cards.list",
  "settings": {
    "title": "reorder Soon",
    "subTitle": "Less than 10 in stock",
    "listType": "condensed",
    "entitySet": "PurchaseSet",
    "customParams": "<function-name>"    // Depending on the logic you define in step 1, input the function name.
    ...
    ...
```

**STEP**: 4 — Implementation notes and checklist

**DESCRIPTION**: Quick actionable checklist for implementing custom parameters:
- Implement onCustomParams in your controller extension and return function references by name.
- Use aSelectionVariant / bIgnoreEmptyString (preferred) or selectionVariant / ignoreEmptyString (deprecated) in returned object shapes.
- For selectionVariant entries, produce objects with path, operator, value1, value2, sign.
- Register the controller extension in manifest.json under sap.ui.controllerExtensions and point controllerName to your extension controller.
- In the card definition, set settings.customParams to the function name that onCustomParams recognizes.

**LANGUAGE**: Plain text

**CODE**:
```text
- Return either:
  - an array of selectionVariant objects (legacy), or
  - { aSelectionVariant: [ ... ], bIgnoreEmptyString: true } (preferred)
  - or mutate oNavigateParams and return it for simple URL param additions.

- Keep function names consistent between:
  - the string passed as customParams in the card definition,
  - the onCustomParams dispatcher checks, and
  - the actual function implemented on the controller extension.
```

fiori-elements-framework sapui5 ovp navigation selection-variant manifest.json controller-extension custom-params


**TITLE**: Defining Determining Actions for Object Page Footer (Fiori Elements)

**INTRODUCTION**: Add determining action buttons to the object page footer in edit mode by annotating UI.DataFieldForAction with the Determining property. Determining actions appear in the object page footer only when Determining = true and must be hidden in display mode via a path-based UI.Hidden annotation. This document provides ready-to-use annotation examples for XML, ABAP CDS, and CAP CDS.

**TAGS**: fiori-elements-framework, object-page, determining-actions, annotations, UI.Identification, DataFieldForAction, CAP, ABAP, XML

STEP: Behavior and constraints

DESCRIPTION:
- Determining actions are used to trigger actions directly using the page context on an object page.
- Determining actions appear in the object page footer only when in edit mode and only if the DataFieldForAction has Determining set to true.
- If Determining is absent or false, the action will appear in the header (or not in the footer).
- Footer actions must not be available in display mode — add a path-based UI.Hidden annotation to the action to hide it when the page is not in edit mode.
- Use the UI.Identification vocabulary term to define actions for the object page.

LANGUAGE: None

CODE:
```text
Notes:
- Determining actions appear in the footer only in edit mode.
- Use UI.Identification to define object page actions.
- Ensure you add a path-based value to UI.Hidden for the action so it is not available in display mode.
- Image reference (optional): images/ObjectPage_DeterminingAction_5dc52f1.jpg
```

STEP: XML Annotation example

DESCRIPTION: Use the UI.Identification annotation to define DataFieldForAction entries. Set Determining="true" on the DataFieldForAction record you want placed in the footer (edit mode). The example below shows two action records; the second has Determining set and will appear in the footer.

LANGUAGE: XML

CODE:
```xml
<Annotation Term="UI.Identification">
    <Collection>
       <Record Type="UI.DataFieldForAction">
          <PropertyValue Property="Label" String="CWP"/>
          <PropertyValue Property="Action"
             String="STTA_PROD_MAN.STTA_PROD_MAN_Entities/
             STTA_C_MP_ProductCopywithparams"/>
       </Record>
       <Record Type="UI.DataFieldForAction">
          <PropertyValue Property="Label" String="Copy"/>
          <PropertyValue Property="Action"
             String="STTA_PROD_MAN.STTA_PROD_MAN_Entities/STTA_C_MP_ProductCopy"/>
          <PropertyValue Property="Determining" Bool="true"/>
       </Record>
    </Collection>
</Annotation>
```

STEP: ABAP CDS Annotation example

DESCRIPTION: Equivalent ABAP CDS annotation using @UI.identification. The determining action is declared with determining: true so it will be rendered in the footer in edit mode.

LANGUAGE: ABAP CDS

CODE:
```
@UI.identification: [
  {
    label: 'CWP',
    dataAction: 'PUSHDOWN: STTA_C_MP_ProductCopywithparams ',
    type: #FOR_ACTION,
    position: 1
  },
  {
    label: 'Copy',
    dataAction: 'PUSHDOWN: STTA_C_MP_ProductCopy',
    type: #FOR_ACTION,
    determining: true,
    position: 2
  }
]
product;
```

STEP: CAP CDS Annotation example

DESCRIPTION: CAP CDS uses UI.Identification with UI.DataFieldForAction records. Set Determining : true on the record to place the action in the footer (edit mode).

LANGUAGE: CAP CDS

CODE:
```
UI.Identification : [
    {
        $Type : 'UI.DataFieldForAction',
        Label : 'CWP',
        Action : 'STTA_PROD_MAN.STTA_PROD_MAN_Entities/
        STTA_C_MP_ProductCopywithparams'
    },
    {
        $Type : 'UI.DataFieldForAction',
        Label : 'Copy',
        Action : 'STTA_PROD_MAN.STTA_PROD_MAN_Entities/STTA_C_MP_ProductCopy',
        Determining : true
    }
]
```

STEP: Hide footer action in display mode

DESCRIPTION: Footer actions must not be available in display mode. Add a path-based UI.Hidden annotation on the action record so the action is hidden when the page is not in edit mode. Implement the UI.Hidden annotation according to your annotation format (XML, ABAP CDS, CAP CDS) and the property/path that represents the page edit mode in your service/UI model.

LANGUAGE: Guidance

CODE:
```text
Implement UI.Hidden as a path-based annotation on the same DataFieldForAction entry:
- XML: add a PropertyValue with Property="Hidden" and Path="..." inside the Record.
- ABAP CDS: add hidden: 'Path: <YourEditModeFlag>' or equivalent in the @UI annotation.
- CAP CDS: add Hidden : { Path : '<YourEditModeFlag>' } in the UI.DataFieldForAction record.

Replace <YourEditModeFlag> with the path/property from your service that indicates edit/display mode.
```

STEP: Related information

DESCRIPTION: Refer to related documentation for additional ways to display actions on the object page and details about action placement and behavior.

LANGUAGE: None

CODE:
```text
Related doc:
- Displaying Actions on the Object Page (displaying-actions-on-the-object-page-f65e8b1.md)
```

fiori-elements-framework object-page determining-actions annotations UI.Identification DataFieldForAction CAP ABAP XML


**TITLE**: Defining Determining Actions in List Reports (SAP Fiori elements, OData V2)

**INTRODUCTION**: Use UI annotation UI.LineItem to add determining action buttons to the footer of a List Report smart table in SAP Fiori elements (OData V2). Determining actions use the table context to either call backend OData operations or trigger intent-based navigation. Note: this feature is deprecated and supported only for compatibility; avoid using it for new designs.

**TAGS**: fiori-elements, odata-v2, annotations, ui.lineitem, datafieldforaction, intentbasednavigation, determining-actions, deprecated

STEP: 1 — Applicability and recommendation
DESCRIPTION: Confirm applicability and preferred usage. This feature is supported only in SAP Fiori elements for OData V2 and is deprecated. Use only for compatibility; prefer alternative UI patterns for new implementations.
LANGUAGE: Text
CODE:
```text
Note: This topic is only applicable to SAP Fiori elements for OData V2.
Recommendation: This feature is deprecated. SAP Fiori elements supports it only for compatibility reasons. Avoid using determining actions in list reports for new designs.
```

STEP: 2 — Determining action types
DESCRIPTION: There are two determining action types. Choose the appropriate complex type based on the action behavior required.
LANGUAGE: Text
CODE:
```text
- DataFieldForAction: triggers a back-end call through the OData service (Function, FunctionImport, Action, or ActionImport).
- DataFieldForIntentBasedNavigation: triggers intent-based navigation (semantic object + action).
```

STEP: 3 — Add determining actions to the List Report footer
DESCRIPTION: Add determining actions by defining UI.LineItem annotations and setting the Determining property to true on the relevant DataField record(s). Determining=true causes buttons to render in the smart table footer. If Determining is omitted or false, the action appears in the smart table toolbar.
LANGUAGE: XML
CODE:
```xml
<!-- File: Annotations (e.g., annotations.xml) -->
<Annotation Term="UI.LineItem">
   <Collection>
      <Record Type="UI.DataFieldForAction">
         <PropertyValue Property="Label" String="Copy with new Supplier"/>
         <PropertyValue Property="Action"
           String="STTA_PROD_MAN.STTA_PROD_MAN_Entities/
            STTA_C_MP_ProductCopywithparams"/>
         <PropertyValue Property="InvocationGrouping"
            EnumMember="UI.OperationGroupingType/Isolated"/>
      </Record>
      <Record Type="UI.DataFieldForAction">
         <PropertyValue Property="Label" String="Copy"/>
         <PropertyValue Property="Action"
            String="STTA_PROD_MAN.STTA_PROD_MAN_Entities/STTA_C_MP_ProductCopy"/>
         <PropertyValue Property="Determining" Bool="true"/>
         <PropertyValue Property="InvocationGrouping"
            EnumMember="UI.OperationGroupingType/Isolated"/>
      </Record>
      <Record Type="UI.DataFieldForIntentBasedNavigation">
         <PropertyValue Property="Label" String="Manage Products (ST)"/>
         <PropertyValue Property="SemanticObject" String="EPMProduct"/>
         <PropertyValue Property="Action" String="manage_st"/>
         <PropertyValue Property="Determining" Bool="true"/>
      </Record>
   </Collection>
</Annotation>
```

STEP: 4 — Explain sample behavior
DESCRIPTION: Interpret the example: first DataFieldForAction has no Determining property -> appears in smart table toolbar. The second DataFieldForAction and the DataFieldForIntentBasedNavigation include Determining=true -> these action buttons appear in the table footer.
LANGUAGE: Text
CODE:
```text
- Record 1 (DataFieldForAction) has no Determining -> action appears in the smart table toolbar.
- Record 2 (DataFieldForAction) has Determining="true" -> action appears in the smart table footer.
- Record 3 (DataFieldForIntentBasedNavigation) has Determining="true" -> navigation action appears in the footer.
```

STEP: 5 — Additional details and assets
DESCRIPTION: Use the UI.LineItem vocabulary term to define columns for the smart table. Reference example image for expected footer rendering (preserve path if needed).
LANGUAGE: Text
CODE:
```text
Note: The UI.LineItem vocabulary term defines the columns for the smart table.
Example image (reference): images/Determining_Action_in_List_Report_5adb885.png
```

fiori-elements odata-v2 annotations ui.lineitem datafieldforaction intentbasednavigation determining-actions deprecated


**TITLE**: Defining Filter Facets (UI.FilterFacets) for Fiori Elements

**INTRODUCTION**: Use UI.FilterFacets annotations to display filter groups in filter bars. This document shows how to add ReferenceFacet entries that point to UI.FieldGroup qualifiers and how filter fields are grouped and displayed. Includes examples for XML annotations, ABAP CDS, and CAP CDS.

**TAGS**: fiori-elements-framework, UI.FilterFacets, ReferenceFacet, FieldGroup, UI.SelectionFields, OData V2, ABAP CDS, CAP CDS, XML, annotations

STEP: Add a ReferenceFacet via XML annotation on the target entity type

DESCRIPTION: Add a UI.FilterFacets annotation to the target entity type and include a UI.ReferenceFacet that targets a UI.FieldGroup qualifier. The Target property uses AnnotationPath to reference the FieldGroup qualifier (e.g., @UI.FieldGroup#MyFilterGroup).

LANGUAGE: XML

CODE:
```xml
<Annotations Target="STTA_PROD_MAN.STTA_C_MP_SupplierType">
   <Annotation Term="UI.FilterFacets">
      <Collection>
            <Record Type="UI.ReferenceFacet">
                <PropertyValue Property="Target" AnnotationPath="@UI.FieldGroup#MyFilterGroup"/>
            </Record>
      </Collection>
   </Annotation>
</Annotations>
```

STEP: Add a ReferenceFacet via ABAP CDS annotation

DESCRIPTION: In ABAP CDS, annotate the view with @UI.Facet entries. Use type #FIELDGROUP_REFERENCE, set targetQualifier to the FieldGroup qualifier and set purpose to #FILTER.

LANGUAGE: ABAP CDS

CODE:
```abap
annotate view STTA_C_MP_SUPPLIERTYPE with {
@UI.Facet: [
  {
    targetQualifier: 'MyFilterGroup',
    type: #FIELDGROUP_REFERENCE,
    purpose: #FILTER
  }
]
Supplier;
}
```

STEP: Add a ReferenceFacet via CAP CDS annotation

DESCRIPTION: In CAP CDS, set @UI.FilterFacets with a collection entry typed as 'UI.ReferenceFacet' and provide the Target path to the FieldGroup qualifier (example uses an association path).

LANGUAGE: CAPCDS

CODE:
```cds
@UI.FilterFacets                                    : [
    {
        $Type             : 'UI.ReferenceFacet',
        Target            : '_SoldToParty/@UI.FieldGroup#MyFilterGroup'
    }
]
```

STEP: Default visibility and grouping behavior (applies to OData V2 only)

DESCRIPTION: By default only UI.SelectionFields and mandatory filters appear directly in the filter bar. Other filters appear in the Adapt Filters dialog and are grouped as follows. Note the restriction: this feature is only available in SAP Fiori elements for OData V2.

LANGUAGE: TEXT

CODE:
```
- Basic Group:
  - Includes all fields listed in UI.SelectionFields.
  - Also includes fields that are part of UI.FieldGroup with qualifier "_BASIC" under the UI.FilterFacets structure.

- Field Group:
  - Includes fields that are part of a UI.FieldGroup (via a FieldGroup qualifier referenced by a ReferenceFacet)
    but are NOT listed in UI.SelectionFields.

- Entity Type Name Group:
  - Fields not in UI.SelectionFields or any UI.FieldGroup are grouped under a group named <EntityTypeName>.
  - If multiple entity types are present, multiple <EntityTypeName> groups are created.
```

STEP: Define a FieldGroup via XML annotation

DESCRIPTION: Use UI.FieldGroup with a Qualifier to list DataFields (UI.DataField) and provide a Label. Reference this FieldGroup via FilterFacets ReferenceFacet Target with the qualifier.

LANGUAGE: XML

CODE:
```xml
<Annotation Term="UI.FieldGroup" Qualifier="Group_Name">
    <Record>
        <PropertyValue Property="Data">
            <Collection>
                <Record Type="UI.DataField">
                    <PropertyValue Property="Value" Path="Name"/>
                </Record>
            </Collection>
        </PropertyValue>
        <PropertyValue Property="Label" String="Group Name"/>
    </Record>
</Annotation>
```

STEP: Define a FieldGroup via ABAP CDS annotation

DESCRIPTION: In ABAP CDS, declare a @UI.fieldGroup annotation with qualifier and label, then list the property in the view/entity. This FieldGroup can be referenced by a ReferenceFacet in UI.FilterFacets.

LANGUAGE: ABAP CDS

CODE:
```abap
@UI.fieldGroup: [{ qualifier: 'Group Name', groupLabel: 'Group Name' }]
PROPERTY_NAME;
```

STEP: Define a FieldGroup via CAP CDS annotation

DESCRIPTION: In CAP CDS, create a UI.FieldGroup with a qualifier, include Data entries of type UI.DataField that reference properties, and set the Label. Reference the qualifier from UI.FilterFacets ReferenceFacet.

LANGUAGE: CAPCDS

CODE:
```cds
UI.FieldGroup #GroupName : {
    Data : [
        {
            $Type : 'UI.DataField',
            Value : PropertyName
        }
    ],
    Label : 'Group Name'
}
```

fiori-elements-framework
UI.FilterFacets
ReferenceFacet
FieldGroup
UI.SelectionFields
OData V2
ABAP CDS
CAP CDS
XML
annotations


**TITLE**: Defining Line Items

**INTRODUCTION**: This guide shows how to define table line items for SAP Fiori Elements using UI.LineItem annotations. Includes exact examples for XML (OData annotations), ABAP CDS, and CAP CDS. Use these annotations to control which properties appear as table columns, their order, and importance (visibility/responsiveness).

**TAGS**: fiori-elements-framework, UI.LineItem, LineItem, annotations, CDS, CAP, ABAP, XML, OData

**STEP**: 1 — XML Annotation (OData / EDMX annotations)

**DESCRIPTION**: Add a UI.LineItem annotation to the entity or EntitySet annotations in your OData service annotations file. Each Record of Type="UI.DataField" specifies a column via PropertyValue Property="Value" Path="...". Use UI.Importance to mark important/high-priority columns.

**LANGUAGE**: XML

**CODE**:
```xml
...
<Annotation Term="UI.LineItem">
  <Collection>
    <Record Type="UI.DataField">
      <PropertyValue Property="Value" Path="Product"/>
      <Annotation Term="UI.Importance" EnumMember="UI.ImportanceType/High"/>
    </Record>
    <Record Type="UI.DataField">
      <PropertyValue Property="Value" Path="ProductCategory"/>
      <Annotation Term="UI.Importance" EnumMember="UI.ImportanceType/High"/>
    </Record>
    <Record Type="UI.DataField">
      <PropertyValue Property="Value" Path="Supplier"/>
      <Annotation Term="UI.Importance" EnumMember="UI.ImportanceType/High"/>
    </Record>
  </Collection>
</Annotation>
```

**STEP**: 2 — ABAP CDS Annotation

**DESCRIPTION**: Annotate CDS entities or fields with @UI.lineItem to declare table columns. Specify properties: value (property name), importance (#HIGH/#MEDIUM/#LOW), type (e.g., #STANDARD), and position to set ordering. Place the annotation where appropriate (on the field or after the field declaration).

**LANGUAGE**: ABAP CDS

**CODE**:
```

@UI.lineItem: [
  {
    importance: #HIGH,
    value: 'PRODUCT',
    type: #STANDARD,
    position: 1
  }
]
PRODUCT;

@UI.lineItem: [
  {
    importance: #HIGH,
    value: 'PRODUCTCATEGORY',
    type: #STANDARD,
    position: 2
  }
]
PRODUCTCATEGORY;

@UI.lineItem: [
  {
    importance: #HIGH,
    value: 'SUPPLIER',
    type: #STANDARD,
    position: 3
  }
]
SUPPLIER;
```

**STEP**: 3 — CAP CDS Annotation

**DESCRIPTION**: In CAP (Core Data Services) use the UI.LineItem annotation array on the entity to list UI.DataField entries. Use Value to reference the property and ![@UI.Importance] to set importance. This controls which properties are shown as columns and their responsiveness behavior.

**LANGUAGE**: CDS (CAP)

**CODE**:
```

UI.LineItem : [
    {
        $Type : 'UI.DataField',
        Value : Product,
        ![@UI.Importance] : #High
    },
    {
        $Type : 'UI.DataField',
        Value : ProductCategory,
        ![@UI.Importance] : #High
    },
    {
        $Type : 'UI.DataField',
        Value : Supplier,
        ![@UI.Importance] : #High
    }
]

```

**STEP**: 4 — Determining Column Names, Order, and Responsiveness

**DESCRIPTION**: Implementation notes to apply when writing or generating code:
- Column names derive from the property referenced by Value (CAP/CDS) or PropertyValue Path (XML). Use the exact property name used in the entity/model.
- Order:
  - In XML and CAP, the sequence of entries in UI.LineItem determines column order.
  - In ABAP CDS, use the position attribute to explicitly set column order.
- Visibility/responsiveness:
  - Use UI.Importance / @UI.lineItem importance settings (#High/#Medium/#Low) to influence responsive behavior and which columns collapse on smaller screens.
- Field types: set type (e.g., #STANDARD) where supported (ABAP CDS) to declare rendering expectations.

**LANGUAGE**: Plain text

**CODE**:
```text
- Column source: Value / PropertyValue Path -> property in entity
- Order control: sequence (XML/CAP) or position (ABAP CDS)
- Importance: UI.Importance or @UI.lineItem.importance -> influences responsive hiding
- Use UI.DataField records for simple property columns
```

**STEP**: 5 — Related Links

**DESCRIPTION**: References for related capabilities (actions, responsiveness) to include when extending line items or tables.

**LANGUAGE**: Markdown links / file paths

**CODE**:
```text
- Adding actions for line items: adding-actions-to-tables-b623e0b.md
- Responsiveness options in tables (example): responsiveness-options-example-69efbe7.md
```

Defining Line Items

fiori-elements-framework UI.LineItem LineItem annotations CDS CAP ABAP XML OData


**TITLE**: Defining Multiple Chart Configurations (UI.Chart with Qualifier)

**INTRODUCTION**: Show how to define multiple chart configurations for the same dataset by creating multiple UI.Chart annotations with different qualifiers, and how to select a specific chart configuration in a Fiori Elements page (List Report or Object Page). Use cases: show different chart types or measures for different views/sections while reusing the same entity set and data source.

**TAGS**: fiori-elements-framework, UI.Chart, qualifier, annotations, OData, CDS, manifest

**STEP**: 1 — Create multiple UI.Chart annotations in OData V4 annotation XML

**DESCRIPTION**: Add multiple UI.Chart annotations on the same target entity, each with a unique Qualifier. Each Annotation Record defines Title, ChartType, Dimensions and Measures. The Qualifier differentiates chart configurations so the runtime can pick the correct chart.

**LANGUAGE**: XML

**CODE**:
```xml
<!-- annotations.xml -->
<Annotations Target="MyService.SalesEntityType">
  <!-- Chart configuration 1: monthly column chart -->
  <Annotation Term="UI.Chart" Qualifier="byMonth">
    <Record>
      <PropertyValue Property="Title" String="Sales by Month"/>
      <PropertyValue Property="ChartType" EnumMember="UI.ChartType/Column"/>
      <PropertyValue Property="Dimensions">
        <Collection>
          <PropertyPath>Month</PropertyPath>
        </Collection>
      </PropertyValue>
      <PropertyValue Property="Measures">
        <Collection>
          <PropertyPath>TotalSales</PropertyPath>
        </Collection>
      </PropertyValue>
    </Record>
  </Annotation>

  <!-- Chart configuration 2: regional donut chart -->
  <Annotation Term="UI.Chart" Qualifier="byRegion">
    <Record>
      <PropertyValue Property="Title" String="Sales by Region"/>
      <PropertyValue Property="ChartType" EnumMember="UI.ChartType/Donut"/>
      <PropertyValue Property="Dimensions">
        <Collection>
          <PropertyPath>Region</PropertyPath>
        </Collection>
      </PropertyValue>
      <PropertyValue Property="Measures">
        <Collection>
          <PropertyPath>TotalSales</PropertyPath>
        </Collection>
      </PropertyValue>
    </Record>
  </Annotation>
</Annotations>
```

**STEP**: 2 — Define multiple chart qualifiers in ABAP CDS (alternative approach)

**DESCRIPTION**: In ABAP CDS views you can annotate the entity/view with multiple UI.Chart entries (as an array) where each entry uses a qualifier. This produces multiple UI.Chart annotations in the generated OData metadata.

**LANGUAGE**: CDS

**CODE**:
```abap
@AbapCatalog.sqlViewName: 'ZV_SALES'
@EndUserText.label: 'Sales View'
define view ZI_Sales as select from sepm_sales
{
  key SalesID,
  Month,
  Region,
  TotalSales,

  @UI.chart: [
    {
      qualifier: 'byMonth',
      title: 'Sales by Month',
      chartType: #Column,
      dimensions: ['Month'],
      measures: ['TotalSales']
    },
    {
      qualifier: 'byRegion',
      title: 'Sales by Region',
      chartType: #Donut,
      dimensions: ['Region'],
      measures: ['TotalSales']
    }
  ]
}
```

**STEP**: 3 — Select a qualified chart configuration in the app manifest (List Report / Object Page)

**DESCRIPTION**: Configure the Fiori Elements page to use a specific chart qualifier by setting the chartQualifier property (or the equivalent page-level setting) in the manifest. Use the same entitySet but point the page’s chart configuration to the desired qualifier to display the corresponding chart.

**LANGUAGE**: JSON

**CODE**:
```json
{
  "sap.ui.generic.app": {
    "pages": [
      {
        "entitySet": "Sales",
        "component": {
          "name": "sap.suite.ui.generic.template.ListReport",
          "settings": {
            "chartQualifier": "byMonth"   /* uses the UI.Chart qualifier "byMonth" */
          }
        }
      },
      {
        "entitySet": "Sales",
        "component": {
          "name": "sap.suite.ui.generic.template.ObjectPage",
          "settings": {
            "sections": {
              "OverviewSection": {
                "chartQualifier": "byRegion" /* use a different qualifier in another section */
              }
            }
          }
        }
      }
    ]
  }
}
```

**STEP**: 4 — Notes and best practices

**DESCRIPTION**: Key technical notes to follow:
- Use unique Qualifier values for each UI.Chart annotation on the same entity.
- The runtime picks a chart by matching the chartQualifier configured for the page/section to the Qualifier of a UI.Chart annotation.
- Keep chart dimensions and measures consistent with entity properties (PropertyPath values).
- You can define charts in OData annotation XML or generate them from ABAP CDS annotations—both approaches produce UI.Chart annotations with qualifiers in the service metadata.
- For live examples and detailed property names, consult the SAP Fiori documentation: Building Blocks - Chart - Usage with Qualifier (https://ui5.sap.com/test-resources/sap/fe/core/fpmExplorer/index.html#/buildingBlocks/chart/chartQualifier).

fiori-elements-framework UI.Chart qualifier annotations OData CDS manifest