**TITLE**: Set table header text and visibility in Fiori Elements (manifest.json)

**INTRODUCTION**: This document shows how to set or hide a table header for Fiori Elements lists/tables by configuring controlConfiguration.tableSettings in manifest.json. Use these settings to override header text and header visibility per list/table or per LineItem annotation.

**TAGS**: fiori-elements-framework, manifest.json, table header, headerVisible, controlConfiguration, LineItem, tableSettings, HeaderInfo, com.sap.vocabularies.UI.v1

STEP: 1 — Source of the table header
DESCRIPTION: The table header is defined by the UI annotation com.sap.vocabularies.UI.v1.HeaderInfo (TypeNamePlural) in the service/annotations. You can read/define header text via that annotation. In Fiori Elements you can override or control the header text and its visibility from the app manifest using controlConfiguration.tableSettings.
LANGUAGE: JSON
CODE:
```json
// Annotation source (conceptual)
// Header in OData/annotations: com.sap.vocabularies.UI.v1.HeaderInfo TypeNamePlural
// Often defined in the service annotations; manifest.json can override/replace visibility/text.
```

STEP: 2 — Configure header text and visibility in manifest.json
DESCRIPTION: Add settings under sap.ui5.routing.targets.<TargetName>.options.settings.controlConfiguration.<AnnotationPath>.tableSettings. Use:
- header: string value to display as the table header
- headerVisible: boolean to show or hide the header in the UI

Place this JSON inside your application's manifest.json. The example below shows:
- a generic LineItem table configuration for SalesOrderManageList
- per-entityset LineItem configurations for the Object Page target (overrides for _Partner and _Item)
LANGUAGE: JSON
CODE:
```json
{
	"sap.ui5": {
		"routing": {
			"targets": {
				"SalesOrderManageList": {
					"options": {
						"settings": {
							"controlConfiguration": {
								"@com.sap.vocabularies.UI.v1.LineItem": {
									"tableSettings": {
										"header": "Another header",
										"headerVisible": true
									}
								}
							}
						}
					}
				},
				"SalesOrderManageObjectPage": {
					"options": {
						"settings": {
							"controlConfiguration": {
								"_Partner/@com.sap.vocabularies.UI.v1.LineItem": {
									"tableSettings": {
										"header": "Another header for the Partners",
										"headerVisible": true
									}
								},
								"_Item/@com.sap.vocabularies.UI.v1.LineItem": {
									"tableSettings": {
										"headerVisible": false
									}
								}
							}
						}
					}
				}
			}
		}
	}
}
```

fiori-elements-framework
manifest.json
table header
headerVisible
controlConfiguration
LineItem
tableSettings
HeaderInfo
com.sap.vocabularies.UI.v1


**TITLE**: Configure Table Type and Table Settings in manifest.json and Annotations

**INTRODUCTION**: This guide shows how to control which table type (ResponsiveTable, GridTable, AnalyticalTable, TreeTable) is rendered in SAP Fiori elements list report and object pages by configuring manifest.json and using OData annotations. It includes device/service selection logic (OData V2/V4), popin layout configuration for responsive tables, analytical-service annotations and aggregation settings, tree-table activation, and row count controls. Use the exact manifest and annotation snippets below when implementing.

**TAGS**: manifest.json, tableSettings, tableTypes, ResponsiveTable, GridTable, AnalyticalTable, TreeTable, popinLayout, aggregation, @Aggregation.ApplySupported, ODataV2, ODataV4, sap.fe, controlConfiguration, manifest

STEP: Available Table Types
DESCRIPTION: Use one of these values in tableSettings.type to select the rendered control.
LANGUAGE: JSON
CODE:
```json
{
  "tableSettings": {
    "type": "ResponsiveTable | GridTable | AnalyticalTable | TreeTable"
  }
}
```

STEP: Selection Logic — OData V2 & OData V4 (Summary)
DESCRIPTION: Implement selection fallback and automatic selection rules per runtime and service type:
- OData V2:
  - If manifest specifies analytical but entitySet lacks analytical capabilities → use GridTable as fallback.
  - If no type in manifest: smartphone/tablet → ResponsiveTable; desktop → analytical services → AnalyticalTable, otherwise ResponsiveTable.
- OData V4:
  - If manifest specifies analytical but entitySet lacks analytical capabilities → show empty table.
  - If no type in manifest → choose automatically:
    - Analytical services with @Aggregation.ApplySupported and required transformations → AnalyticalTable
    - Hierarchical services with @Aggregation.RecursiveHierarchy and @Hierarchy.RecursiveHierarchy with shared qualifier → TreeTable
    - Otherwise → ResponsiveTable
- Restrictions:
  - Grid, Tree, Analytical tables do not support multi-line content columns (FieldGroup, multi-line text).
LANGUAGE: text
CODE:
```
OData V2 and V4 selection rules and restrictions summarized:
- V2: Analytical fallback -> GridTable; device/service defaults apply.
- V4: Analytical specified w/o support -> empty table; otherwise auto-select based on annotations.
- Grid/Tree/Analytical: no multi-line content support.
```

STEP: Set Table Type for List Report (manifest.json sap.ui.generic.app)
DESCRIPTION: Add tableSettings.type under sap.ui.generic.app > pages to enforce a GridTable on the list report page.
LANGUAGE: JavaScript
CODE:
```js
"sap.ui.generic.app": {
    "pages": [
        {
            "entitySet": "Zfarvd_Bs_Hd_Bo",
            "component": {
                "name": "sap.suite.ui.generic.template.ListReport",
                "list": true,
                "settings": {
                    "tableSettings": {
                        "type": "GridTable"
                    }
                }
            }
        }
    ]
}

```

STEP: Set Table Type for Object Page Section (manifest.json sap.ui.generic.app)
DESCRIPTION: Define tableSettings.type inside the object page section to use a TreeTable for a section that navigates to ProductText.
LANGUAGE: JavaScript
CODE:
```js
"sap.ui.generic.app": {
    "pages": [
        {
            "entitySet": "STTA_C_MP_Product",
            "component": {
                "name": "sap.suite.ui.generic.template.ListReport",
                "list": true
            },
            "pages": [
                {
                    "entitySet": "STTA_C_MP_Product",
                    "component": {
                        "name": "sap.suite.ui.generic.template.ObjectPage",
                        "settings": {
                            "sections": {
                                "to_ProductText::com.sap.vocabularies.UI.v1.LineItem": {
                                    "navigationProperty": "to_ProductText",
                                    "entitySet": "STTA_C_MP_ProductText",
                                    "tableSettings": {
                                        "type": "TreeTable"
                                    }
                                }
                            }
                        }
                    }
                }
            ]
        }
    ]
}
```

STEP: tableSettings in Object Page vs Sections (precedence)
DESCRIPTION: Use tableSettings at section level to override the object page-level setting. Example: ObjectPage default ResponsiveTable overridden to GridTable in a section.
LANGUAGE: JavaScript
CODE:
```js
"pages": [
    {
        "entitySet": "STTA_C_MP_Product",
        "component": {
            "name": "sap.suite.ui.generic.template.ObjectPage",
            "settings": {
                "showRelatedApps": true,
                "tableSettings": {
                    "type": "ResponsiveTable"
                },
                "sections": {
                    "to_ProductText::com.sap.vocabularies.UI.v1.LineItem": {
                        "navigationProperty": "to_ProductText",
                        "entitySet": "STTA_C_MP_ProductText",
                        "tableSettings": {
                            "type": "GridTable"
                        }
                    }
                }
            }
        }
    }
]
```

STEP: Configure Table Type in sap.fe routing targets (OData V4 List Report)
DESCRIPTION: For SAP Fiori elements V4, set controlConfiguration.tableSettings inside sap.ui5 > routing > targets options to select a ResponsiveTable for the list report page.
LANGUAGE: JSON
CODE:
```
"targets": {
    "SalesOrderManageList": {
        "type": "Component",
        "id": "SalesOrderManageList",
        "name": "sap.fe.templates.ListReport",
        "options": {
            "settings": {
                "controlConfiguration": {
                    "@com.sap.vocabularies.UI.v1.LineItem": {
                        "tableSettings": {
                            "type": "ResponsiveTable"
                        }
                    }
                }
                ...
            }
        }
    }
}
```

STEP: Configure Table Type in sap.fe routing targets (OData V4 Object Page)
DESCRIPTION: For object page in sap.ui5 routing target, set controlConfiguration.tableSettings to GridTable for the object page LineItem.
LANGUAGE: JSON
CODE:
```
"targets": {
    "SalesOrderManageObjectPage": {
        "type": "Component",
        "id": "SalesOrderManageObjectPage",
        "name": "sap.fe.templates.ObjectPage",
        "options": {
            "settings": {
                "controlConfiguration": {
                    "_Item/@com.sap.vocabularies.UI.v1.LineItem": {
                        "tableSettings": {
                            "type": "GridTable"
                        }
                    }
                }
            }
        }
    }
}
```

STEP: Configure Popin Layout for ResponsiveTable (table-level)
DESCRIPTION: Set popinLayout in tableSettings for a responsive table (supports Block, GridLarge, GridSmall). This example sets GridSmall for the LineItem control.
LANGUAGE: JSON
CODE:
```
"controlConfiguration": {
    "@com.sap.vocabularies.UI.v1.LineItem": {
        "tableSettings": {
            "type": "ResponsiveTable",
            "popinLayout": "GridSmall"
        }
    },
    ...
}
```

STEP: Configure Default Popin Layout at Application Level (sap.fe)
DESCRIPTION: Define a defaultPopinLayout at application level under sap.fe.macros.table. Table-level popinLayout overrides this setting. Example sets GridLarge as application default.
LANGUAGE: JSON
CODE:
```
"sap.fe": {
    "macros": {
        "table":{
            "defaultPopinLayout": "GridLarge"
        }
    }
}
```

STEP: Annotate Service as Analytical — XML @Aggregation.ApplySupported
DESCRIPTION: Ensure analytical services include the @Aggregation.ApplySupported annotation with supported Transformations. Example XML lists supported transformation functions.
LANGUAGE: XML
CODE:
```xml
<Annotation Term="Aggregation.ApplySupported">
    <Record>
        <PropertyValue Property="Transformations">
            <Collection>
                <String>filter</String>
                <String>identity</String>
                <String>orderby</String>
                <String>search</String>
                <String>skip</String>
                <String>top</String>
                <String>groupby</String>
                <String>aggregate</String>
                <String>concat</String>
            </Collection>
        </PropertyValue>
    </Record>
</Annotation>
```

STEP: Annotate Service as Analytical — ABAP CDS & CAP
DESCRIPTION: Examples to mark aggregation support in ABAP CDS and CAP CDS.
LANGUAGE: Text
CODE:
```
// ABAP CDS
@OData.applySupportedForAggregation: #FULL

// CAP CDS (entity root)
@Aggregation.ApplySupported : {
}
```

STEP: Define Groupable Properties (XML & CAP)
DESCRIPTION: To allow grouping in analytical tables, declare GroupableProperties inside Aggregation.ApplySupported. Example XML and CAP show adding Segment and Country.
LANGUAGE: XML / CAP
CODE:
```xml
<!-- XML Annotation -->
<Annotations Target="sap.fe.managepartners.ManagePartnersService.Customers">
    <Annotation Term="Aggregation.ApplySupported">
        <PropertyValue Property="GroupableProperties">
            <Collection>
                <PropertyPath>Segment</PropertyPath>
                <PropertyPath>Country</PropertyPath>
            </Collection>
        </PropertyValue>
    </Annotation>
</Annotations>
```

```
// CAP CDS
@Aggregation.ApplySupported : {
    GroupableProperties: [Segment, Country]
}
```

STEP: Define Aggregatable Properties (measures) — XML, ABAP CDS, CAP examples
DESCRIPTION: Mark measures with Aggregation.default/@Analytics.Measure and define Aggregation.CustomAggregate at entity container level. Examples show XML, ABAP CDS, and CAP declarations.
LANGUAGE: XML / ABAP CDS / CAP
CODE:
```xml
<!-- XML Annotation -->
<Annotations Target="sap.fe.managepartners.ManagePartnersService.BusinessPartners/SalesAmount">
    <Annotation Term="Aggregation.default" EnumMember="Aggregation.defaultType/SUM"/>
    <Annotation Term="Analytics.Measure" Bool="true"/>
</Annotations>
...
<Annotations Target="sap.fe.managepartners.ManagePartnersService.EntityContainer">
    <Annotation Term="Aggregation.CustomAggregate" Qualifier="SalesAmount" String="Edm.Decimal"/>
</Annotations>
```

```
// ABAP CDS
@Aggregation.default: #SUM

SalesAmount
```

```
// CAP CDS
SalesAmount @Analytics.Measure : true @Aggregation.default : #SUM; //use the aggregation function you want
// At the entity level also define Aggregation.CustomAggregate with the property name as qualifier:
@Aggregation.CustomAggregate #SalesAmount : 'Edm.Decimal'
```

STEP: Enable/Disable Search Field for Analytical Service
DESCRIPTION: Include "search" in Transformations under Aggregation.ApplySupported to enable Search field (otherwise search disabled when Transformations present but omit 'search'). Examples: XML and CAP.
LANGUAGE: XML / CAP
CODE:
```xml
<!-- XML Annotation -->
<Annotations Target="sap.fe.managepartners.ManagePartnersService.Customers">
     <Annotation Term="Aggregation.ApplySupported">
          <Record Type="Aggregation.ApplySupportedType">
               <PropertyValue Property="Transformations">
                    <Collection>
                         <String>search</String>
                         <String>topcount</String>
                         <String>bottomcount</String>
                         <String>identity</String>
                         ...
                    </Collection>
               </PropertyValue>
          </Record>
      </Annotation>
</Annotations>
```

```
// CAP CDS
@Aggregation.ApplySupported : {
   Transformations : [
      'search',
      'topcount',
      'bottomcount',
      'identity',
      ...
   ],
}
```

STEP: Request Aggregation Based on Visible Columns (aggregationOnLeafLevel)
DESCRIPTION: Configure aggregationOnLeafLevel in analyticalConfiguration inside tableSettings to request aggregation only for visible columns. When true, navigation/bound actions require all entity key properties to be visible.
LANGUAGE: JSON
CODE:
```
"controlConfiguration":
{
    "@com.sap.vocabularies.UI.v1.LineItem":
     {        "tableSettings":
        {
            "type": "AnalyticalTable",
            "analyticalConfiguration":
            {
                "aggregationOnLeafLevel": true
            },
            "personalization": true
        }
    }
}
```

STEP: Require Transformation Filters on Back End for Aggregate Controls
DESCRIPTION: Ensure back end supports transformation filters for aggregate controls; add Transformations (e.g., filter) in @Aggregation.ApplySupported for aggregate entities. Example XML and CAP snippet for Transformations with filter.
LANGUAGE: XML / CAP
CODE:
```xml
<!-- XML Annotation -->
<Annotations Target="sap.fe.managepartners.ManagePartnersService.Customers">
     <Annotation Term="Aggregation.ApplySupported">
          <Record Type="Aggregation.ApplySupportedType">
               <PropertyValue Property="Transformations">
                    <Collection>
                         <String>filter</String>
                         ...
                    </Collection>
               </PropertyValue>
          </Record>
      </Annotation>
</Annotations>
```

```
// CAP CDS
@Aggregation.ApplySupported : {
   Transformations : [
      'filter',
      ...
   ],
}
```

STEP: Activate Tree Table (manifest controlConfiguration)
DESCRIPTION: To activate TreeTable, set tableSettings.type to "TreeTable" and provide the hierarchyQualifier; personalization can be enabled.
LANGUAGE: JSON
CODE:
```
"controlConfiguration": {
                "@com.sap.vocabularies.UI.v1.LineItem": {
                  "tableSettings": {
                    "type": "TreeTable",
                    "hierarchyQualifier": "SalesOrgHierarchy",
                    "personalization": true
                  }
                }
              }
```

STEP: Define Number of Visible Rows (rowCount, rowCountMode)
DESCRIPTION: Control number of visible rows with rowCount and rowCountMode inside tableSettings. rowCountMode values: Fixed, Auto, Interactive. Example sets GridTable to 10 Fixed rows and enables personalization. Note: rowCountMode doesn't apply to ResponsiveTable. If sectionLayout is Tabs and table is sole control, rowCountMode defaults to Auto.
LANGUAGE: JSON
CODE:
```
"controlConfiguration": {
    "@com.sap.vocabularies.UI.v1.LineItem": {
        "tableSettings": {
	            "type": "GridTable",
                    "rowCount": 10,
                    "rowCountMode": "Fixed"
                    "personalization": true,
                     ...
        }
    },
    ...
}
```

STEP: Draft-Enabled Service Behavior with Analytical/Tree Tables (summary)
DESCRIPTION: When using draft-enabled services with analytical or tree tables on the list report:
- Only active entities displayed
- Editing Status not shown in filter bar
- Draft indicator shown for active record with draft
- New objects must be saved or discarded
- Saved objects: draft management unchanged
- Analytical table on object/custom page is read-only (no create/delete); tree table not affected
- Analytical/Tree table not allowed in List Report with draft service in flexible column layout
LANGUAGE: text
CODE:
```
Draft-enabled service rules for analytical/tree tables:
- Active entities only
- Editing Status hidden in filter bar
- Draft indicator visible if draft exists
- New objects require save/discard
- Analytical on OP/custom: read-only (no create/delete)
- Prohibited in FCL for list report
```

STEP: References and Next Steps
DESCRIPTION: Use these docs for deeper details and constraints:
- Tables (detailed table types)
- Settings for List Report Tables
- Enabling Standard List Items and Object List Items
- Settings for Object Page Tables
- Table Groupings
LANGUAGE: text
CODE:
```
See: tables-c0f6592.md
See: settings-for-list-report-tables-4c2d17a.md
See: enabling-standard-list-items-and-object-list-items-4ed47aa.md
See: settings-for-object-page-tables-47425bb.md
See: table-groupings-d344c5a.md
```

manifest.json tableSettings tableTypes ResponsiveTable GridTable AnalyticalTable TreeTable popinLayout aggregation @Aggregation.ApplySupported ODataV2 ODataV4 sap.fe controlConfiguration manifest


**TITLE**: Setting Units of Measure for Numeric Properties (OData / Annotations / CAP)

**INTRODUCTION**: This document shows three ways to attach units/currency to numeric properties so UI (Fiori elements) displays the unit next to values: 1) add sap:unit and sap:semantics in the OData metadata (XML) EntityType, 2) add OData XML annotation entries using Org.OData.Measures.V1.Unit and Org.OData.Measures.V1.ISOCurrency, and 3) add CAP CDS annotations using @Measures.Unit and @Measures.ISOCurrency. Use the metadata approach when you control the service metadata; use annotation files when you cannot modify metadata; use CAP CDS in SAP CAP projects.

**TAGS**: fiori-elements-framework, odata, annotations, unit-of-measure, currency, sap, CAP, CDS, XML

**STEP**: 1 — Add sap:unit / sap:semantics in OData metadata (EntityType)
**DESCRIPTION**: In the OData metadata XML, set the sap:unit attribute on numeric (measure) properties to reference the property that holds the unit/currency code. Mark unit/currency properties with sap:semantics where appropriate (e.g., "unit-of-measure", "currency-code"). This modifies the service metadata so clients automatically render units next to numeric values.
**LANGUAGE**: XML
**CODE**:
```xml
<EntityType Name="Product" sap:content-version="1">
    <Key>
        <PropertyRef Name="ProductID"/>
    </Key>
    <Property Name="ProductID" Type="Edm.String" Nullable="false" MaxLength="10" sap:label="Product ID" sap:updatable="false"/>
    <Property Name="TypeCode" Type="Edm.String" MaxLength="2" sap:label="Prod. Type Code"/>
    <Property Name="Category" Type="Edm.String" MaxLength="40" sap:label="Prod. Cat."/>
    <Property Name="Name" Type="Edm.String" MaxLength="255" sap:label="Product Name" sap:sortable="false" sap:filterable="false"/>
    <Property Name="NameLanguage" Type="Edm.String" MaxLength="1" sap:label="Language" sap:creatable="false" sap:updatable="false" sap:sortable="false" sap:filterable="false"/>
    <Property Name="Description" Type="Edm.String" MaxLength="255" sap:label="Prod.Descrip." sap:sortable="false" sap:filterable="false"/>
    <Property Name="DescriptionLanguage" Type="Edm.String" MaxLength="1" sap:label="Language" sap:creatable="false" sap:updatable="false" sap:sortable="false" sap:filterable="false"/>
    <Property Name="SupplierID" Type="Edm.String" MaxLength="10" sap:label="Bus. Part. ID"/>
    <Property Name="SupplierName" Type="Edm.String" MaxLength="80" sap:label="Company Name" sap:creatable="false" sap:updatable="false"/>
    <Property Name="TaxTarifCode" Type="Edm.Byte" sap:label="Prod. Tax Code"/>
    <Property Name="MeasureUnit" Type="Edm.String" MaxLength="3" sap:label="Qty. Unit" sap:semantics="unit-of-measure"/>
    <Property Name="WeightMeasure" Type="Edm.Decimal" Precision="13" Scale="3" sap:unit="WeightUnit" sap:label="Wt. Measure"/>
    <Property Name="WeightUnit" Type="Edm.String" MaxLength="3" sap:label="Qty. Unit" sap:semantics="unit-of-measure"/>
    <Property Name="CurrencyCode" Type="Edm.String" MaxLength="5" sap:label="Currency" sap:semantics="currency-code"/>
    <Property Name="Price" Type="Edm.Decimal" Precision="16" Scale="3" sap:unit="CurrencyCode" sap:label="Unit Price"/>
    <Property Name="Width" Type="Edm.Decimal" Precision="13" Scale="3" sap:unit="DimUnit" sap:label="Dimensions"/>
    <Property Name="Depth" Type="Edm.Decimal" Precision="13" Scale="3" sap:unit="DimUnit" sap:label="Dimensions"/>
    <Property Name="Height" Type="Edm.Decimal" Precision="13" Scale="3" sap:unit="DimUnit" sap:label="Dimensions"/>
    <Property Name="DimUnit" Type="Edm.String" MaxLength="3" sap:label="Dim. Unit" sap:semantics="unit-of-measure"/>
    <Property Name="CreatedAt" Type="Edm.DateTime" Precision="7" sap:label="Time Stamp" sap:creatable="false" sap:updatable="false"/>
    <Property Name="ChangedAt" Type="Edm.DateTime" Precision="7" ConcurrencyMode="Fixed" sap:label="Time Stamp" sap:creatable="false" sap:updatable="false"/>
    <NavigationProperty Name="ToSalesOrderLineItems" Relationship="GWSAMPLE_BASIC.Assoc_Product_SalesOrderLineItems" FromRole="FromRole_Assoc_Product_SalesOrderLineItems" ToRole="ToRole_Assoc_Product_SalesOrderLineItems"/>
    <NavigationProperty Name="ToSupplier" Relationship="GWSAMPLE_BASIC.Assoc_BusinessPartner_Products" FromRole="ToRole_Assoc_BusinessPartner_Products" ToRole="FromRole_Assoc_BusinessPartner_Products"/>
</EntityType>
```

**STEP**: 2 — Add OData XML Annotations (annotation document)
**DESCRIPTION**: If you cannot change service metadata, add annotation entries in a separate XML annotation file. Use Term="Org.OData.Measures.V1.Unit" with Path pointing to the unit property, and Term="Org.OData.Measures.V1.ISOCurrency" with Path pointing to the currency code property. The Target must be "Namespace.EntityType/Property".
**LANGUAGE**: XML
**CODE**:
```xml
<Annotations Target="GWSAMPLE_BASIC.Product/WeightMeasure">
    <Annotation Term="Org.OData.Measures.V1.Unit" Path="WeightUnit"/>
</Annotations>
<Annotations Target="GWSAMPLE_BASIC.Product/Width">
    <Annotation Term="Org.OData.Measures.V1.Unit" Path="DimUnit"/>
</Annotations>
<Annotations Target="GWSAMPLE_BASIC.Product/Depth">
    <Annotation Term="Org.OData.Measures.V1.Unit" Path="DimUnit"/>
</Annotations>
<Annotations Target="GWSAMPLE_BASIC.Product/Height">
    <Annotation Term="Org.OData.Measures.V1.Unit" Path="DimUnit"/>
</Annotations>
<Annotations Target="GWSAMPLE_BASIC.Product/Price">
    <Annotation Term="Org.OData.Measures.V1.ISOCurrency" Path="CurrencyCode"/>
</Annotations>
```

**STEP**: 3 — Add CAP CDS annotations (SAP CAP model files)
**DESCRIPTION**: In CAP CDS model files, annotate the entity's properties using @Measures.Unit and @Measures.ISOCurrency. Each annotate block attaches the measure semantic to the target property. Place these annotate statements in the same CDS model or in a separate .cds file that augments the entity.
**LANGUAGE**: CDS
**CODE**:
```
annotate GWSAMPLE_BASIC.Product with {
  @Measures.Unit : WeightUnit
  WeightMeasure
};

annotate GWSAMPLE_BASIC.Product with {
  @Measures.Unit : DimUnit
  Width
};

annotate GWSAMPLE_BASIC.Product with {
  @Measures.Unit : DimUnit
  Depth
};

annotate GWSAMPLE_BASIC.Product with {
  @Measures.Unit : DimUnit
  Height
};

annotate GWSAMPLE_BASIC.Product with {
  @Measures.ISOCurrency : CurrencyCode
  Price
};
```

**STEP**: 4 — ABAP CDS annotation
**DESCRIPTION**: No ABAP CDS annotation sample is provided in this source. If developing on ABAP stack, use local XML annotation files (OData XML annotations) to define units and currencies as shown above.
**LANGUAGE**: PlainText
**CODE**:
```
No ABAP CDS annotation sample is available. Please use the local XML annotation.
```

fiori-elements-framework odata annotations unit-of-measure currency sap CAP CDS XML


**TITLE**: Setting Up the Object Page Header (UI.HeaderInfo)

**INTRODUCTION**: This guide shows exactly how to define the Object Page header (UI.HeaderInfo) using OData XML annotations, ABAP CDS annotations, or CAP CDS annotations. Follow the mappings and sample snippets to set title, subtitle/description, image, type name, type image/icon, and initials. Use these annotations in your annotation files (OData annotation XML) or CDS views to render the header in Fiori Elements object pages.

**TAGS**: fiori-elements, annotations, UI.HeaderInfo, object-page, HeaderInfo, CDS, OData, CAP

**STEP**: 1 — Choose header type and reference docs

**DESCRIPTION**: Decide whether to use the dynamic header or the standard header. The object page supports the dynamic header. See the control reference for options and behavior before implementing annotations.

- Refer to: ../10_More_About_Controls/object-page-header-6e340c1.md

**LANGUAGE**: Text

**CODE**:
```text
Reference: ../10_More_About_Controls/object-page-header-6e340c1.md
```

**STEP**: 2 — Map vocabulary properties to header fields

**DESCRIPTION**: Use these vocabulary properties in the UI.HeaderInfo annotation to control header display. Apply them in OData annotation XML, ABAP CDS, or CAP CDS.

- com.sap.vocabularies.UI.v1.HeaderInfo/Title/Value  -> object title
- com.sap.vocabularies.UI.v1.HeaderInfo/Description/Value -> subtitle
- com.sap.vocabularies.UI.v1.HeaderInfo/ImageUrl -> image URL for the instance
- com.sap.vocabularies.UI.v1.HeaderInfo/TypeName -> text for link back to list report (object type)
- com.sap.vocabularies.UI.v1.HeaderInfo/TypeImageUrl -> icon for object type
- com.sap.vocabularies.UI.v1.HeaderInfo/Initials -> initials fallback

Include TypeNamePlural to show plural label where appropriate.

**LANGUAGE**: Text

**CODE**:
```text
Vocabularies to use:
- HeaderInfo.Title.Value
- HeaderInfo.Description.Value
- HeaderInfo.ImageUrl
- HeaderInfo.TypeName
- HeaderInfo.TypeImageUrl
- HeaderInfo.Initials
- HeaderInfo.TypeNamePlural
```

**STEP**: 3 — Understand the main header elements (visual mapping)

**DESCRIPTION**: The typical object page header includes:
1. Title (Object Type) — Title.Value
2. Image of object instance — ImageUrl
3. Language-dependent product text — Title.Value (localized field)
4. Product title — Description.Value or additional DataField

The sample diagram (if needed) is included as an image in the docs resources.

**LANGUAGE**: Text

**CODE**:
```text
Image file (diagram): images/Object_Page_Header_Main_Elements_698018b.png
```

**STEP**: 4 — Implement UI.HeaderInfo via OData XML annotations

**DESCRIPTION**: Add the following UI.HeaderInfo annotation to your OData annotation XML file (service annotations or local annotation file). This example maps a SalesOrder title, description, image, and type names.

Place in your annotation XML where other UI annotations live or attach to the relevant EntityType.

**LANGUAGE**: XML

**CODE**:
```xml
<Annotation Term="UI.HeaderInfo">
     <Record Type="UI.HeaderInfoType">
          <PropertyValue Property="Description">
               <Record Type="UI.DataField">
                    <PropertyValue Property="Value" Path="SalesOrderTypeName"/>
               </Record>
          </PropertyValue>
          <PropertyValue Property="ImageUrl" Path="ImageUrl"/>
          <PropertyValue Property="Title">
               <Record Type="UI.DataField">
                    <PropertyValue Property="Value" Path="SalesOrder"/>
               </Record>
          </PropertyValue>
          <PropertyValue Property="TypeName" String="Sales Order"/>
          <PropertyValue Property="TypeNamePlural" String="Sales Orders"/>
     </Record>
</Annotation>
```

**STEP**: 5 — Implement UI.headerInfo in ABAP CDS

**DESCRIPTION**: Add the @UI.headerInfo annotation to your ABAP CDS view. Use typeName/typeNamePlural, imageUrl column, and DataField-like structures for title and description. Annotate the view (example uses STTA_C_MP_PRODUCT).

**LANGUAGE**: ABAP

**CODE**:
```abap
@UI.headerInfo: {
  typeName: 'Product',
  typeNamePlural: 'Products',
  imageUrl: 'PRODUCTPICTUREURL',
  title: {
    value: '_PRODUCTTEXTINCURRENTLANG.NAME',
    type: #STANDARD
  },
  description: {
    value: 'PRODUCT',
    type: #STANDARD
  }
}
annotate view STTA_C_MP_PRODUCT with {

}
```

**STEP**: 6 — Implement UI.HeaderInfo in CAP CDS

**DESCRIPTION**: In CAP model or annotation file, declare UI.HeaderInfo with TypeName/TypeNamePlural, map ImageUrl to the entity element, and set Title/Description using UI.DataField ($Type: 'UI.DataField') and Value references.

**LANGUAGE**: CDS

**CODE**:
```cds
UI.HeaderInfo : {
    TypeName : 'Product',
    TypeNamePlural : 'Products',
    ImageUrl : ProductPictureURL,
    Title : {
        $Type : 'UI.DataField',
        Value : to_ProductTextInCurrentLang.Name
    },
    Description : {
        $Type : 'UI.DataField',
        Value : Product
    }
}
```

**STEP**: 7 — Optional: Images, initials, icons, and custom status

**DESCRIPTION**: Use ImageUrl, TypeImageUrl, and Initials for icons and initials behavior. For advanced display options and usage examples, consult the dedicated docs. To display a custom status message in the object page header, use extension points for header facets.

- Using images, initials, and icons doc: using-images-initials-and-icons-5760b63.md
- Extension points for object page header facets: extension-points-for-object-page-header-facets-61cf0ee.md

**LANGUAGE**: Text

**CODE**:
```text
See:
- using-images-initials-and-icons-5760b63.md
- extension-points-for-object-page-header-facets-61cf0ee.md
```

fiori-elements annotations UI.HeaderInfo object-page HeaderInfo CDS OData CAP


**TITLE**: Configuring Display of Editing Status in List Report Tables

**INTRODUCTION**: This guide explains how to ensure draft/editing statuses (Draft, Unsaved Changes by Another User, Locked by Another User) appear correctly in Fiori Elements list report tables. It covers standard behavior (responsive vs grid tables), the OData V2 fallback rules, and the relevant annotation examples (SemanticKey, LineItem, HeaderInfo) required to control where the editing status is rendered.

**TAGS**: fiori-elements-framework, list-report, editing-status, draft, annotations, OData-v2, LineItem, SemanticKey, HeaderInfo, manifest.json

**STEP**: 1 — Verify draft support in the service

**DESCRIPTION**: Ensure the OData service supports draft handling. The application must be draft-enabled on the backend (Draft Root annotation present). Without draft support, the Fiori Elements list report will not display editing status information.

**LANGUAGE**: XML

**CODE**:
```xml
<!-- Example: mark an EntityType or EntitySet as draft-enabled using the Common DraftRoot annotation -->
<Annotations Target="YourService.YourEntityType">
  <Annotation Term="com.sap.vocabularies.Common.v1.DraftRoot" />
</Annotations>
```

**STEP**: 2 — Provide a Semantic Key for consistent placement of editing status

**DESCRIPTION**: Add com.sap.vocabularies.Common.v1.SemanticKey to the entity type. When a semantic key is present and included in the table LineItem, the editing status will be shown in the column where the first semantic key appears (responsive table: key column; grid table: separate column next to key column).

**LANGUAGE**: XML

**CODE**:
```xml
<!-- Example: define a SemanticKey for the entity -->
<Annotations Target="YourService.YourEntityType">
  <Annotation Term="com.sap.vocabularies.Common.v1.SemanticKey">
    <Collection>
      <PropertyPath>SalesOrderID</PropertyPath>
      <PropertyPath>ItemPosition</PropertyPath>
    </Collection>
  </Annotation>
</Annotations>
```

**STEP**: 3 — Define LineItem annotation (table columns) including semantic key fields

**DESCRIPTION**: Define the LineItem annotation to list the table columns. Include the semantic key properties as DataField entries so the editing status is placed in the expected column. If the semantic key fields are in the LineItem, draft indicators are shown in that column for responsive tables or in a dedicated column for grid tables.

**LANGUAGE**: XML

**CODE**:
```xml
<!-- Example: LineItem with DataField entries; include the semantic key properties -->
<Annotations Target="YourService.YourEntityType">
  <Annotation Term="com.sap.vocabularies.UI.v1.LineItem">
    <Collection>
      <Record Type="com.sap.vocabularies.UI.v1.DataField">
        <PropertyValue Property="Label" String="Sales Order"/>
        <PropertyValue Property="Value"><PropertyPath>SalesOrderID</PropertyPath></PropertyValue>
      </Record>
      <Record Type="com.sap.vocabularies.UI.v1.DataField">
        <PropertyValue Property="Label" String="Item"/>
        <PropertyValue Property="Value"><PropertyPath>ItemPosition</PropertyPath></PropertyValue>
      </Record>
      <!-- additional DataField entries -->
    </Collection>
  </Annotation>
</Annotations>
```

**STEP**: 4 — Provide HeaderInfo (Title/Description) for OData V2 fallback behavior

**DESCRIPTION**: For OData V2 scenarios where a semantic key is not added to the LineItem, the system falls back to showing draft information in the Title or Description column. Provide HeaderInfo with Title and/or Description paths so the fallback can locate a column to display the editing status.

**LANGUAGE**: XML

**CODE**:
```xml
<!-- Example: HeaderInfo providing Title and Description for fallback -->
<Annotations Target="YourService.YourEntityType">
  <Annotation Term="com.sap.vocabularies.UI.v1.HeaderInfo">
    <Record>
      <PropertyValue Property="Title">
        <Record Type="com.sap.vocabularies.UI.v1.DataField">
          <PropertyValue Property="Value"><PropertyPath>TitleField</PropertyPath></PropertyValue>
        </Record>
      </PropertyValue>
      <PropertyValue Property="Description">
        <Record Type="com.sap.vocabularies.UI.v1.DataField">
          <PropertyValue Property="Value"><PropertyPath>DescriptionField</PropertyPath></PropertyValue>
        </Record>
      </PropertyValue>
    </Record>
  </Annotation>
</Annotations>
```

**STEP**: 5 — Understand where editing status is displayed

**DESCRIPTION**: Summary of rendering rules to implement/verify in annotations and configuration:
- Responsive table: editing status appears in the key column (where the first semantic key DataField appears).
- Grid table: editing status appears in a separate column next to the key column.
- OData V2 fallback: if no semantic key is provided in LineItem, editing status is shown in Title or Description column (the system checks HeaderInfo and then LineItem Title/Value/Path).

**LANGUAGE**: Plain text

**CODE**:
```text
Behavior summary:
- ResponsiveTable -> status displayed in key column (first semantic key column)
- GridTable      -> status displayed in a separate column next to the key column
- OData V2       -> If no LineItem semantic key: try Title (HeaderInfo) or Description; if not found, check LineItem Title/Value/Path
```

**STEP**: 6 — (Optional) Configure table type in manifest.json

**DESCRIPTION**: Configure the list report template to use a responsive or grid table. The property name depends on the template version (sap.ui.generic.app or sap.fe.templates). Use this manifest setting to control whether the app renders ResponsiveTable or GridTable (which affects placement of editing status).

**LANGUAGE**: JSON

**CODE**:
```json
{
  "sap.ui.generic.app": {
    "settings": {
      "tableType": "ResponsiveTable" // options: "ResponsiveTable" or "GridTable"
    }
  }
}
```

fiori-elements-framework list-report editing-status draft annotations OData-v2 LineItem SemanticKey HeaderInfo manifest.json


**TITLE**: Settings for Object Page Tables in manifest.json

**INTRODUCTION**: This guide shows where and how to configure table-related settings for Object Pages in an SAP Fiori elements application using the application's manifest.json. It provides a clear, editable JSON template to copy and adapt for specifying table behavior and appearance on Object Pages.

**TAGS**: fiori-elements-framework, object-page, manifest.json, tables, settings

**STEP**: 1 — Locate manifest.json

**DESCRIPTION**: Open the application's manifest.json at the project root. Object Page table settings belong inside the app descriptor where the Object Page (generic template) is defined. Typically this is under "sap.ui.generic.app" -> "pages" (or under the routing target that references the Object Page component). If your app uses component-based pages, similar settings live under the corresponding page/component settings.

**LANGUAGE**: JSON

**CODE**:
```json
{
  "sap.ui.generic.app": {
    "pages": {
      "YourEntitySet::ObjectPage": {
        "component": {
          "name": "sap.suite.ui.generic.template.ObjectPage",
          "settings": {
            // table settings go here
          }
        }
      }
    }
  }
}
```

**STEP**: 2 — Add table-specific settings (example template)

**DESCRIPTION**: Insert table-specific configuration inside the Object Page component's "settings" node. Adapt keys and values to your app's needs. This template shows common configurable areas: table type, selection mode, visible fields, and action enablement. Replace placeholder names and arrays with your actual entity set and field names.

**LANGUAGE**: JSON

**CODE**:
```json
{
  "sap.ui.generic.app": {
    "pages": {
      "YourEntitySet::ObjectPage": {
        "component": {
          "name": "sap.suite.ui.generic.template.ObjectPage",
          "settings": {
            "tableSettings": {
              "type": "ResponsiveTable",        // e.g., ResponsiveTable, AnalyticalTable, GridTable
              "mode": "SingleSelect",          // e.g., None, SingleSelect, MultiSelect
              "enableExport": true,            // enable/disable export actions
              "visibleFields": [               // fields/columns to show on the table
                "Field1",
                "Field2",
                "Field3"
              ],
              "preserveSelection": true,       // keep selection on navigation
              "initialSort": [                 // optional initial sort configuration
                {
                  "path": "Field1",
                  "descending": false
                }
              ],
              "filters": {                     // optional filter defaults
                "Field2": {
                  "operator": "EQ",
                  "value": "SomeValue"
                }
              },
              "customActions": [               // optional actions added to the table toolbar
                {
                  "id": "actionId",
                  "text": "Do Action",
                  "enabled": true
                }
              ]
            }
          }
        }
      }
    }
  }
}
```

**STEP**: 3 — Validate and extend

**DESCRIPTION**: After adding settings:
- Validate JSON (no trailing commas).
- Ensure the "pages" key and entity set names match your app routing and annotations.
- Extend settings with framework- or project-specific keys as required (e.g., annotation-driven keys or additional template-specific switches).
- Test in the app to confirm the Object Page table reflects the configured settings.

**LANGUAGE**: Plain text

**CODE**:
```text
Notes:
- Replace "YourEntitySet::ObjectPage" with the actual page key used in your manifest routing/pages.
- Use only keys supported by your Fiori elements/template version; consult the specific framework documentation for all supported table settings and exact key names.
```

fiori-elements-framework object-page manifest.json tables settings


**TITLE**: Sharing Overview Pages (SAP Fiori)

**INTRODUCTION**: Describe how to share the current state of an SAP Fiori overview page either as a tile on the SAP Fiori Launchpad or by sending an email link. This is used when you need to preserve the filter-bar state for later access or distribute a direct link representing the current view.

**TAGS**: fiori-elements-framework, sap-fiori, launchpad, sharing, overview-page, email

**STEP**: Save Overview Page as Tile on SAP Fiori Launchpad

**DESCRIPTION**: Store the current filter-bar state of an overview page as a tile on the SAP Fiori Launchpad. This enables users to open the application later with the same filter settings applied. Use the exact UI flow to ensure automation scripts or documentation reference the correct labels.

- UI steps to perform:
  - On the filter bar, click "Share"
  - Select "Save As Tile"
  - Fill required fields in the tile creation dialog (title, subtitle, semantic object, etc., as applicable)
  - Click "Ok" to save the tile

- Notes for automation or code-driven flows:
  - Target the "Share" control of the filter bar.
  - Ensure the tile creation dialog is fully loaded before filling fields.
  - Validate that the saved tile reopens the application with the same filter-bar state.

**LANGUAGE**: User Actions

**CODE**:
```User Actions
# Manual/automation steps (no code required)
1. Click: Filter bar -> "Share"
2. Click: "Save As Tile"
3. Fill required fields in dialog
4. Click: "Ok"
```

**STEP**: Share Overview Page via Email Link

**DESCRIPTION**: Generate an email containing a link to the overview page that preserves the current filter-bar state. This allows recipients to open the application directly with the same view.

- UI steps to perform:
  - On the filter bar, click "Share"
  - Select "Send Email"
  - The application generates an email draft (or triggers the mail client) containing a link that encodes the current state

- Notes for automation or code-driven flows:
  - Target the "Share" control of the filter bar.
  - Confirm the generated link includes the relevant state parameters (used by the application to restore filters).
  - If validating programmatically, capture the link string from the email draft or mail client invocation.

**LANGUAGE**: User Actions

**CODE**:
```User Actions
# Manual/automation steps (no code required)
1. Click: Filter bar -> "Share"
2. Click: "Send Email"
3. Verify email draft contains link to the overview page that preserves current filter-bar state
```

Sharing Overview Pages (SAP Fiori)

fiori-elements-framework sap-fiori launchpad sharing overview-page email


**TITLE**: Showing and Hiding Content in Object Page Facets (SAP Fiori Elements)

**INTRODUCTION**: Configure visibility controls on Object Page reference facets and the fields inside them. Set the UI.PartOfPreview annotation to false to enable: (1) Show More / Show Less for reference facets (additional facets in a collection) and (2) Show Details / Hide Details for fields/tables inside a visible reference facet. Includes XML, ABAP CDS and CAP CDS examples. Applicable for OData V4 Object Page floorplan.

**TAGS**: fiori-elements-framework, OData V4, UI.PartOfPreview, reference-facet, fieldgroup, object-page, SAPUI5, CDS, CAP, ABAP

STEP: 1 — Enable Show More / Show Less for Reference Facets

DESCRIPTION: Add UI.PartOfPreview = false to the UI.ReferenceFacet record to mark that facet as not part of the preview. SAP Fiori Elements will render Show More (if hidden facets exist) and Show Less (after expansion) controls. This applies when the reference facet is implemented under a collection facet and the target is a FieldGroup (form). If you do not set the annotation explicitly, the default is UI.PartOfPreview = true.

LANGUAGE: XML

CODE:
```xml
<Record Type="UI.ReferenceFacet">
    <PropertyValue Property="Label" String="{@i18n>@ShipToAddress}"/>
    <PropertyValue Property="ID" String="ShipToAddress"/>
    <PropertyValue Property="Target"
    AnnotationPath="@UI.FieldGroup#ShipToAddress"/>
    <Annotation Term="UI.PartOfPreview" Bool="false"/>
</Record>
```

LANGUAGE: ABAP CDS

CODE:
```abap
@UI.Facet: [{
        type: #FIELDGROUP_REFERENCE,
        label: 'Ship-To Address',
        targetQualifier: 'ShipToAddress',
        isPartOfPreview: false
}]
```

LANGUAGE: CAP CDS

CODE:
```cds
Facets: [{
    $Type : 'UI.ReferenceFacet',
    Label : '{@i18n>@ShipTo_NotPartOfPreview}',
    Target : '@UI.FieldGroup#ShipToAddress',
    ![@UI.PartOfPreview] : false
}]
```

STEP: 2 — Enable Show Details / Hide Details for Fields (inside a visible reference facet)

DESCRIPTION: To enable Show Details / Hide Details in the facet toolbar (for tables and data fields inside a reference facet), set UI.PartOfPreview = false on the DataField entries (or Data entries in a FieldGroup). This only works for fields/tables that are part of a reference facet that is initially visible. You cannot apply this to fields inside a facet that is initially hidden, and you cannot nest UI.PartOfPreview (i.e., you cannot make fields controllable if their parent facet is initially hidden).

LANGUAGE: XML

CODE:
```xml
<Record Type="UI.DataField">
    <PropertyValue Property="Label" String="{@i18n>@StreetName}" />
    <PropertyValue Property="Value" Path="StreetName" />
    <Annotation Term="UI.PartOfPreview" Bool="false" />
</Record>
```

LANGUAGE: CAP CDS

CODE:
```cds
FieldGroup#ShipToAddress: {
    Data: [{
            $Type                : 'UI.DataField',
            Label                : '{@i18n>@StreetName}',
            Value                : StreetName,
            ![@UI.PartOfPreview] : false
    }]
}
```

LANGUAGE: ABAP CDS

CODE:
```text
(No ABAP CDS sample available for showing/hiding fields inside reference facets — use local XML annotation.)
```

STEP: 3 — Restrictions and Notes

DESCRIPTION:
- Applicable only to reference facets with a FieldGroup target (form representation). Not applicable to reference facets that target a table or chart.
- Show More / Show Less: feature available for reference facets that are implemented under a collection facet.
- Show Details / Hide Details: available for tables and data fields included in a visible reference facet only. Cannot use for fields/tables in a reference facet that is initially hidden (no nesting).
- Default behavior: if UI.PartOfPreview is not set, it defaults to true (i.e., part of preview / always visible).
- For live examples and further exploration, see SAP Fiori development portal Global Patterns - Show/Hide Content:
  https://ui5.sap.com/test-resources/sap/fe/core/fpmExplorer/index.html#/topic/floorplanObjectPage/showHideContent

fiori-elements-framework
OData V4
UI.PartOfPreview
reference-facet
fieldgroup
object-page
SAPUI5
CDS
CAP
ABAP


**TITLE**: Side Effect Annotation Examples for SAP Fiori Elements (OData V2 & V4)

**INTRODUCTION**: Collection of ready-to-use side effect annotation examples (XML and ABAP/CDS) for SAP Fiori Elements. Use these snippets to annotate OData V2 services (annotation files or MPC_EXT class) and RAP/CDS models (ABAP CDS) to trigger function imports, refresh properties/entities/navigation targets, and configure action-related side effects.

**TAGS**: fiori-elements-framework, side-effects, annotations, OData V2, OData V4, XML, ABAP, CDS, TriggerAction, MPC_EXT, function-import

**STEP**: TriggerAction — Call function import to recalculate properties on source property change

**DESCRIPTION**: Add this XML SideEffects annotation to your local annotation file or service annotations. When UnitPrice or ProductQuantity is modified and validated, call the function import CalculatePriceIncludingRegionalTax to recalculate GrossPrice and NetPriceIncludingTax.

**LANGUAGE**: XML

**CODE**:
```XML
<Annotations Target="STTA_SALES_ORDER_WD_20_SRV.C_STTA_SalesOrder_WD_20Type">
    <Annotation Term="com.sap.vocabularies.Common.v1.SideEffects" Qualifier="CalculatePrice">
        <Record>
            <PropertyValue Property="SourceProperties">
                <Collection>
                    <PropertyPath>UnitPrice</PropertyPath>
                    <PropertyPath>ProductQuantity</PropertyPath>
                </Collection>
            </PropertyValue>
            <PropertyValue Property="TargetProperties">
                <Collection>
                    <String>GrossPrice</String>
                    <String>NetPriceIncludingTax</String>
                </Collection>
            </PropertyValue>
            <PropertyValue Property="TriggerAction" String="STTA_SALES_ORDER_WD_20_SRV.STTA_SALES_ORDER_WD_20_SRV_Entities/CalculatePriceIncludingRegionalTax"/>
        </Record>
    </Annotation>
</Annotations>
```

**STEP**: TriggerAction — Call function import without targets (no refresh)

**DESCRIPTION**: Configure a side effect to call a TriggerAction function import but without specifying TargetProperties/TargetEntities. Use this to execute server-side logic without triggering any UI refresh automatically.

**LANGUAGE**: XML

**CODE**:
```XML
<Annotations Target="STTA_SALES_ORDER_WD_20_SRV.C_STTA_SalesOrder_WD_20Type">
    <Annotation Term="com.sap.vocabularies.Common.v1.SideEffects" Qualifier="CalculatePrice">
        <Record>
            <PropertyValue Property="SourceProperties">
                <Collection>
                    <PropertyPath>UnitPrice</PropertyPath>
                    <PropertyPath>ProductQuantity</PropertyPath>
                </Collection>
            </PropertyValue>
            <PropertyValue Property="TriggerAction" String="STTA_SALES_ORDER_WD_20_SRV.STTA_SALES_ORDER_WD_20_SRV_Entities/CalculatePriceIncludingRegionalTax"/>
        </Record>
    </Annotation>
</Annotations>
```

**STEP**: Define Side Effects in MPC_EXT (ABAP) — create annotations programmatically in DEFINE

**DESCRIPTION**: In the DEFINE method of an MPC_EXT class, create vocabulary references, include namespaces, and build a SideEffects annotation programmatically. Example shows creating SourceProperties collection (Supplier, CompanyCode, DocumentCurrency, PurchasingGroup, PurchasingOrganization).

**LANGUAGE**: ABAP

**CODE**:
```ABAP
* define Side Effects for Purchase Order:
    DATA lo_ann_target TYPE REF TO /iwbep/if_mgw_vocan_ann_target.   " Vocabulary Annotation Target                     "#EC NEEDED
    DATA lo_annotation TYPE REF TO /iwbep/if_mgw_vocan_annotation.   " Vocabulary Annotation                            "#EC NEEDED
    DATA lo_collection TYPE REF TO /iwbep/if_mgw_vocan_collection.   " Vocabulary Annotation Collection                 "#EC NEEDED
    DATA lo_function   TYPE REF TO /iwbep/if_mgw_vocan_function.     " Vocabulary Annotation Function                   "#EC NEEDED
    DATA lo_fun_param  TYPE REF TO /iwbep/if_mgw_vocan_fun_param.    " Vocabulary Annotation Function Parameter         "#EC NEEDED
    DATA lo_property   TYPE REF TO /iwbep/if_mgw_vocan_property.     " Vocabulary Annotation Property                   "#EC NEEDED
    DATA lo_record     TYPE REF TO /iwbep/if_mgw_vocan_record.       " Vocabulary Annotation Record                     "#EC NEEDED
    DATA lo_reference  TYPE REF TO /iwbep/if_mgw_vocan_reference.    " Vocabulary Annotation Reference

    lo_reference = vocab_anno_model->create_vocabulary_reference( iv_vocab_id = '/IWBEP/VOC_COMMON'
                                                                  iv_vocab_version = '0001').
    lo_reference->create_include( iv_namespace = 'com.sap.vocabularies.Common.v1' ).
    lo_reference = vocab_anno_model->create_vocabulary_reference( iv_vocab_id = '/IWBEP/VOC_CORE'
                                                                  iv_vocab_version = '0001').
    lo_reference->create_include( iv_namespace = 'Org.OData.Core.V1' ).

    lo_ann_target = vocab_anno_model->create_annotations_target( 'MM_PUR_PO_AI_MAINTAIN.C_PurchaseOrderEnhWDType' ) ##NO_TEXT . "Add annotation term for VIPs introduced

    lo_annotation = lo_ann_target->create_annotation( iv_term = 'com.sap.vocabularies.Common.v1.SideEffects' ) ##NO_TEXT .

    lo_record     = lo_annotation->create_record( )  ##NO_TEXT.
    lo_property   = lo_record->create_property( 'SourceProperties' )   ##NO_TEXT.
    lo_collection = lo_property->create_collection( ).

    lo_collection->create_simple_value( )->set_property_path( 'Supplier' )  ##NO_TEXT .
    lo_collection->create_simple_value( )->set_property_path( 'CompanyCode' )  ##NO_TEXT .
    lo_collection->create_simple_value( )->set_property_path( 'DocumentCurrency' )  ##NO_TEXT .
    lo_collection->create_simple_value( )->set_property_path( 'PurchasingGroup' )  ##NO_TEXT.
    lo_collection->create_simple_value( )->set_property_path( 'PurchasingOrganization' )  ##NO_TEXT.
```

**STEP**: PriceChanged — refresh Price when Amount/Discount/multi-input source changes

**DESCRIPTION**: Add a SideEffects annotation to refresh the Price property when Amount, Discount, or a multi-input field (ProductDetail/DeliveryLocations) changes.

**LANGUAGE**: XML

**CODE**:
```XML
<Annotations Target="NAMESPACE.ENTITYTYPE">
    <Annotation Term="com.sap.vocabularies.Common.v1.SideEffects" Qualifier="PriceChanged">
        <Record>
            <PropertyValue Property="SourceProperties">
                <Collection>
                    <PropertyPath>Amount</PropertyPath>
                    <PropertyPath>Discount</PropertyPath>
                    <PropertyPath>ProductDetail/DeliveryLocations</PropertyPath>// Source property pointing to multi input field
                </Collection>
            </PropertyValue>
            <PropertyValue Property="TargetProperties">
                <Collection>
                    <String>Price</String>
                </Collection>
            </PropertyValue>
        </Record>
    </Annotation>
</Annotations>
```

**STEP**: SupplierChanged — refresh 1:1 navigation target entity

**DESCRIPTION**: When Supplier changes, refresh the 1:1 navigation property toSupplier (the associated entity).

**LANGUAGE**: XML

**CODE**:
```XML
<Annotations Target="NAMESPACE.ENTITYTYPE">
    <Annotation Term="com.sap.vocabularies.Common.v1.SideEffects" Qualifier="SupplierChanged">
        <Record>
            <PropertyValue Property="SourceProperties">
                <Collection>
                    <PropertyPath>Supplier</PropertyPath>
                </Collection>
            </PropertyValue>
            <PropertyValue Property="TargetEntities">
               <Collection>
                   <NavigationPropertyPath>toSupplier</NavigationPropertyPath>
               </Collection>
            </PropertyValue>
        </Record>
    </Annotation>
</Annotations>
```

**STEP**: Field control causing full-entity read — Status triggers entity refresh

**DESCRIPTION**: If a single property (Status) change requires reading the whole entity (due to field control), define SideEffects with an empty NavigationPropertyPath entry in TargetEntities to force a full entity read/refresh.

**LANGUAGE**: XML

**CODE**:
```XML
<Annotations Target="NAMESPACE.ENTITYTYPE">
    <Annotation Term="com.sap.vocabularies.Common.v1.SideEffects" Qualifier="PriceChanged">
        <Record>
            <PropertyValue Property="SourceProperties">
                <Collection>
                    <PropertyPath>Status</PropertyPath>
                </Collection>
            </PropertyValue>
            <PropertyValue Property="TargetEntities">
                <Collection>
                    <NavigationPropertyPath></NavigationPropertyPath>
                </Collection>
            </PropertyValue>
        </Record>
    </Annotation>
</Annotations>
```

**STEP**: Structural change on 1:n association — refresh header property when item created/deleted

**DESCRIPTION**: When child collections change (create/delete), refresh header property OverallAmount by defining a SourceEntities entry for the 1:n association (toSalesOrderItems).

**LANGUAGE**: XML

**CODE**:
```XML
<Annotations Target="NAMESPACE.ENTITYTYPE">
    <Annotation Term="com.sap.vocabularies.Common.v1.SideEffects" Qualifier="ReactOnItemCreationOrDeletion">
        <Record>
            <PropertyValue Property="SourceEntities">
                <Collection>
                    <NavigationPropertyPath>toSalesOrderItems</NavigationPropertyPath>
                </Collection>
            </PropertyValue>
            <PropertyValue Property="TargetProperties">
                <Collection>
                    <String>OverallAmount</String>
                </Collection>
            </PropertyValue>
        </Record>
    </Annotation>
</Annotations>
```

**STEP**: Action side effects — refresh associated entity properties and entities after action

**DESCRIPTION**: For action/function import calls that change associated entities or properties, declare the expected SideEffects. Example: Setcurrency action refreshes Currency_Code_Text from to_Currency and also refreshes controls associated with to_Item.

**LANGUAGE**: XML

**CODE**:
```XML
<!-- In the below example, the function import action "Setcurrency" is expected to refresh
     the "Currency_Code_Text" which is coming from the associated entity "to_Currency" -->

<Annotations Target="STTA_SALES_ORDER_WD_20_SRV.STTA_SALES_ORDER_WD_20_SRV_Entities/Setcurrency">
    <Annotation Term="com.sap.vocabularies.Common.v1.SideEffects">
        <Record>
            <PropertyValue Property="TargetProperties">
                <Collection>
                    <PropertyPath>to_Currency/Currency_Code_Text</PropertyPath>
                </Collection>
            </PropertyValue>

            <!-- Side Effects for action annotation with an entity as a target.
                 Here, controls associated with "to_Item" will be refreshed -->
            <PropertyValue Property="TargetEntities">
                <Collection>
                    <NavigationPropertyPath>to_Item</NavigationPropertyPath>
                </Collection>
            </PropertyValue>
        </Record>
    </Annotation>
</Annotations>
```

**STEP**: Refresh navigation target — update root navigation entity when item property changes

**DESCRIPTION**: Use SourceProperties on item-level entity to cause refresh of the navigation to the root entity (to_SalesOrder). Two variants shown: refresh the whole navigation entity, and target specific/all properties (to_SalesOrder/*).

**LANGUAGE**: XML

**CODE**:
```XML
<Annotations Target="STTA_SALES_ORDER_WD_20_SRV.C_STTA_SalesOrderItem_WD_20Type">
    <Annotation Term="com.sap.vocabularies.Common.v1.SideEffects" Qualifier="TaxAmountChanged">
        <Record>
            <PropertyValue Property="SourceProperties">
                <Collection>
                     <PropertyPath>TaxAmount</PropertyPath>
                </Collection>
            </PropertyValue>
            <PropertyValue Property="TargetEntities">
               <Collection>
                     <NavigationPropertyPath>to_SalesOrder</NavigationPropertyPath>
                </Collection>
            </PropertyValue>
        </Record>
    <Annotation>
</Annotations>
```

**LANGUAGE**: XML

**CODE**:
```XML
<Annotations Target="STTA_SALES_ORDER_WD_20_SRV.C_STTA_SalesOrderItem_WD_20Type">
    <Annotation Term="com.sap.vocabularies.Common.v1.SideEffects" Qualifier="TaxAmountChanged">
        <Record>
            <PropertyValue Property="SourceProperties">
                <Collection>
                    <PropertyPath>TaxAmount</PropertyPath>
                </Collection>
            </PropertyValue>
            <PropertyValue Property="TargetProperties">
                <Collection>
                    <String>to_SalesOrder/*</String>
                </Collection>
            </PropertyValue>
        </Record>
    </Annotation>
</Annotations>
```

**STEP**: Side effect on 1:1 associated entity set property (smart field in smart form)

**DESCRIPTION**: Add a SideEffects annotation where the SourceProperties points to a 1:1 associated navigation property property (format: to_Rating/Rating/Property). This triggers side effect when the associated smart field changes.

**LANGUAGE**: XML

**CODE**:
```XML
<Annotations Target="<Schema Namespace>.<EntityType Name>">
    <Annotation Term="com.sap.vocabularies.Common.v1.SideEffects" Qualifier="<Qualifier Name (Optional)>">
        <PropertyValue Property="SourceProperties">
            <Collection>
                <PropertyPath><1:1 Associated Navigation Property Name.Ex:to_Rating/Rating>/<Property Name></PropertyPath>
            </Collection>
        </PropertyValue>
        <PropertyValue Property="TargetProperties">
            <Collection>
                <String><Target Property Name></String>
            </Collection>
        </PropertyValue>
    </Annotation>
</Annotations>
```

**STEP**: RAP / ABAP CDS — side effects block with fields, entities, actions, messages, permissions

**DESCRIPTION**: Use the ABAP CDS side effects block in BDEF/RAP modeling to define side effects for fields, entities, actions, and messages. This example demonstrates multiple targets, actions, and message targets. Copy this block into your CDS behavior definition (BDEF) as appropriate.

**LANGUAGE**: ABAP CDS

**CODE**:
```ABAP CDS
side effects {
    field IntegerValue affects field ProgressIntegerValue, field RadialIntegerValue;
    field Timestamp affects field IANATimestamp;
    field Supplier affects entity toSupplier;
    action changeCriticality affects field CriticalityCode;
    action resetTimesChildCreated affects field TimesChildCreated, permissions ( action resetTimesChildCreated );
    action overwriteTimezone affects $self;
    determine action validateDate executed on field ValidTo affects messages;
    $self affects permissions ( update _Child );
    determine action updateTimes executed on entity _Child affects field TotalPieces;
  }
```

fiori-elements-framework
side-effects
annotations
OData V2
OData V4
XML
ABAP
CDS
TriggerAction
MPC_EXT
function-import


**TITLE**: Side Effects — SAP Fiori elements (fiori-elements-framework)

**INTRODUCTION**: Practical, code-focused reference for annotating and handling side effects in SAP Fiori elements apps (OData V2 and V4). Use this when writing annotations, extension code, manifest entries, or CDS to ensure the UI refreshes affected properties/entities after backend changes.

**TAGS**: fiori-elements, side-effects, ODataV2, ODataV4, annotations, SAPUI5, manifest.json, CAP, CDS, XML, JavaScript

STEP: 1 — Default Side Effects

DESCRIPTION: Default side effects are provided by Fiori elements and typically require no annotation. Use annotations only when you must inform the front end about additional fields/entities affected by a backend change so the UI requests fresh data.

LANGUAGE: Text

CODE:
```text
Default behaviors include:
- Creating a new entity or draft: refresh list binding of parent page to show new entity.
- Deleting an entity: refresh parent page list binding to remove entity.
- Creating a draft for an active object: refresh list report to show new draft.
- Discarding/Activating a draft: refresh list report to remove draft and show active version.
- Triggering an action: refresh collection automatically when action is bound and returned instance does not match bound instance (e.g., copy).
```

STEP: 2 — Side Effect Annotation Format (high-level)

DESCRIPTION: Use side effect annotations to declare what triggers side effects and what must be refreshed. A side effect annotation contains:
- Source: property change, action, or structural change (create/delete subitem).
- Target: properties or entities to refresh.
- TriggerAction (optional): path to a function import to execute when side effect is triggered.
Note: TriggerAction replaces PreparationAction; EffectTypes is deprecated.

LANGUAGE: Text

CODE:
```text
Elements:
- Source (SourceProperties, SourceEntities)
- Target (TargetProperties, TargetEntities)
- TriggerAction (optional)
```

STEP: 3 — Source Properties (behavior & restrictions)

DESCRIPTION: Rules for source properties and virtual field groups:
- ValueHelp, ComboBox, CheckBox, DatePicker: side effect triggers when value is set or focus leaves control.
- Virtual field groups (list of properties): side effect triggers when focus moves away from the group.
- OData V2: define single property or list of properties as source; trigger when focus leaves property or field group.
Restriction: navigation properties cannot be used as SourceProperties.

LANGUAGE: Text

CODE:
```text
OData V2:
- SourceProperties: single property or collection forming a virtual field group.
- Triggers: on focus leave of source property or field group.
Restriction: No navigation properties allowed as source.
```

STEP: 4 — Source Entities (OData V2 vs OData V4)

DESCRIPTION: Use SourceEntities to specify navigation properties that trigger side effects due to structural changes or property changes.
- OData V2: only 1:n navigation properties can be SourceEntities; side effect triggered by structural change (add/delete).
- OData V4: any navigation property (1:1 or 1:n) can be SourceEntities; side effects triggered when any property of the entity changes or structural changes.
Caution: Do not specify a 1:1 association or an empty NavigationPropertyPath as source if you intend the whole entity to be the source.

LANGUAGE: Text

CODE:
```text
OData V2: SourceEntities supports only 1:n navigation properties (structural changes).
OData V4: SourceEntities supports 1:1 and 1:n navigation properties (property & structural changes).
```

STEP: 5 — Target Properties and Entities

DESCRIPTION: Define which properties or entities must be refreshed after source change:
- TargetProperties: a property or list of properties. You may use 1:1 navigation properties; front end will issue a $expand when needed.
- TargetEntities: specify 1:1 or 1:n navigation properties or an absolute path (entity container + entity) to refresh whole entity sets. If empty target is specified, the whole entity is updated.
- If TriggerAction exists and no TargetProperties/TargetEntities are defined, only the TriggerAction is called.

LANGUAGE: Text

CODE:
```text
- Always enclose the 'type' of TargetProperties in quotes when using SideEffectsType (see OData vocab).
- TargetEntities can be absolute paths: /Namespace.EntityContainer/EntityType
```

STEP: 6 — Example: Validation prevents side-effect trigger (EntityType)

DESCRIPTION: Example EDMX EntityType where validation (MaxLength) blocks side effects until errors are resolved.

LANGUAGE: XML

CODE:
```xml
<EntityType Name="SEPMRA_I_ProductCategoryType" sap:label="Category" sap:content-version="1">
    <Key>
        <PropertyRef Name="ProductCategory"/>
    </Key>
    <Property Name="ProductCategory" Type="Edm.String" Nullable="false" MaxLength="40" sap:label="Category"/>
    <Property Name="MainProductCategory" Type="Edm.String" MaxLength="40" sap:label="Main Category" sap:value-list="fixed-values"/>
    <NavigationProperty Name="to_MainCategory" Relationship="STTA_PROD_MAN.assoc_BBDC3EA034F824A7382F8EEF561C1160" FromRole="FromRole_assoc_BBDC3EA034F824A7382F8EEF561C1160" ToRole="ToRole_assoc_BBDC3EA034F824A7382F8EEF561C1160"/>
</EntityType>
```

STEP: 7 — Example: Side Effect Annotation (entity-level sample)

DESCRIPTION: XML local annotation sample showing SourceProperties and TargetEntities for side effect when ProductCategory/MainProductCategory change.

LANGUAGE: XML

CODE:
```xml
<Annotations Target="NAMESPACE.ENTITYTYPE">
    <Annotation Term="com.sap.vocabularies.Common.v1.SideEffects" Qualifier="ProductChanged">
        <Record>
            <PropertyValue Property="SourceProperties">
                <Collection>
                    <PropertyPath>ProductCategory</PropertyPath>
                    <PropertyPath>MainProductCategory</PropertyPath>
                </Collection>
            </PropertyValue>
            <PropertyValue Property="TargetEntities">
                <Collection>
                    <NavigationPropertyPath></NavigationPropertyPath>
                </Collection>
            </PropertyValue>
        </Record>
    </Annotation>
</Annotations>
```

STEP: 8 — OData V2: Additional features — global side effects & extension APIs

DESCRIPTION:
- You can define side effects in backend or local annotation files.
- For 1:n TargetEntities on tables, binding paging is not considered — use carefully.
- Global side effects: define side effect without source properties/entities (see Using Global Side Effects).
- For extension fields in forms/tables, register custom controls with extension API in onAfterRendering; the API returns a callback you must call from the control event handler with the field name to trigger side-effect processing.

LANGUAGE: Text

CODE:
```text
Extension APIs (OData V2):
- registerCustomFieldForSideEffect(oControl, FieldName, EntitySet) -> returns callback; call callback(FieldName) from event handler.
- registerCustomColumnForSideEffect(oTable, FieldName, EntitySet) -> returns callback; call callback(FieldName) from event handler.
Notes: navigation properties are not supported for custom fields; supported table types: responsive and grid tables.
```

STEP: 9 — Example: registerCustomFieldForSideEffect (form extension, OData V2)

DESCRIPTION: JavaScript extension code. Register a custom field for side effects in onAfterRendering and invoke the callback from the control event handler.

LANGUAGE: JavaScript

CODE:
```javascript
sap.ui.define("SOwoExt.ext.controller.ObjectPageExtension", ["sap/m/MessageBox"], function (MessageBox) {
    "use strict";
    var CustomFieldGroupChangeRegister;

    return {
        onCheckBoxEvent: function (oEvent) {
            var oView = this.getView();
            var model = oView.getModel();
            var context = oView.getBindingContext();
            var sFields = "SrcgProjNotesAreForbidden";
            var data = oEvent.getParameter("selected");

            model.setProperty(context.getPath() + "/" + sFields, data);
            CustomFieldGroupChangeRegister("SrcgProjNotesAreForbidden");
        },

        onAfterRendering: function (event) {
            var oView = this.getView();
            var sEntitySet = "C_STTA_SalesOrder_WD_20";
            var sProperty = "SrcgProjNotesAreForbidden";
            var oControl = sap.ui.getCore().getElementById(
                "SOwoExt::sap.suite.ui.generic.template.ObjectPage.view.Details::C_STTA_SalesOrder_WD_20--srcgProjNotesAreForbiddenCheckBox"
            );

            CustomFieldGroupChangeRegister = this.extensionAPI.registerCustomFieldForSideEffect(oControl, sProperty, sEntitySet);
        }
    };
});
```

STEP: 10 — Example: registerCustomColumnForSideEffect (table extension, OData V2)

DESCRIPTION: JavaScript extension code. Register a custom column in a table for side effects; invoke the returned callback from the column event handler.

LANGUAGE: JavaScript

CODE:
```javascript
sap.ui.define("SOwoExt.ext.controller.ObjectPageExtension", ["sap/m/MessageBox"], function (MessageBox) {
    "use strict";

    var CustomFieldGroupChangeRegister;

    return {
        onSubSectionEnteredExtension: function (subSection) {
            if (subSection.getId().indexOf("C_STTA_SalesOrder_WD_20--to_Item") !== -1) {
                var sourcingProjectItemTreeTable = this.oView.byId(
                    "SOwoExt::sap.suite.ui.generic.template.ObjectPage.view.Details::C_STTA_SalesOrder_WD_20--to_Item::com.sap.vocabularies.UI.v1.LineItem::responsiveTable"
                );

                sourcingProjectItemTreeTable.addEventDelegate(
                    {
                        onAfterRendering: function (oEvent) {
                            var oControl = this.oView.byId(
                                "SOwoExt::sap.suite.ui.generic.template.ObjectPage.view.Details::C_STTA_SalesOrder_WD_20--to_Item::com.sap.vocabularies.UI.v1.LineItem::responsiveTable"
                            );

                            CustomFieldGroupChangeRegister = this.extensionAPI.registerCustomColumnForSideEffect(
                                oControl,
                                "Raiseamount_ac",
                                "C_STTA_SalesOrderItem_WD_20"
                            );
                        },
                    },
                    this
                );
            }
        },

        onCheckBoxPressed: function (event) {
            var sProperty = "Raiseamount_ac";
            CustomFieldGroupChangeRegister(sProperty);
        },
    };
});
```

STEP: 11 — OData V4: Side Effects on Unbound Actions (XML sample)

DESCRIPTION: Define side effects on unbound actions using absolute paths. This example shows action import and a SideEffects annotation targeting a RootEntity, refreshing the entire entity list.

LANGUAGE: XML

CODE:
```xml
<Schema Namespace="sap.fe.core.Service" xmlns=http://docs.oasis-open.org/odata/ns/edm>
    <EntityContainer Name="EntityContainer">
        <ActionImport Name="unBoundAction" Action="sap.fe.core.Service.unBoundAction" />
        ...
    </EntityContainer>
    ...
    <Action Name="unBoundAction" IsBound="false" />
    ...
    <Annotations Target="sap.fe.core.Service.RootEntity">
        <Annotation Term="UI.LineItem" Qualifier="sample7">
            <Collection>
                <Record Type="UI.DataFieldForAction">
                    <PropertyValue Property="Label" String="Table Refresh" />
                    <PropertyValue Property="Action" String="sap.fe.core.Service.EntityContainer/unBoundAction" />
                    <PropertyValue Property="InvocationGrouping" EnumMember="UI.OperationGroupingType/ChangeSet" />
                </Record>
                ...
            </Collection>
        </Annotation>
    </Annotations>
    <Annotations Target="sap.fe.core.Service.UnboundAction()">
        <Annotation Term="Common.SideEffects">
            <Record Type="Common.SideEffectsType">
                <PropertyValue Property="TargetEntities">
                    <Collection>
                        <NavigationPropertyPath>"/sap.fe.core.Service.EntityContainer/RootEntity"
                        </NavigationPropertyPath>
                    </Collection>
                </PropertyValue>
            </Record>
        </Annotation>
    </Annotations>
</Schema>
```

STEP: 12 — OData V4: CAP CDS Sample (unbound action + side effects)

DESCRIPTION: CAP CDS example showing LineItem with unbound action and a side effect annotation using an absolute path to refresh RootEntity.

LANGUAGE: CDS

CODE:
```cds
// LineItem annotation with an unbound action
annotate RootEntity with @(
  UI    : {
        …
            LineItem : [
                {
                    $Type             : 'UI.DataFieldForAction',
                    Label             : 'My Unbound action',
                    Action            : 'MyService.EntityContainer/unBoundAction',
                    InvocationGrouping: #ChangeSet
                },
                {
                    $Type: 'UI.DataField',
                    Value: property1,
                },
                {
                    $Type: 'UI.DataField',
                    Value: property2
      },
      {
        $Type: 'UI.DataField',
        Value: property3
      }
    ],
  },
…
);

//actions and corresponding side effects for different samples
service MyService {

//Side effect annotation using an abosolute path
@Common.SideEffects: {TargetEntities: ['/MyService.EntityContainer/RootEntity']}
    action unBoundAction();
}
```

STEP: 13 — OData V4: Value List Refresh (absolute path target)

DESCRIPTION: If a value list is backed by transactional data or expected to change by actions/users, define an absolute side effect with the value list collection as TargetEntities to force refresh despite caching.

LANGUAGE: XML

CODE:
```xml
<Annotation Term="com.sap.vocabularies.Common.v1.SideEffects" Qualifier="ChangeOfProperty">
     <Record>
          <PropertyValue Property="SourceProperties">
               <Collection>
                    <PropertyPath>PropertyName</PropertyPath>
               </Collection>
          </PropertyValue>
          <PropertyValue Property="TargetEntities">
               <Collection>
                    <NavigationPropertyPath>/Namespace.EntityContainer/ValueListCollection</NavigationPropertyPath>
               </Collection>
          </PropertyValue>
     </Record>
</Annotation>
```

STEP: 14 — OData V4: Extension field in form via manifest.json

DESCRIPTION: When using custom extension fields in OData V4 forms, declare the property in manifest.json under controlConfiguration using the property key. Side effects execute when focus leaves the extension control if SourceProperties include the property.

LANGUAGE: JSON

CODE:
```json
"targets": {
    "MyObjectPage": {
        "type": "Component",
        "id": "Default",
        "name": "sap.fe.templates.ObjectPage",
        "level": 1,
        "options": {
            "settings": {
                "contextPath": "/RootEntity",
                "editableHeaderContent": true,
                "controlConfiguration": {
                    "@com.sap.vocabularies.UI.v1.Identification": {
                        "fields": {
                            "customFormElementIdentification1": {
                                "template": "sap.fe.core.fpmExplorer.customFormElementContent.CustomFormElement1",
                                "label": "Custom FormElement 1",
                                "property": "NameProperty"
                            }
                        }
                    }
                }
            }
        }
    }
}
```

STEP: 15 — Implementation Notes & Best Practices

DESCRIPTION:
- Validation errors block sending data to back end — side effects won't trigger until validation errors are resolved.
- For non-draft apps, source-property side effects trigger after a successful Save action; structural changes to items tables configured as source are supported.
- If using text arrangement or value list + key changes, annotate side effects so the text updates when a key changes.
- Use global side effects (no source) when needed to refresh parts of UI without a specific trigger.

LANGUAGE: Text

CODE:
```text
Best practices:
- Avoid using 1:n TargetEntities on paged tables unless you handle paging implications.
- For custom fields/columns register via the extension API and call the returned callback inside the control event handler with the FieldName.
- Use absolute paths in TargetEntities to refresh entire entity sets (OData V4).
```


**TITLE**: Smart Controls for SAP Fiori elements (OData V2) — Annotation-driven configuration

**INTRODUCTION**: This document explains how to control Smart Controls on a List Report page in SAP Fiori elements (OData V2) using OData annotations. It provides concise, copy-pasteable annotation examples (XML) and the manifest (JSON) wiring pattern to register annotation files. Use these examples as templates to implement Smart Table, Smart Filter Bar, Smart Field, Smart Link and Smart Form behavior via annotations.

**TAGS**: fiori-elements-framework, smart-controls, OData V2, annotations, smart-table, smart-filter-bar, smart-field, smart-link, smart-form

STEP: 1 — Confirm applicability

DESCRIPTION: Smart Controls configuration via OData annotations is supported only for SAP Fiori elements with OData V2. Before applying annotations, confirm your service and project use OData V2.

LANGUAGE: JSON

CODE:
```json
{
  "sap.app": {
    "id": "my.app.id",
    "applicationVersion": { "version": "1.0.0" }
  },
  "sap.ui5": {
    "models": {
      "": { "dataSource": "mainService" }
    }
  }
}
```

STEP: 2 — Add selection/filter annotations for Smart Filter Bar

DESCRIPTION: Use the UI.SelectionFields annotation on the entity set to describe which properties appear as selection fields in the Smart Filter Bar. Use PropertyPath entries for each filterable property.

LANGUAGE: XML

CODE:
```xml
<!-- annotations.xml (fragment) -->
<Annotations Target="MyService.ProductType">
  <Annotation Term="UI.SelectionFields">
    <Collection>
      <PropertyPath>ProductID</PropertyPath>
      <PropertyPath>Name</PropertyPath>
      <PropertyPath>Category</PropertyPath>
    </Collection>
  </Annotation>
</Annotations>
```

STEP: 3 — Define table columns for Smart Table (UI.LineItem)

DESCRIPTION: Define the columns displayed in a Smart Table using the UI.LineItem annotation on the EntityType. Use UI.DataField records for simple fields and UI.DataFieldForIntentBasedNavigation for navigation/links.

LANGUAGE: XML

CODE:
```xml
<!-- annotations.xml (fragment) -->
<Annotations Target="MyService.ProductType">
  <Annotation Term="UI.LineItem">
    <Collection>
      <Record Type="UI.DataField">
        <PropertyValue Property="Value" Path="ProductID"/>
        <PropertyValue Property="Label" String="Product ID"/>
      </Record>
      <Record Type="UI.DataField">
        <PropertyValue Property="Value" Path="Name"/>
        <PropertyValue Property="Label" String="Name"/>
      </Record>
      <Record Type="UI.DataFieldForIntentBasedNavigation">
        <PropertyValue Property="Label" String="Open Product"/>
        <PropertyValue Property="SemanticObject" String="Product"/>
        <PropertyValue Property="Action" String="display"/>
      </Record>
    </Collection>
  </Annotation>
</Annotations>
```

STEP: 4 — Create form layout and fields for Smart Form

DESCRIPTION: Use UI.FieldGroup (and nested UI.DataField records) to specify fields and groups for Smart Form layouts (Detail or Object Page). Qualifiers can distinguish multiple groups.

LANGUAGE: XML

CODE:
```xml
<!-- annotations.xml (fragment) -->
<Annotations Target="MyService.ProductType">
  <Annotation Term="UI.FieldGroup" Qualifier="General">
    <Record Type="UI.FieldGroupType">
      <PropertyValue Property="Data">
        <Collection>
          <Record Type="UI.DataField">
            <PropertyValue Property="Value" Path="Name"/>
            <PropertyValue Property="Label" String="Name"/>
          </Record>
          <Record Type="UI.DataField">
            <PropertyValue Property="Value" Path="Price"/>
            <PropertyValue Property="Label" String="Price"/>
          </Record>
        </Collection>
      </PropertyValue>
    </Record>
  </Annotation>
</Annotations>
```

STEP: 5 — Define navigation via Smart Link (intent-based navigation)

DESCRIPTION: Use UI.DataFieldForIntentBasedNavigation in LineItem or other annotations to enable Smart Link behavior that opens intent-based navigation targets.

LANGUAGE: XML

CODE:
```xml
<!-- annotations.xml (fragment) -->
<Annotations Target="MyService.ProductType">
  <Annotation Term="UI.LineItem">
    <Collection>
      <!-- ... other fields ... -->
      <Record Type="UI.DataFieldForIntentBasedNavigation">
        <PropertyValue Property="Label" String="Open"/>
        <PropertyValue Property="SemanticObject" String="Product"/>
        <PropertyValue Property="Action" String="display"/>
      </Record>
    </Collection>
  </Annotation>
</Annotations>
```

STEP: 6 — Register annotation files in manifest.json (local or service annotations)

DESCRIPTION: Register your service and annotation files in manifest.json so the Fiori elements runtime picks up annotations. Replace URIs and datasource names to match your project. This pattern shows OData V2 service plus a local annotation XML file referenced as an annotation data source.

LANGUAGE: JSON

CODE:
```json
{
  "sap.app": {
    "dataSources": {
      "mainService": {
        "uri": "/sap/opu/odata/sap/Z_SERVICE_SRV/",
        "type": "OData",
        "settings": { "odataVersion": "2.0" }
      },
      "annotations": {
        "uri": "annotations.xml",
        "type": "ODataAnnotation"
      }
    }
  },
  "sap.ui5": {
    "models": {
      "": { "dataSource": "mainService" },
      "annotations": { "dataSource": "annotations" }
    }
  }
}
```

STEP: 7 — Where to find more control-specific guidance

DESCRIPTION: For complete control-specific annotation reference and advanced options (e.g., variant management, personalization, table types), consult the smart control topics listed below (these are preserved file paths to the Fiori elements docs). Use these docs when you need control-specific annotation terms or UI variants.

LANGUAGE: Text/Links

CODE:
```text
- Smart Table: ../10_More_About_Controls/smart-table-bed8274.md
- Smart Filter Bar: ../10_More_About_Controls/smart-filter-bar-7bcdffc.md
- Smart Field: ../10_More_About_Controls/smart-field-4864403.md
- Smart Link: ../10_More_About_Controls/smart-link-f638884.md
- Smart Form: ../10_More_About_Controls/smart-form-99e33bd.md
```

STEP: 8 — Implementation checklist

DESCRIPTION: Quick checklist to deploy annotation-driven Smart Controls:
- Confirm OData V2 service usage.
- Add annotation XML fragments (SelectionFields, LineItem, FieldGroup, DataFieldForIntentBasedNavigation) to an annotations file.
- Register annotation file as a data source and model in manifest.json.
- Test the List Report page and Smart Filter Bar behavior in the running app.
- Consult the control-specific docs (links above) for advanced annotation terms and qualifiers.

LANGUAGE: Text

CODE:
```text
Checklist:
- OData version = 2.0
- annotations.xml added and contains UI.SelectionFields / UI.LineItem / UI.FieldGroup etc.
- manifest.json references annotation dataSource and model
- Run app and verify Smart Table, Smart Filter Bar, Smart Form, Smart Link
```

fiori-elements-framework
smart-controls
OData V2
annotations
smart-table
smart-filter-bar
smart-field
smart-link
smart-form


**TITLE**: Smart Table Extensions for Analytical List Page (ALP) — Controller, Column, and Row Navigation Extensions

**INTRODUCTION**: This guide shows how to implement ALP table extensions for SAP Fiori elements (OData V2): add an onBeforeRebindTableExtension controller hook, add custom table columns via view fragment extensions, and implement conditional row navigation using onListNavigationExtension. All changes are made in manifest.json (controller/view extensions) and extension JS/XML fragment files inside the app namespace.

**TAGS**: fiori-elements-framework, AnalyticalListPage, ALP, manifest.json, controllerExtensions, viewExtensions, fragments, OData V2, table-extensions, navigation

STEP: 1 — Applicability and short summary
DESCRIPTION: Confirm applicability and purpose.
LANGUAGE: JSON
CODE:
```json
{
  "note": "These extensions apply only to SAP Fiori elements for OData V2.",
  "purpose": "Use onBeforeRebindTableExtension to modify table binding before render, use sap.ui.viewExtensions to add custom Analytical columns via fragments, and use onListNavigationExtension for row-specific navigation (internal or external)."
}
```

STEP: 2 — Add controller extension entry in manifest.json to extend ALP controller
DESCRIPTION: In manifest.json, add sap.ui.controllerExtensions to extend the ALP controller. Replace controllerName with your app controller path (namespace). This enables ALP to call extension hook methods such as onBeforeRebindTableExtension and onListNavigationExtension.
LANGUAGE: JSON
CODE:
```json
{
  "sap.ui5": {
    "_version": "1.1.0",
    "extends": {
      "extensions": {
        "sap.ui.controllerExtensions": {
          "sap.suite.ui.generic.template.AnalyticalListPage.controller.AnalyticalListPage": {
            "controllerName": "sap.poc.ftu.apps.alr.ext.controller.AnalyticalListPageExt",
            "sap.ui.generic.app": {
              "": "..."
            }
          }
        }
      }
    }
  }
}
```

STEP: 3 — Implement onBeforeRebindTableExtension in the extension controller
DESCRIPTION: Create the extension controller file (controller.AnalyticalListPageExt under your app namespace). Implement onBeforeRebindTableExtension(oEvent) to run app-specific logic before the table is rebound. The event object contains binding and UI control references you can use to add filters or parameters to the table query.
LANGUAGE: JavaScript
CODE:
```javascript
// File: webapp/ext/controller/AnalyticalListPageExt.js (example path)
sap.ui.define([], function() {
    return {
        onBeforeRebindTableExtension: function(oEvent) {
            // Example: simple alert to verify extension is called.
            alert('onBeforeRebindTableExtension called!');

            // Example pattern: get binding info and add custom filter parameters
            // var oBindingParams = oEvent.getParameter("bindingParams");
            // oBindingParams.filters.push(new sap.ui.model.Filter("MyProperty", sap.ui.model.FilterOperator.EQ, "Value"));
        }
    };
});
```

STEP: 4 — Add view extension in manifest.json to provide custom Analytical table columns via fragment
DESCRIPTION: In manifest.json, add sap.ui.viewExtensions for the ALP view. Provide an entry with key "AnalyticalTableColumnsExtension|<EntitySetName>". The key format: "AnalyticalTableColumnsExtension|<EntitySet>" where the second part after "|" is the entity set. Set className to "sap.ui.core.Fragment", fragmentName to your fragment XML path (app namespace), and type to "XML".
LANGUAGE: JSON
CODE:
```json
{
  "sap.ui5": {
    "_version": "1.1.0",
    "extends": {
      "extensions": {
        "sap.ui.viewExtensions": {
          "sap.suite.ui.generic.template.AnalyticalListPage.view.AnalyticalListPage": {
            "AnalyticalTableColumnsExtension|CZ_EASILINEITEMS_SADL": {
              "className": "sap.ui.core.Fragment",
              "fragmentName": "sap.poc.ftu.apps.alr.ext.fragment.CustomColumn",
              "type": "XML"
            }
          }
        }
      }
    }
  }
}
```

STEP: 5 — Create XML fragment defining the custom AnalyticalColumn
DESCRIPTION: Implement the XML fragment referenced in manifest (fragmentName). Use table:AnalyticalColumn with header Label, template control, and p13nData in core:CustomData to provide personalization metadata (columnKey and columnIndex). Keep fragment namespace matching SAPUI5 controls.
LANGUAGE: XML
CODE:
```xml
<!-- File: webapp/ext/fragment/CustomColumn.fragment.xml (example path) -->
<core:FragmentDefinition xmlns:core="sap.ui.core"
          xmlns="sap.m" xmlns:table="sap.ui.table">
    <table:AnalyticalColumn width="150px" autoResizable="true">
        <Label text="My Extended Column"/> <!-- Column header name -->
        <table:template>
            <Label text="data"/> <!-- value in each cell of the table -->
        </table:template>
        <table:customData>
            <core:CustomData key="p13nData"
                  value='{"columnKey": "Test", "columnIndex" : "1"}' />
        </table:customData>
    </table:AnalyticalColumn>
</core:FragmentDefinition>
```

STEP: 6 — Implement onListNavigationExtension for conditional row navigation
DESCRIPTION: In the same extension controller, implement onListNavigationExtension(oEvent). Use this.extensionAPI.getNavigationController() to obtain the navigation controller. Decide target based on the selected row's binding context. Use navigateExternal(target) for external navigation. Return true to prevent default navigation, or return false to allow default ALP internal navigation.
LANGUAGE: JavaScript
CODE:
```javascript
// Add to the same extension controller file
onListNavigationExtension: function(oEvent) {
    var oNavigationController = this.extensionAPI.getNavigationController();
    var oBindingContext = oEvent.getSource().getBindingContext();
    var oObject = oBindingContext.getObject();
    // for notebooks we trigger external navigation for all others we use internal navigation
    if (oObject.CostCenter == "300-1000") {
        oNavigationController.navigateExternal("ActualCostsKPIDetails");
    } else {
        // return false to trigger the default internal navigation
        return false;
    }
    // return true is necessary to prevent further default navigation
    return true;
}
```

STEP: 7 — Implementation notes and best practices
DESCRIPTION: Keep the following implementation details:
- These APIs and extension points are specific to SAP Fiori elements for OData V2.
- manifest.json keys used: sap.ui.controllerExtensions and sap.ui.viewExtensions under sap.ui5 > extends > extensions.
- Use the full fragment/application namespace in fragmentName (e.g., sap.poc.ftu.apps.alr.ext.fragment.CustomColumn).
- Provide p13nData as JSON string in core:CustomData value to enable personalization (columnKey, columnIndex).
- Prefer extensionAPI.getNavigationController().navigateExternal() for external navigation to ensure ALP handles cross-app navigation correctly.

fiori-elements-framework
AnalyticalListPage
ALP
manifest.json
controllerExtensions
viewExtensions
fragments
OData V2
table-extensions
navigation