**TITLE**: Grouping Fields with UI.FieldGroup and UI.ConnectedFields (Fiori Elements)

**INTRODUCTION**: Practical, code-focused instructions to define and reference grouped and semantically connected fields in SAP Fiori Elements object pages and tables. Includes XML, ABAP CDS, CAP CDS, and manifest.json examples for FieldGroup, LineItem integration, ConnectedFields (OData V2/V4), table label display, textarea merging, and checkbox groups. Use these snippets directly when generating annotations or manifest settings.

**TAGS**: UI.FieldGroup, UI.ConnectedFields, LineItem, FieldGroup, Fiori Elements, OData V2, OData V4, ABAP CDS, CAP CDS, XML, manifest.json

STEP: 1 — Define a UI.FieldGroup in an Object Page (form-like grouping)
DESCRIPTION: Create a FieldGroup annotation to group related properties (arranged vertically or spilling to next column in a form). If all grouped fields are hidden, the container is hidden. Typical use: group address parts or dimensions in an object page form. Keep in mind: if there is no HeaderFacet and no images in HeaderInfo, expand/collapse/pin buttons in header are hidden. If a subsection contains only one group and the subsection title equals the group title, the group title is hidden.
LANGUAGE: XML
CODE:
```xml
<Annotation Term="UI.FieldGroup" Qualifier="Dimensions">
   <Record>
      <PropertyValue Property="Label" String="Dimensions"/>
      <PropertyValue Property="Data">
         <Collection>
            <Record Type="UI.DataField">
               <PropertyValue Property="Value" Path="BaseUnit"/>
            </Record>
            <Record Type="UI.DataField">
               <PropertyValue Property="Value" Path="Height"/>
            </Record>
            <Record Type="UI.DataField">
               <PropertyValue Property="Value" Path="Width"/>
            </Record>
            <Record Type="UI.DataField">
               <PropertyValue Property="Value" Path="Depth"/>
            </Record>
            <Record Type="UI.DataField">
               <PropertyValue Property="Value" Path="Weight"/>
            </Record>
         </Collection>
      </PropertyValue>
   </Record>
</Annotation>
```

LANGUAGE: ABAP CDS
CODE:
```
@UI.fieldGroup: [
  {
    type: #STANDARD,
    position: 1 ,
    qualifier: 'Dimensions',
    groupLabel: 'Dimensions'
  }
]
BaseUnit;

@UI.fieldGroup: [
  {
    type: #STANDARD,
    position: 2 ,
    qualifier: 'Dimensions'
  }
]
Height;

@UI.fieldGroup: [
  {
    type: #STANDARD,
    position: 3 ,
    qualifier: 'Dimensions'
  }
]
Width;

@UI.fieldGroup: [
  {
    type: #STANDARD,
    position: 4 ,
    qualifier: 'Dimensions'
  }
]
Depth;

@UI.fieldGroup: [
  {
    type: #STANDARD,
    position: 5 ,
    qualifier: 'Dimensions'
  }
]
Weight;
```

LANGUAGE: CAP CDS
CODE:
```
UI.FieldGroup #Dimensions : {
    $Type : 'UI.FieldGroupType',
    Label : 'Dimensions',
    Data : [
        {
            $Type : 'UI.DataField',
            Value : BaseUnit
        },
        {
            $Type : 'UI.DataField',
            Value : Height
        },
        {
            $Type : 'UI.DataField',
            Value : Width
        },
	{
            $Type : 'UI.DataField',
            Value : Depth
        },
	{
            $Type : 'UI.DataField',
            Value : Weight
        }
    ]
}
```

STEP: 2 — Reference the UI.FieldGroup from UI.Facets (object page form)
DESCRIPTION: To display the FieldGroup in the object page form, add a UI.ReferenceFacet that targets the FieldGroup annotation qualifier.
LANGUAGE: XML
CODE:
```xml
<Annotation Term="UI.Facets">
   <Collection>
      <Record Type="UI.ReferenceFacet">
         <PropertyValue Property="Label" String="Dimensions" />
         <PropertyValue Property="Target"AnnotationPath="@UI.FieldGroup#Dimensions"/>
      </Record>
   </Collection>
</Annotation>
```

LANGUAGE: ABAP CDS
CODE:
```
@UI.Facet: [
  {
    label: 'Dimensions',
    targetQualifier: 'Dimensions',
    type: #FIELDGROUP_REFERENCE,
    purpose: #STANDARD
  }
]
```

LANGUAGE: CAP CDS
CODE:
```
UI.Facets : [
    {
        $Type : 'UI.ReferenceFacet',
        Label : 'Dimensions',
        Target : '@UI.FieldGroup#Dimensions'
    }
]
```

STEP: 3 — Table Implementation: enable UI.FieldGroup inside a LineItem column
DESCRIPTION: To display multiple related fields stacked inside a table cell, add a UI.DataFieldForAnnotation under UI.LineItem that Target-refers to a UI.FieldGroup. Supported inner types: DataField, DataFieldForAction, DataFieldForAnnotation (for nested annotations, rating/progress indicators, or contact cards). Note: UI.FieldGroup is not supported in grid/tree/analytical tables. If using multiple DataFieldForAction buttons, omit the LineItem column Label to hide the column header.
LANGUAGE: XML
CODE:
```xml
<Annotation Term="UI.LineItem">
    <Collection>
        …………
        …………
        <Record Type="UI.DataFieldForAnnotation">
            <PropertyValue Property="Target" AnnotationPath="@UI.FieldGroup#FieldGroup1" />
            <PropertyValue Property="Label" String="Type Information"/>
        </Record>
        …………
        …………
    </Collection>
</Annotation>
```

LANGUAGE: ABAP CDS
CODE:
```
@UI.lineItem: [
  {
    label: 'Type Information',
    type: #AS_FIELDGROUP,
    valueQualifier: 'FieldGroup1'
  }
]
producttype;
```

LANGUAGE: CAP CDS
CODE:
```
UI.LineItem : [
    {
        $Type : 'UI.DataFieldForAnnotation',
        Target : '@UI.FieldGroup#FieldGroup1',
        Label : 'Type Information'
    }
]
```

STEP: 4 — Define the UI.FieldGroup used inside a LineItem (table column group)
DESCRIPTION: Define the FieldGroup qualifier referenced from the LineItem. This example mixes a DataField and a DataFieldForAction (dummy button). Preserve action URI for ABAP/remote action strings.
LANGUAGE: XML
CODE:
```xml
<Annotation Term="UI.FieldGroup" Qualifier="FieldGroup1">
    <Record>
        <PropertyValue Property="Data">
            <Collection>
                <Record Type="UI.DataField">
                    <PropertyValue Property="Value" Path="ContractType"/>
                </Record>
                <Record Type="UI.DataFieldForAction">
                    <PropertyValue Property="Label" String="Dummy Button"/>
                    <PropertyValue Property="Action" String="com.sap.gateway.srvd.sadl_gw_appmusicdr_definition.v0001.SOME_ACTION_2"/>
                </Record>
            </Collection>
        </PropertyValue>
    </Record>
</Annotation>
```

LANGUAGE: ABAP CDS
CODE:
```
@UI.fieldGroup: [
  {
    type: #STANDARD,
    position: 1 ,
    qualifier: 'FieldGroup1'
  }
]
ContractType;

@UI.fieldGroup: [
  {
    label: 'Dummy Button',
    dataAction: 'com.sap.gateway.srvd.sadl_gw_appmusicdr_definition.v0001.SOME_ACTION_2',
    type: #FOR_ACTION,
    position: 2 ,
    qualifier: 'FieldGroup1'
  }
]
contractName;
```

LANGUAGE: CAP CDS
CODE:
```
UI.FieldGroup #FieldGroup1 : {
    Data : [
        {
            $Type : 'UI.DataField',
            Value : ContractType
        },
        {
            $Type : 'UI.DataFieldForAction',
            Label : 'Dummy Button',
            Action : 'com.sap.gateway.srvd.sadl_gw_appmusicdr_definition.v0001.SOME_ACTION_2'
        }
    ]
}
```

STEP: 5 — Semantically Connected Fields (OData V2) — define ConnectedFields and include in FieldGroup
DESCRIPTION: For OData V2, use com.sap.vocabularies.UI.v1.ConnectedFields to display multiple properties side-by-side under one label with a Template. Reference this ConnectedFields annotation via UI.DataFieldForAnnotation inside a FieldGroup. Action: create ConnectedFields record with Data fields, Template and Label, then reference it from FieldGroup.
LANGUAGE: XML
CODE:
```
<Annotation Term="com.sap.vocabularies.UI.v1.ConnectedFields" Qualifier="ConnectedDateTime">
    <Record >
        <PropertyValue Property="Data">
            <Record >
                <PropertyValue Property="SalesOrderDate">
                    <Record Type="com.sap.vocabularies.UI.v1.DataField">
                        <PropertyValue Property="Value" Path="SalesOrderDate"/>
                    </Record>
                </PropertyValue>
                <PropertyValue Property="SalesOrderTime">
                    <Record Type="com.sap.vocabularies.UI.v1.DataField">
                        <PropertyValue Property="Value" Path="TrialTOD"/>
                    </Record>
                </PropertyValue>
            </Record>
        </PropertyValue>
        <PropertyValue Property="Label" String="Connected DateTime"/>
        <PropertyValue Property="Template" String="{SalesOrderDate} / {SalesOrderTime}"/>
    </Record>
</Annotation>

<Annotation Term="com.sap.vocabularies.UI.v1.ConnectedFields" Qualifier="ConnectedData">
    <Record >
        <PropertyValue Property="Data">
            <Record >
                <PropertyValue Property="PurchaseOrderByCustomer">
                    <Record Type="com.sap.vocabularies.UI.v1.DataField">
                        <PropertyValue Property="Value" Path="PurchaseOrderByCustomer"/>
                    </Record>
                </PropertyValue>
                <PropertyValue Property="ShippingCondition">
                    <Record Type="com.sap.vocabularies.UI.v1.DataField">
                        <PropertyValue Property="Value" Path="ShippingCondition"/>
                    </Record>
                </PropertyValue>
            </Record>
        </PropertyValue>
        <PropertyValue Property="Label" String="Connected Data"/>
        <PropertyValue Property="Template" String="{ShippingCondition} - {PurchaseOrderByCustomer}"/>
    </Record>
</Annotation>

.....
<Annotation Term="com.sap.vocabularies.UI.v1.FieldGroup" Qualifier="OrderData">
    <Record >
        <PropertyValue Property="Data">
            <Collection>
                <Record Type="com.sap.vocabularies.UI.v1.DataFieldForAnnotation">
                    <PropertyValue Property="Target" AnnotationPath="@UI.ConnectedFields#ConnectedDateTime"/>
                    <Annotation Term="UI.Importance" EnumMember="UI.ImportanceType/High"/>
                </Record>
                <Record Type="com.sap.vocabularies.UI.v1.DataFieldForAnnotation">
                    <PropertyValue Property="Target" AnnotationPath="@UI.ConnectedFields#ConnectedData"/>
                    <Annotation Term="UI.Importance" EnumMember="UI.ImportanceType/High"/>
                </Record>
            </Collection>
        </PropertyValue>
    </Record>
</Annotation>
```

STEP: 6 — Semantically Connected Fields (OData V4) — define ConnectedFields and reference in FieldGroup (XML, ABAP CDS, CAP CDS)
DESCRIPTION: For OData V4 use SAP__UI.ConnectedFields or UI.ConnectedFieldsType and reference via UI.DataFieldForAnnotation inside UI.FieldGroup. Restriction: connected fields only allowed in sections that belong to a form (not header sections).
LANGUAGE: XML
CODE:
```
...
<Annotation Term="UI.FieldGroup" Qualifier="OrderData">
    <Record Type="UI.FieldGroupType">
        <PropertyValue Property="Data">
            <Collection>
                <Record Type="UI.DataFieldForAnnotation">
                    <PropertyValue Property="Target" AnnotationPath="@UI.ConnectedFields#ConnectedOrderDates"/>
                </Record>
            </Collection>
        </PropertyValue>
    </Record>
</Annotation>
...
<Annotation Term="SAP__UI.ConnectedFields" Qualifier="ConnectedOrderDates">
<Record>
    <PropertyValue Property="Label" String="Order / Delivery"/>
    <PropertyValue Property="Template" String="{OrderDate}/{DeliveryDate}"/>
    <PropertyValue Property="Data">
        <Record Type="Core.Dictionary">
            <PropertyValue Property="OrderDate">
                <Record Type="SAP__UI.DataField">
                    <PropertyValue Property="Value" Path="OrderDate"/>
                </Record>
            </PropertyValue>
            <PropertyValue Property="DeliveryDate">
                <Record Type="SAP__UI.DataField">
                    <PropertyValue Property="Value" Path="DeliveryDate"/>
                </Record>
            </PropertyValue>
        </Record>
    </PropertyValue>
</Record>
</Annotation>
...
```

LANGUAGE: ABAP CDS
CODE:
```
annotate view SALESORDER with {
  ...
  @UI.facet: [
    {
      id: 'idIdentification',
      type: #IDENTIFICATION_REFERENCE,
    },
    ...
  ]
  ...
  @UI: {
    identification: [
      { type: #AS_CONNECTED_FIELDS, valueQualifier: 'ConnectedOrderDates' }
    ],
    connectedFields: [
      {
        name: 'OrderDate',
        qualifier: 'ConnectedOrderDates',
        template: '{OrderDate}/{DeliveryDate}',
        groupLabel: 'Order / Delivery'
      }
    ]
  }
  OrderDate;

  @UI: {
    connectedFields: [
      { name: 'DeliveryDate', qualifier: 'ConnectedOrderDates' }
    ]
  }
  DeliveryDate;

  ...
}
```

LANGUAGE: CAP CDS
CODE:
```
annotate SalesOrderService.SalesOrder with @UI : {

  FieldGroup #OrderData : {
    Data : [
      { $Type : 'UI.DataFieldForAnnotation', Target: '@UI.ConnectedFields#ConnectedOrderDates' }
    ]
  },
  ...

  ConnectedFields #ConnectedOrderDates: {
    $Type   : 'UI.ConnectedFieldsType',
    Label   : 'Order / Delivery',
    Template: '{OrderDate}/{DeliveryDate}',
    Data    : {
      $Type        : 'Core.Dictionary',
      OrderDate    : { $Type : 'UI.DataField', Value : OrderDate },
      DeliveryDate : { $Type : 'UI.DataField', Value : DeliveryDate }
    }
  },
  ...
}
```

STEP: 7 — Show field labels inside table FieldGroup columns (OData V4)
DESCRIPTION: To display labels for fields inside a table column where a FieldGroup is used, add controlConfiguration in manifest.json using the LineItem key (column key). Set showDataFieldsLabel to true.
LANGUAGE: JSON
CODE:
```
"controlConfiguration": {
   "@com.sap.vocabularies.UI.v1.LineItem": {
      columns: {
         "DataFieldForAnnotation::FieldGroup::myFieldGroup": {
            "showDataFieldsLabel": true
         }
      }
   }
}
```
NOTE: Use the appropriate column key for your LineItem column (see "Finding the Right Key for the Anchor").

STEP: 8 — Merge a single TextArea label with section/subsection title (manifest.json)
DESCRIPTION: When a FieldGroup contains only one UI.MultiLineText field and no other controls, hide the TextArea label and show only the section title by setting useSingleTextAreaFieldAsNotes = true at the section level in manifest.json. Ensure the text area still has an accessible label; mandatory text areas will always show labels in edit mode.
LANGUAGE: JSON
CODE:
```
"sap.ui5": {
        "routing": {
            "targets": {
                "SalesOrderManageObjectPage": {
                    "options": {
                        "settings": {
                            "content": {
                                "body": {
                                    "sections": {
                                        "ReferenceFacet1": {
                                            "useSingleTextAreaFieldAsNotes": true
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
```

STEP: 9 — Checkbox groups inside a FieldGroup (XML, ABAP CDS, CAP CDS) and horizontal layout
DESCRIPTION: Group multiple boolean (checkbox) properties under one FieldGroup by defining an inner FieldGroup qualifier containing DataFields (Boolean). Restrictions: only Boolean properties allowed inside checkbox group; not supported in header forms, filter bars, or tables; dynamic instantiation not supported; must define FieldControl for Boolean properties in behavior/metadata. Use manifest horizontalLayout to align checkboxes horizontally.
LANGUAGE: XML
CODE:
```
<Annotation Term="UI.FieldGroup" Qualifier="GeneralInformation">
    <Record Type="UI.FieldGroupType">
        <PropertyValue Property="Label" String="Line item data"/>
        <PropertyValue Property="Data">
            <Collection>
                <Record Type="UI.DataFieldForAnnotation">
                    <PropertyValue Property="Target" AnnotationPath="@UI.FieldGroup#CheckBoxGroup"/>
                </Record>
            </Collection>
        </PropertyValue>
    </Record>
</Annotation>
<Annotation Term="UI.FieldGroup" Qualifier="CheckBoxGroup">
    <Record Type="UI.FieldGroupType">
        <PropertyValue Property="Label" String="Standard CheckBoxGroup"/>
        <PropertyValue Property="Data">
            <Collection>
                <Record Type="UI.DataField">
                    <PropertyValue Property="Value" Path="Boolean1"/>
                    <PropertyValue Property="Label" String="Checkbox One"/>
                </Record>
                <Record Type="UI.DataField">
                    <PropertyValue Property="Value" Path="Boolean2"/>
                    <PropertyValue Property="Label" String="Checkbox Two"/>
                </Record>
                <Record Type="UI.DataField">
                    <PropertyValue Property="Value" Path="Boolean3"/>
                    <PropertyValue Property="Label" String="Checkbox Three"/>
                </Record>
            </Collection>
        </PropertyValue>
    </Record>
</Annotation>

<Annotations Target="sap.fe.core.FieldGroup.Products/Boolean1">
    <Annotation Term="Common.FieldControl" Int="7"/>
</Annotations>
<Annotations Target="sap.fe.core.FieldGroup.Products/Boolean3">
    <Annotation Term="Common.FieldControl">
        <If>
                <Path>Boolean2</Path>
                <Int>0</Int>
                <Int>3</Int>
        </If>
    </Annotation>
</Annotations>
```

LANGUAGE: ABAP CDS
CODE:
```
Define the following in the metadata extension of the data definition containing the Boolean fields:
...
@UI: {
    fieldGroup: [
        { qualifier: 'GeneralInformation', type: #AS_FIELDGROUP, valueQualifier: 'CheckBoxGroup', position: 10, label: 'CheckBox Group Label' },
        { qualifier: 'CheckBoxGroup', position: 10, label: 'Checkbox One' }
    ]
}
Boolean1;
    @UI: {
        fieldGroup: [
            { qualifier: 'CheckBoxGroup', position: 20, label: 'Checkbox Two'  }
        ]
    }
Boolean2;
    @UI: {
        fieldGroup: [
            { qualifier: 'CheckBoxGroup', position: 30, label: 'Checkbox Three'  }
        ]
    }
Boolean3;
...
```

LANGUAGE: CAP CDS
CODE:
```
...
Boolean1            : Boolean @Common.FieldControl: #Mandatory;
Boolean2            : Boolean;
Boolean3            : Boolean @Common.FieldControl: (Boolean2 ? 0 : 3);
// FieldControl can also be set as path based reference to property or expression binding
...
FieldGroup #CheckBoxGroup: {
    $Type: 'UI.FieldGroupType',
    Label: 'CheckBox Group Label',
    Data : [
        {
            $Type: 'UI.DataField',
            Value: Boolean1,
            Label: 'Checkbox One'
        },
        {
            $Type: 'UI.DataField',
            Value: Boolean2,
            Label: 'Checkbox Two'
        },
        {
            $Type: 'UI.DataField',
            Value: Boolean3,
            Label: 'Checkbox Three'
        }
    ]
},
...
FieldGroup #GeneralInformation: {
    Label: 'Line item data',
	Data : [
    {
        $Type : 'UI.DataFieldForAnnotation',
        Target: '@UI.FieldGroup#CheckBoxGroup'
    }
    ]
}
```

LANGUAGE: JSON
CODE:
```
"options": {
    "settings": {
         "entitySet": "Products",
         "content": {
             "body": {
                "sections": {
                     "@com.sap.vocabularies.UI.v1.FieldGroup#CheckBoxGroups": {
                         "subSections": {
                              "@com.sap.vocabularies.UI.v1.FieldGroup#CheckBoxGroupH1": {
                                  "horizontalLayout": true
            }
         }
        }
       }
       }
    }
  }
}
```

STEP: 10 — Navigation and limitations for semantically connected fields
DESCRIPTION: To make connected fields navigable render them as links — you must define navigation on the individual data fields inside ConnectedFields. Allowed navigation types: DataFieldWithURL, SemanticObject on the data field, DataFieldWithIntentBasedNavigation (Action optional), DataFieldWithNavigationPath. Restriction: Connected fields can only be used in form sections (not header). Also: UI.FieldGroup is not supported in grid, tree and analytical tables; table personalization supports filtering/sorting/grouping only on the individual properties of the same entity type contained in UI.FieldGroup's Data collection.

RELATED LINKS (for UI design and form guidance)
DESCRIPTION: Use SAP Fiori design system guidelines for forms and object page forms:
LANGUAGE: URL
CODE:
https://experience.sap.com/fiori-design-web/form/
https://experience.sap.com/fiori-design-web/object-page/#forms

UI.FieldGroup
UI.ConnectedFields
LineItem
FieldGroup
Fiori Elements
OData V2
OData V4
ABAP CDS
CAP CDS
XML
manifest.json


**TITLE**: Handling Inconsistent Input in SAP Fiori Elements (Draft & Non-Draft Apps)

**INTRODUCTION**: This guide explains how to detect and handle technical input inconsistencies (e.g., entering characters into numeric fields or exceeding field length) so the system prevents saving/activating drafts or persisting objects until those errors are resolved. It covers behavior for draft-enabled apps, subobject Apply actions, and non-draft OData V2 apps, and provides actionable code examples for integrating with SAPUI5 message management and save logic.

**TAGS**: fiori-elements-framework, sapui5, validation, draft, odata-v2, message-manager, save-blocking

**STEP**: 1 — Detect technical inconsistencies via UI5 MessageManager

**DESCRIPTION**: Technical inconsistencies (parse/format/validation errors thrown by bindings or UI controls) are surfaced through the SAPUI5 MessageManager. Register the view with the MessageManager and query the message model to determine whether any Error messages exist. Use this check to control save/activate/Apply actions.

**LANGUAGE**: JavaScript

**CODE**:
```javascript
// In your controller (before save/activate/apply action)
var oMessageManager = sap.ui.getCore().getMessageManager();
// Ensure messages for controls in this view are registered
oMessageManager.registerObject(this.getView(), true);

// Retrieve flat array of messages
var oMessageModel = oMessageManager.getMessageModel();
var aMessages = oMessageModel.getData() || [];

// Check if any Error-type messages exist (technical inconsistencies)
var bHasErrors = aMessages.some(function (m) {
  return m.type === sap.ui.core.MessageType.Error;
});

// bHasErrors == true means there are technical errors that must be resolved
```

**STEP**: 2 — Block save/activate/Apply until technical errors are resolved

**DESCRIPTION**: Prevent draft activation, draft save, object save, or subobject Apply when technical Error messages exist. Inform users with a focused message instructing them to correct the inconsistent inputs. Use a modal or message toast with clear text: "Resolve technical errors before saving/activating/applying."

**LANGUAGE**: JavaScript

**CODE**:
```javascript
// Example: intercept Save/Activate/Apply button press
onSavePress: function () {
  var oMessageManager = sap.ui.getCore().getMessageManager();
  var aMessages = oMessageManager.getMessageModel().getData() || [];
  var bHasErrors = aMessages.some(function (m) {
    return m.type === sap.ui.core.MessageType.Error;
  });

  if (bHasErrors) {
    // Inform user and prevent save
    sap.m.MessageBox.error("Resolve technical errors before saving.");
    return; // block actual save/activate/apply flow
  }

  // Proceed with normal save/activate/apply logic
  this._proceedWithSave();
}
```

**STEP**: 3 — Draft-enabled apps: ensure UI equals draft before activation or when Apply is used on subobjects

**DESCRIPTION**: In draft-enabled apps, the system requires that UI content and the stored draft are identical before activating or saving the draft. The same requirement applies when using the Apply button on a subobject page — the system must align UI and draft content. Use the MessageManager check to prevent activation or Apply while technical inconsistencies exist. After the user resolves all errors, allow activation/Apply to continue.

**LANGUAGE**: JavaScript

**CODE**:
```javascript
// Hook to "Activate Draft" or "Apply" events
onActivateDraft: function () {
  var oMM = sap.ui.getCore().getMessageManager();
  var aMsgs = oMM.getMessageModel().getData() || [];
  var bHasErrors = aMsgs.some(function (m) {
    return m.type === sap.ui.core.MessageType.Error;
  });

  if (bHasErrors) {
    sap.m.MessageBox.error("Correct the errors in the UI so the draft and UI match, then activate.");
    return;
  }

  // If no technical errors, proceed to activate the draft
  this._activateDraft();
}
```

**STEP**: 4 — Distinguish technical inconsistencies from logical/business validation

**DESCRIPTION**: The system message displayed to block save/activation lists only technical inconsistencies (parse/format/field-length issues). Logical or business validation errors (for example, entering a non-existent business partner) are reported as state messages during actual save operations and should be handled separately (e.g., server-side validation error handling and state message display).

**LANGUAGE**: JSON / JavaScript (example handling strategy)

**CODE**:
```javascript
// Example: After server save attempt, handle business/state messages separately
this.getModel().submitChanges({
  success: function (oResponse) {
    // handle success
  },
  error: function (oError) {
    // parse server response for business/state messages and surface as state messages
    // Do NOT treat these as the "technical inconsistencies" that block client-side save pre-checks
    this._showStateMessagesFromServer(oError);
  }.bind(this)
});
```

**STEP**: 5 — Non-draft OData V2 apps: block object save until technical errors are fixed

**DESCRIPTION**: For non-draft OData V2 apps, apply the same client-side pre-save checks. Before calling the OData model's create/update/submit operation, check the MessageManager for Error-type messages and block the call until users fix the input. After resolving errors, proceed with the save call.

**LANGUAGE**: JavaScript

**CODE**:
```javascript
// Example pre-check before creating/updating an entity in OData V2 app
onSaveEntity: function () {
  var oMM = sap.ui.getCore().getMessageManager();
  var aMsgs = oMM.getMessageModel().getData() || [];
  var bHasErrors = aMsgs.some(function (m) {
    return m.type === sap.ui.core.MessageType.Error;
  });

  if (bHasErrors) {
    sap.m.MessageBox.error("Resolve the input errors before saving the object.");
    return;
  }

  // No technical errors => proceed to call OData create/update
  this.getModel().create("/EntitySet", oPayload, {
    success: function () { /* ... */ },
    error: function () { /* ... */ }
  });
}
```

fiori-elements-framework sapui5 validation draft odata-v2 message-manager save-blocking


**TITLE**: Handling the preferredMode Parameter (SAP Fiori Elements, OData V2 & V4)

**INTRODUCTION**: Configure how an object page is launched (display, edit, create, or call an unbound action) using the preferredMode parameter. This guide provides the exact URL, manifest, metadata, and Component.js examples required to implement startup behavior and to pass prefill parameters for both OData V2 and OData V4 SAP Fiori Elements apps.

**TAGS**: fiori-elements-framework, preferredMode, manifest.json, OData V2, OData V4, create, edit, callUnboundAction, inboundParameters, NewAction

STEP: 1 — Quick reference: supported preferredMode values and behaviors

DESCRIPTION: Reference of allowed preferredMode values and their high-level behavior. Use these when building URLs, setting startup parameters, or configuring manifest defaults.

LANGUAGE: JSON

CODE:
```JSON
{
  "preferredMode values": [
    "display",                 // open object page in display (unless draft exists → edit)
    "edit",                    // open object page in edit mode, create draft if none
    "create",                  // open Create Object Page (POST or NewAction)
    "callUnboundAction",       // trigger specified unbound action on startup
    "createWith:<action>",     // (OData V4) call specified action and open create
    "autoCreateWith:<action>"  // (OData V4) same as createWith but auto-skip dialog if all params resolved
  ],
  "note": "If target app has no object page or external navigation overrides internal navigation, the list report is shown (no double navigation)."
}
```

STEP: 2 — Launching Create Mode via URL (basic examples)

DESCRIPTION: Use preferredMode=create in external navigation URLs to open the object page directly in create mode. You can append field=value pairs to prefill values.

LANGUAGE: text

CODE:
```text
#SalesOrder-manage?preferredMode=create
#Defect-displayWorklist?preferredMode=create&DefectCategory=01
```

STEP: 3 — OData V2: Allow URL parameters for create (manifest inboundParameters useForCreate)

DESCRIPTION: For POST-based create in OData V2, the target app must declare which incoming URL parameters are allowed for creation in manifest.json. Only parameters marked useForCreate are sent to the backend during the POST create call.

LANGUAGE: JSON

CODE:
```JSON
"sap.ui.generic.app": {
   "_version": "1.2.0",
   "settings": {
      ...
      "inboundParameters": {
         "DefectCategory": {
            "useForCreate": true
         }
      }
   },
   "pages": [
      {
         ...
```

STEP: 4 — OData V2: callUnboundAction — manifest configuration, metadata, and example URL

DESCRIPTION: Configure callUnboundAction to automatically call an unbound function import at app startup. In manifest.json map a logical action name to backend function imports using useForActionResolution. Define the function imports in service metadata (metadata.xml). The source app starts navigation with preferredMode=callUnboundAction and passes myActionName plus inbound parameter values in the URL.

LANGUAGE: JSON

CODE:
```JSON
"sap.ui.generic.app": {
   "_version": "1.2.0",
   "settings": {
      ...
      "inboundParameters": {
         "myActionName": {
            "useForActionResolution": {
              "myCreateWithNameAndStreet": "myCreate1",
              "myCreateWithoutNameAndStreet": "myCreate3",
            }
         }
```

LANGUAGE: XML

CODE:
```XML
<FunctionImport Name="myCreate1" ReturnType="cds_zvd_drafts_customer_sd.CustomerType" EntitySet="Customer" m:HttpMethod="POST">
  <Parameter Name="ResultIsActiveEntity" Type="Edm.Boolean" Mode="In" Nullable="true" sap:label="Result is active"/>
  <Parameter Name="Name" Type="Edm.String" Mode="In" MaxLength="40" Nullable="true" sap:label="Customer Name"/>
  <Parameter Name="Street" Type="Edm.String" Mode="In" MaxLength="40" Nullable="true" sap:label="Customer Street"/>
</FunctionImport>
<FunctionImport Name="myCreate3" ReturnType="cds_zvd_drafts_customer_sd.CustomerType" EntitySet="Customer" m:HttpMethod="POST">
  <Parameter Name="ResultIsActiveEntity" Type="Edm.Boolean" Mode="In" Nullable="true" sap:label="Result is active"/>
</FunctionImport>
```

LANGUAGE: text

CODE:
```text
#NewActionTest-NewActionTest?preferredMode=callUnboundAction&myActionName=myCreate1&ResultIsActiveEntity=true&Name=myName
```

STEP: 5 — OData V4: Configure createWith and autoCreateWith in manifest

DESCRIPTION: For OData V4 you can set preferredMode defaults that call a specified action when the app is opened in create mode. Use createWith:<action> to always open the action dialog; use autoCreateWith:<action> to auto-skip the dialog if the navigation context supplies values for all action parameters.

LANGUAGE: JSON

CODE:
```JSON
"preferredMode": {
     "defaultValue": {
          "value": "createWith:com.c_salesordermanage_sd.CreateWithSalesOrderType",
          "format": "value"
     }
},
```

LANGUAGE: JSON

CODE:
```JSON
"preferredMode": {
     "defaultValue": {
          "value": "autoCreateWith:com.c_salesordermanage_sd.CreateWithSalesOrderType",
          "format": "value"
     }
},
```

STEP: 6 — OData V4: Rules for create parameter prefilling (POST vs NewAction)

DESCRIPTION: Behavior differs by creation method:
- POST-based create: Only URL parameters listed under inboundParameters with useForCreate=true in manifest.json are included in the backend create call.
- NewAction (NewAction()/function import) based create: Navigation context values are mapped to action parameter dialog fields by exact technical name match; manifest useForCreate is ignored. Hidden action parameters that match are still populated.

LANGUAGE: JSON

CODE:
```JSON
"options": {
    "settings": {
        "contextPath": "/SalesOrderManage", // Object Page
        ...
        "inboundParameters": {
             "SalesOrderType": {
                "useForCreate": true
             }
        }
    }
}
```

EXAMPLE (behavior):
```text
Incoming URL:
#SalesOrder-manage?preferredMode=create&SalesOrderType=OR&Supplier=ABC

Result for POST-based create:
Only SalesOrderType=OR is passed to backend (Supplier ignored unless configured useForCreate=true).

Result for NewAction-based create:
Matching action parameter fields receive values from the navigation context by exact name match; useForCreate is not used.
```

STEP: 7 — preferredMode=edit: configure via startup parameters (Component.js) or URL

DESCRIPTION: preferredMode=edit opens the object page directly in edit mode (creates a draft if none exists). You can configure it as a startup parameter in Component.js or pass it directly in the URL with the object key.

LANGUAGE: JavaScript

CODE:
```JavaScript
sap.ui.define(["sap/fe/core/AppComponent"], function(AppComponent)
    "use strict";

    return AppComponent.extend("FormTemplate.Component", {
        metadata: {
            manifest: "json"
        },
        getStartupParameters: function() {
            return Promise.resolve({
                preferredMode: ["edit"],
                ID: "1"
            });
        }
    });
);
```

LANGUAGE: text

CODE:
```text
#Manage-items?preferredMode=edit&ID=1
```

STEP: 8 — Implementation checklist (practical steps for code generation)

DESCRIPTION: Actionable checklist for implementing preferredMode behavior in your app and caller:
- Decide which preferredMode value is needed (display/edit/create/callUnboundAction/createWith/autoCreateWith).
- If using POST-based create, add inboundParameters entries with useForCreate=true in target app manifest.json for every URL parameter you want passed to backend.
- If using callUnboundAction (V2) or NewAction (V4), map logical action names in manifest to backend function imports and add corresponding FunctionImport definitions in metadata.xml.
- For V4 createWith/autoCreateWith, set preferredMode.defaultValue.value in manifest.json to "createWith:<action>" or "autoCreateWith:<action>".
- For startup parameter configuration, implement getStartupParameters in Component.js or configure startup params in FLP.
- Test external navigation URLs in the format:
  - #EntitySet-manage?preferredMode=create&Field=Value
  - #EntitySet-manage?preferredMode=callUnboundAction&myActionName=ActionLogicalName&Param=Value
  - #EntitySet-manage?preferredMode=edit&ID=<key>

CODE:
```text
// No additional code. Follow the manifest/metadata/URL examples in previous steps.
```

fiori-elements-framework
preferredMode
manifest.json
OData V2
OData V4
create
edit
callUnboundAction
inboundParameters
NewAction


**TITLE**: Handling Semantic Key Fields in SAP Fiori Elements

**INTRODUCTION**: How to declare semantic key fields for entity types and how SAP Fiori elements renders those fields in list report tables (responsive and grid/other tables). Includes XML, ABAP CDS, and CAP CDS annotation examples and UI behavior rules for OData V2 and V4.

**TAGS**: fiori-elements-framework, semantic-key, annotations, CDS, CAP, OData, UI5, list-report, responsive-table

**STEP**: 1 — Add SemanticKey using XML Annotation

**DESCRIPTION**: Add a Common.SemanticKey annotation to your service metadata or annotation XML file. Set Target to the entity type and include the property (DataField) name(s) used as the semantic key. This works for default DataField only.

**LANGUAGE**: XML

**CODE**:
```xml
<Annotations xmlns="http://docs.oasis-open.org/odata/ns/edm" Target="STTA_PROD_MAN.STTA_C_MP_ProductType">
    <Annotation Term="Common.SemanticKey">
        <Collection>
            <PropertyPath>ProductForEdit</PropertyPath>
        </Collection>
    </Annotation>
</Annotations>
```

**STEP**: 2 — Add SemanticKey in ABAP CDS

**DESCRIPTION**: In ABAP CDS, declare the semanticKey in the @ObjectModel annotation for the CDS view that represents your entity. Use the property name(s) as strings in the semanticKey array. This annotation is consumed by Fiori elements to identify the semantic key field.

**LANGUAGE**: ABAP CDS

**CODE**:
```
@ObjectModel: {
  semanticKey: [ 'ProductForEdit' ]
}

define view C_MP_PRODUCT {

}
```

**STEP**: 3 — Add SemanticKey in CAP CDS

**DESCRIPTION**: For SAP Cloud Application Programming Model (CAP) CDS, annotate the entity type with Common.SemanticKey and list the semantic key property name(s). Place this annotation in your CDS module where the entity is defined or in a separate annotation file.

**LANGUAGE**: CAP CDS

**CODE**:
```
annotate STTA_PROD_MAN.STTA_C_MP_ProductType @(
  Common.SemanticKey : [ ProductForEdit ]
);
```

**STEP**: 4 — Availability Note

**DESCRIPTION**: Important constraint: The semantic key setting is only available for the default DataField. Ensure the field you annotate is the default DataField used in list report tables.

**LANGUAGE**: Text

**CODE**:
```
Note: This setting is only available for the default `DataField`.
```

**STEP**: 5 — Responsive Table Rendering Logic

**DESCRIPTION**: Fiori elements renders semantic key fields in responsive tables using sap.m.ObjectIdentifier. Rendering rules (implement these or expect default behavior in list reports):

- If text and ID are available: first line is bold text; second line is ID.
- If no text available: first line is bold ID; no second line.
- If a semantic object/link is associated with the field, ObjectIdentifier is not used — the ID is displayed as a link instead.

Include images in documentation if helpful: images/Semantic_Key_Fields_in_a_Table_Text_and_ID_d58b9d9.png

**LANGUAGE**: Text

**CODE**:
```
Responsive tables:
- Use ObjectIdentifier.
- Bold first line: text (if present), otherwise ID.
- Second line: ID only when text is present.
- If the field has a semantic object/link, do not render ObjectIdentifier; render the ID as a link.
```

**STEP**: 6 — Grid/Other Table Rendering and TextArrangement Differences (OData V2 vs V4)

**DESCRIPTION**: For non-responsive (grid or other) tables, Fiori elements renders a label and displays the entire content in bold. It also reads associated text and arranges ID/text according to TextArrangement and OData version:

- OData V2 (no TextArrangement configured): display ID with text in parenthesis if text exists; if no text, display only ID.
- OData V4 (no TextArrangement configured): display only the text if available; if no text, display only ID.
- When TextArrangement is configured (e.g., TextFirst), Fiori elements combines ID and text per that arrangement.

Include example image for TextFirst arrangement: images/Semantic_Key_Fields_in_a_Table_TextFirst_40b9a46.png

**LANGUAGE**: Text

**CODE**:
```
Grid/other tables:
- Use a bold label for the semantic key content.
- Combine ID and associated text based on TextArrangement config and OData version.

Behavior when TextArrangement is not configured:
- OData V2: ID (text) if text exists; else ID only.
- OData V4: text only if exists; else ID only.

If TextArrangement is configured (e.g., TextFirst), render ID and text per that arrangement.
```

**STEP**: 7 — Linking Behavior in Non-Responsive Tables

**DESCRIPTION**: Linking behavior differs between table types:

- Responsive tables: when a semantic object is linked, show the ID as a hyperlink (ObjectIdentifier is not used).
- Other tables (grid/list): when linked, display the entire content (ID and text) as a single link; wrapping is not applied.

**LANGUAGE**: Text

**CODE**:
```
Linking behavior:
- Responsive: ID displayed as a link (no ObjectIdentifier).
- Other tables: ID + text displayed together as one link, with no wrapping.
```

**STEP**: 8 — Applicability to Object Pages and Subobject Pages

**DESCRIPTION**: The same semantic key rendering logic used in list reports applies to object pages and subobject pages within Fiori elements for OData V4. Ensure your entity annotations are available to those pages.

**LANGUAGE**: Text

**CODE**:
```
Applicability:
- Semantic key rendering rules apply to list reports, object pages, and subobject pages (OData V4).
```

**STEP**: 9 — Related Settings and Further Configuration

**DESCRIPTION**: For additional table configuration options (annotations and manifest.json settings), consult the List Report Tables settings documentation.

**LANGUAGE**: Text

**CODE**:
```
See: Settings for List Report Tables
Link: settings-for-list-report-tables-4c2d17a.md
```

fiori-elements-framework semantic-key annotations CDS CAP OData UI5 list-report responsive-table


**TITLE**: Harvey Micro Chart Annotations (UI.Chart and UI.DataPoint)

**INTRODUCTION**: Use the Harvey (HarveyBallMicroChart) micro chart to display a single measure value against a maximum value. This guide provides required annotations and exact code examples (XML, ABAP CDS, CAP CDS). Follow the examples to implement the chart in Fiori Elements and ensure semantic coloring via Criticality if needed.

**TAGS**: fiori-elements-framework, harvey, microchart, UI.Chart, UI.DataPoint, annotations, CDS, XML, ABAP, CAP

**STEP**: 1 — UI.Chart (XML Annotation)

**DESCRIPTION**: Add a UI.Chart annotation to the metadata XML annotation file. The UI.Chart Title property maps to the chart title; Description maps to the subtitle. Ensure ChartType is set to "Pie", list your measure(s) under Measures, and set MeasureAttributes with DataPoint referencing the UI.DataPoint annotation (AnnotationPath="@UI.DataPoint").

**LANGUAGE**: XML

**CODE**:
```xml
<Annotation Term="UI.Chart" Qualifier="SpecificationWidthHarveyChart">
    <Record>
        <PropertyValue EnumMember="UI.ChartType/Pie" Property="ChartType" />
        <PropertyValue Property="Title" String="Sold to Produced Harvey Chart" />
        <PropertyValue Property="Description" String="Harvey Chart" />
        <PropertyValue Property="Measures">
            <Collection>
                <PropertyPath>Sold</PropertyPath>
            </Collection>
        </PropertyValue>
        <PropertyValue Property="MeasureAttributes">
            <Collection>
                <Record Type="UI.ChartMeasureAttributeType">
                    <PropertyValue Property="DataPoint" AnnotationPath="@UI.DataPoint" />
                </Record>
            </Collection>
        </PropertyValue>
    </Record>
</Annotation>
```

**STEP**: 2 — UI.Chart (ABAP CDS Annotation)

**DESCRIPTION**: Add the UI.Chart annotation to your ABAP CDS view. Use qualifier if needed. Ensure chartType is #PIE, measures list contains the measure property, and measureAttributes links the measure to a DataPoint (asDataPoint: true).

**LANGUAGE**: ABAP CDS

**CODE**:
```
@UI.Chart: [
  {
    title: 'Sold to Produced Harvey Chart',
    description: 'Harvey Chart',
    chartType: #PIE,
    measures: [
      'Sold'
    ],
    measureAttributes: [
      {
        measure: 'Sold',
        role: #AXIS_1,
        asDataPoint: true
      }
    ],
    qualifier: 'SpecificationWidthHarveyChart'
  }
]
annotate view STTA_C_MP_PRODUCT with {

}
```

**STEP**: 3 — UI.Chart (CAP CDS Annotation)

**DESCRIPTION**: For CAP model files, add the UI.Chart annotation syntax below. Ensure ChartType is #Pie, include Measures, and set MeasureAttributes with UI.ChartMeasureAttributeType and DataPoint referencing @UI.DataPoint.

**LANGUAGE**: CAP CDS

**CODE**:
```
UI.Chart #SpecificationWidthHarveyChart : {
    ChartType : #Pie,
    Title : 'Sold to Produced Harvey Chart',
    Description : 'Harvey Chart',
    Measures : [
        Sold
    ],
    MeasureAttributes : [
        {
            $Type : 'UI.ChartMeasureAttributeType',
            DataPoint : '@UI.DataPoint'
        }
    ]
}
```

**STEP**: 4 — UI.DataPoint (XML Annotation)

**DESCRIPTION**: Define the UI.DataPoint annotation in the annotation XML. Map Value to the measure, MaximumValue to the maximum reference, and Criticality to the property used for semantic coloring (optional). Include this DataPoint annotation where referenced by UI.Chart.MeasureAttributes.DataPoint.

**LANGUAGE**: XML

**CODE**:
```xml
<Annotation Term="UI.DataPoint">
    <Record>
        <PropertyValue Path="Sold" Property="Value" />
        <PropertyValue Path="Produced" Property="MaximumValue" />
        <PropertyValue Path="criticalityValue" Property="Criticality" />
    </Record>
</Annotation>
```

**STEP**: 5 — UI.DataPoint (ABAP CDS Annotation)

**DESCRIPTION**: In ABAP CDS, annotate the DataPoint details on the measure field or as a separate annotation block. Use criticality and/or maximumValue properties as shown.

**LANGUAGE**: ABAP CDS

**CODE**:
```
@UI.dataPoint: {
  criticality: 'criticalityValue',
  maximumValue: 20
}
Sold;
```

**STEP**: 6 — UI.DataPoint (CAP CDS Annotation)

**DESCRIPTION**: CAP CDS DataPoint example. Map Value, MaximumValue and Criticality to model properties. Use this DataPoint reference from UI.Chart.MeasureAttributes.DataPoint.

**LANGUAGE**: CAP CDS

**CODE**:
```
UI.DataPoint : {
    Value : Sold,
    MaximumValue : Produced,
    Criticality : criticalityValue
}
```

**STEP**: 7 — Mandatory Annotations and Semantic Coloring

**DESCRIPTION**: Ensure the following mandatory annotations and rules are applied for the Harvey micro chart to render correctly. For semantic coloring, only Criticality is supported.

**LANGUAGE**: text

**CODE**:
```
Mandatory annotations and rules:
- UI.Chart → ChartType: "Pie" (EnumMember UI.ChartType/Pie or #PIE / #Pie)
- UI.Chart → Measures: include the measure property (e.g., Sold)
- UI.Chart → MeasureAttributes → DataPoint: must reference the UI.DataPoint annotation (e.g., AnnotationPath="@UI.DataPoint" or asDataPoint in ABAP)
- UI.DataPoint → MaximumValue: must be provided (e.g., Produced)
- For semantic coloring (optional): UI.DataPoint → Criticality must be used (only Criticality is supported for coloring)

Mapping guidance:
- Title maps from UI.Chart.Title
- Subtitle maps from UI.Chart.Description
- Value (UI.DataPoint.Value) = measure property (e.g., Sold)
- MaximumValue (UI.DataPoint.MaximumValue) = maximum reference (e.g., Produced)
- Criticality (UI.DataPoint.Criticality) = property providing semantic status (e.g., criticalityValue)
```

fiori-elements-framework harvey microchart UI.Chart UI.DataPoint annotations CDS XML ABAP CAP


**TITLE**: Header Facets — defining and configuring object page header facets in SAP Fiori Elements

**INTRODUCTION**: Use UI.HeaderFacets to expose header facets (reference facets) in an Object Page header to show contact data, ratings, datapoints, and other header information. This document provides the exact annotation/code patterns for XML, ABAP CDS, and CAP CDS, explains desktop vs mobile behavior, shows how to enable the carousel on desktop (OData V2), and describes the stashing behavior (OData V4).

**TAGS**: fiori-elements-framework, UI.HeaderFacets, header-facets, object-page, manifest.json, showHeaderAsCarouselOnDesktop, stashing, OData V2, OData V4, CAP, ABAP, XML, CDS

STEP: 1 — UI.HeaderFacets (XML annotation)

DESCRIPTION: Use the UI.HeaderFacets annotation to define a collection of UI.ReferenceFacet entries. Each UI.ReferenceFacet targets a data point (AnnotationPath) or a navigation target with an annotation qualifier. Use PropertyValue Property="Target" with AnnotationPath values to reference @UI.DataPoint qualifiers or navigation target paths.

LANGUAGE: XML

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

STEP: 2 — UI.HeaderFacets (ABAP CDS annotation)

DESCRIPTION: Define header facets in ABAP CDS using @UI.Facet with entries that specify targetQualifier (qualifier of a datapoint), optional targetElement for navigation targets, type (#DATAPOINT_REFERENCE), and purpose (#HEADER).

LANGUAGE: ABAP

CODE:
```ABAP
@UI.Facet: [
    {
        targetQualifier: 'Price',
        type: #DATAPOINT_REFERENCE,
        purpose: #HEADER
    },
    {
        targetQualifier: 'StockAvailability',
        targetElement: 'TO_STOCKAVAILABILITY',
        type: #DATAPOINT_REFERENCE,
        purpose: #HEADER
    }
]Test;
```

STEP: 3 — UI.HeaderFacets (CAP CDS / CAP annotation)

DESCRIPTION: In CAP (service model annotation) annotate the entity/service to add UI.HeaderFacets. Use UI.ReferenceFacet entries with $Type = 'UI.ReferenceFacet' and Target referencing @UI.DataPoint qualifiers or navigation targets plus qualifier.

LANGUAGE: CDS

CODE:
```CDS
Annotate c_salesordermanage_sd.SalesOrderManage with @(
    UI : {
        HeaderFacets : [
            {
                $Type  : 'UI.ReferenceFacet',
                Label  : 'Price',
                ID     : 'Price',
                Target : '@UI.DataPoint#Price'
            },
            {
                $Type  : 'UI.ReferenceFacet',
                Label  : 'Stock Availability',
                ID     : 'StockAvailability',
                Target : 'to_StockAvailability@UI.DataPoint#StockAvailability'
            }
        ]
    }
)
```

STEP: 4 — Desktop vs Mobile behavior (visual/layout notes)

DESCRIPTION: Default rendering:
- Desktop: dynamic/static header with responsive layout (header facets in header area).
- Mobile: header container with horizontal layout and horizontal scrolling for header facets.
Preserve visuals in UI by testing on both device types. Images referenced in the original documentation:
- images/Header_Facet_Desktop_Version_b1c531e.png
- images/Header_Facets_Mobile_Version_8abec0d.png
- images/Desktop_Carousels_for_Header_Facet_6113e92.jpg

LANGUAGE: Text

CODE:
```Text
Desktop: dynamic/static header (responsive).
Mobile: header container with horizontal scroll for header facets.
Referenced images:
- images/Header_Facet_Desktop_Version_b1c531e.png
- images/Header_Facets_Mobile_Version_8abec0d.png
- images/Desktop_Carousels_for_Header_Facet_6113e92.jpg
```

STEP: 5 — Enable carousel header on desktop (OData V2) — manifest.json

DESCRIPTION: To render header facets as a carousel on desktops (instead of default dynamic/static header), set "showHeaderAsCarouselOnDesktop": true in each ObjectPage component's settings in manifest.json. Note: this setting must be applied at every component level where you want the carousel (top-level page component and nested page components).

LANGUAGE: JSON

CODE:
```JSON
"sap.ui.generic.app": {
    ...
    "pages": [
        {
            "entitySet": "STTA_C_MP_Product",
            "component": {
                "name": "sap.suite.ui.generic.template.ObjectPage",
                "settings": {
                    "showHeaderAsCarouselOnDesktop": true,
                    ...
                }
            },
            "pages": [
                {
                    "navigationProperty": "to_ProductText",
                    "entitySet": "STTA_C_MP_ProductText",
                    "component": {
                        "name": "sap.suite.ui.generic.template.ObjectPage",
                        "settings": {
                            "showHeaderAsCarouselOnDesktop": true,
                            ...
                        }
                    }
                }
            ]
        }
    ]
}
```

STEP: 6 — Stashing header facets (OData V4) — manifest.json & key-user adaptation

DESCRIPTION: In OData V4, header facets can be marked as stashed in manifest.json so they are not initially visible and are not loaded at application start. Key users can add stashed header facets at runtime using key user adaptation; once added they become visible to end users. For details see the Adapting the UI guide: adapting-the-ui-59bfd31.md.

LANGUAGE: Text

CODE:
```Text
Stashed header facets: define in manifest.json (stashed) => not loaded initially.
Key user adaptation can add these facets at runtime.
See: adapting-the-ui-59bfd31.md
```

fiori-elements-framework
UI.HeaderFacets
header-facets
object-page
manifest.json
showHeaderAsCarouselOnDesktop
stashing
OData V2
OData V4
CAP
ABAP
XML
CDS


**TITLE**: Hiding UI Elements with the UI.Hidden Annotation (Fiori Elements)

**INTRODUCTION**: Practical, code-focused reference for using the UI.Hidden annotation to hide or show UI features on Fiori Elements object pages (header facets, sections, quick views, field groups, facets, and table columns). Includes XML OData annotations, ABAP CDS and CAP CDS examples and rules for conditional hiding.

**TAGS**: UI.Hidden, annotation, Fiori Elements, OData V4, XML Annotations, ABAP CDS, CAP CDS, object page, header facets, quick view, field group, line item

STEP: 1 — UI.Hidden: semantics and conditional usage
DESCRIPTION: Use the UI.Hidden annotation to hide or show annotated properties, facets, or wrapper elements. Default behavior: UI.Hidden without explicit Bool is treated as true (hidden). You can set Bool="false" to show, Bool="true" to hide, or use Path/edmJSON for conditional hiding. When using Path, the path must reference a Boolean property. For conditional expression trees use edmJSON (SAPUI5 expression binding is not supported). Conditional edmJSON expressions apply only to SAP Fiori elements for OData V4.
LANGUAGE: XML
CODE:
```xml
<!-- Default (hidden) -->
<Annotation Term="UI.Hidden"/>

<!-- Explicit not hidden -->
<Annotation Term="UI.Hidden" Bool="false"/>

<!-- Explicit hidden -->
<Annotation Term="UI.Hidden" Bool="true"/>

<!-- Conditional based on a Boolean property -->
<Annotation Term="UI.Hidden" Path="edit_mode"/>

<!-- Conditional using expression (edmJSON) — OData V4 only -->
<Annotation Term="UI.Hidden">
    <If>
        <Or>
            <Eq>
                <Path>displayCriteria</Path>
                <String>value_A</String>
            </Eq>
            <Eq>
                <Path>displayCriteria</Path>
                <String>value_B</String>
            </Eq>
        </Or>
    </If>
</Annotation>
```

STEP: 2 — Hide Header Facets on Object Page (XML, ABAP CDS, CAP CDS)
DESCRIPTION: Hide specific header facets or conditionally hide them. Use UI.HeaderFacets in XML annotations, @UI.Facet in ABAP CDS, or HeaderFacets in CAP CDS. Note: You cannot hide entire UI.FieldGroup or UI.Identification by hiding the group—hide all underlying DataField records or hide the wrapper ReferenceFacet/DataFieldForAnnotation.
LANGUAGE: XML
CODE:
```xml
<Annotation Term="UI.HeaderFacets">
    <Collection>
        <Record Type="UI.ReferenceFacet">
            <PropertyValue Property="Label" String="Net Amount" />
            <PropertyValue Property="ID" String="NetValueDataHeader" />
            <PropertyValue Property="Target" AnnotationPath="@UI.DataPoint#NetValue" />
            <Annotation Term="UI.Hidden" Bool="true" />
        </Record>
        <Record Type="UI.ReferenceFacet">
            <PropertyValue Property="Label" String="Contact Info" />
            <PropertyValue Property="ID" String="ContactHeader" />
            <PropertyValue Property="Target" AnnotationPath="_SoldToParty/@Communication.Contact" />
             <Annotation Term="UI.Hidden" />
        </Record>
        <Record Type="UI.ReferenceFacet">
            <PropertyValue Property="Label" String="Credit Limit Consumption" />
            <PropertyValue Property="ID" String="CreditLimitChartHeader" />
            <PropertyValue Property="Target" AnnotationPath="_CreditLimitDetails/@UI.Chart#CreditLimitChart" />
             <Annotation Term="UI.Hidden" Path="editActionIsEnabled" />
        </Record>
    </Collection>
</Annotation>
```

LANGUAGE: ABAP CDS
CODE:
```abap
@UI.Facet: [
  {
    hidden: true,
    label: 'Net Amount',
    id: 'NetValueDataHeader',
    targetQualifier: 'NetValue',
    type: #DATAPOINT_REFERENCE,
    purpose: #HEADER
  },
  {
    hidden: true,
    label: 'Contact Info',
    id: 'ContactHeader',
    targetElement: '_SOLDTOPARTY',
    type: #CONTACT_REFERENCE,
    purpose: #HEADER
  },
  {
    hidden: #('editActionIsEnabled'),
    label: 'Credit Limit Consumption',
    id: 'CreditLimitChartHeader',
    targetQualifier: 'CreditLimitChart',
    targetElement: '_CREDITLIMITDETAILS',
    type: #CHART_REFERENCE,
    purpose: #HEADER
  }
]
Test;
```

LANGUAGE: CAP CDS
CODE:
```cds
HeaderFacets                                    : [
    {
        $Type             : 'UI.ReferenceFacet',
        Label             : 'Net Amount',
        ID                : 'NetValueDataHeader',
        Target            : '@UI.DataPoint#NetValue',
        ![@UI.Hidden] : true
     },
    {
        $Type             : 'UI.ReferenceFacet',
        Label             : Contact Info',
        ID                : 'ContactHeader',
        Target            : '_SoldToParty/@Communication.Contact',
        ![@UI.Hidden] : true
    },
    {
        $Type             : 'UI.ReferenceFacet',
        Label             : 'Credit Limit Consumption',
        ID                : 'CreditLimitChartHeader',
        Target            : '_CreditLimitDetails/@UI.Chart#CreditLimitChart',
        ![@UI.Hidden] : editActionIsEnabled
    }
    ]
```

STEP: 3 — Hide Sections and Subsections on Object Page
DESCRIPTION: To hide an entire section, annotate the CollectionFacet or child facet with UI.Hidden. To hide a subsection, hide the content within it (e.g., set UI.Hidden on the child facet). Examples for XML, ABAP CDS, CAP CDS below.
LANGUAGE: XML
CODE:
```xml
<Annotation Term="UI.Facets">
    <Collection>
        <Record Type="UI.CollectionFacet">
            <PropertyValue Property="Label" String="Header" />
            <PropertyValue Property="ID" String="HeaderInfo" />
            <PropertyValue Property="Facets">
                <Collection>
                    <Record Type="UI.CollectionFacet">
                        <PropertyValue Property="ID" String="GeneralInfo" />
                        <PropertyValue Property="Label" String="General Information" />
                        <PropertyValue Property="Facets">
                            <Collection>
                                ……..
                               …….
                            </Collection>
                        </PropertyValue>
                       <Annotation Term="UI.Hidden" Bool="true" />
                   </Record>
               </Collection>
           </PropertyValue>
       </Record>
    </Collection>
</Annotation>
```

LANGUAGE: ABAP CDS
CODE:
```abap
@UI.Facet: [
  {
    label: 'Header',
    id: 'HeaderInfo',
    type: #COLLECTION,
    purpose: #STANDARD
  },
  {
    hidden: true,
    id: 'GeneralInfo',
    label: 'General Information',
    parentId: 'HeaderInfo',
    purpose: #STANDARD
  },
  …..
  …..
]
Test;
```

LANGUAGE: CAP CDS
CODE:
```cds
Facets                                          : [
{
        $Type  : 'UI.CollectionFacet',
s
        Label  : 'Header',
        ID     : 'HeaderInfo',
        Facets : [
        {
                $Type             : 'UI.CollectionFacet',
                ID                : 'GeneralInfo',
                Label             : 'General Information',
                Facets            : [
                    ……
                   ……
                ],
                ![@UI.Hidden]     : true
        }]
}]
```

STEP: 4 — Hide Content in Quick Views
DESCRIPTION: Apply UI.Hidden to ReferenceFacet entries inside UI.QuickViewFacets to hide quick view content. Examples include static hiding and conditional hiding using Path.
LANGUAGE: XML
CODE:
```xml
<Annotation Term="UI.QuickViewFacets">
    <Collection>
        <Record Type="UI.ReferenceFacet">
            <PropertyValue Property="Label" String="Material" />
            <PropertyValue Property="Target" AnnotationPath="@Communication.Contact" />
            <Annotation Term="UI.Hidden" Bool="true" />
        </Record>
        <Record Type="UI.ReferenceFacet">
            <PropertyValue Property="Label" String="Address" />
            <PropertyValue Property="Target" AnnotationPath="@UI.FieldGroup#SoldToQuickView" />
            <Annotation Term="UI.Hidden" Path="edit_Ac" />
        </Record>
    </Collection>
</Annotation>
```

LANGUAGE: ABAP CDS
CODE:
```abap
@UI.Facet: [
  {
    hidden: true,
    label: 'Material',
    type: #CONTACT_REFERENCE,
    purpose: #QUICK_VIEW
  },
  {
    hidden: #('edit_Ac'),
    label: 'Address',
    targetQualifier: 'SoldToQuickView',
    type: #FIELDGROUP_REFERENCE,
    purpose: #QUICK_VIEW
  }
]
Test;
```

LANGUAGE: CAP CDS
CODE:
```cds
UI.QuickViewFacets        : [
   {
        $Type  : 'UI.ReferenceFacet',
        Label  : 'Material',
        Target : '@Communication.Contact',
        ![@UI.Hidden]     : true
    },
    {
        $Type  : 'UI.ReferenceFacet',
        Label  : 'Address',
        Target : '@UI.FieldGroup#SoldToQuickView',
        ![@UI.Hidden]     : edit_Ac
   }
]
```

STEP: 5 — Hide DataField Records in Header Facets (FieldGroup Qualifier)
DESCRIPTION: To hide specific DataField records within a FieldGroup qualifier, add UI.Hidden to each DataField entry (static Bool or Path-based). Use ABAP CDS @UI.fieldGroup or CAP CDS FieldGroup equivalents.
LANGUAGE: XML
CODE:
```xml
<Annotation Term="UI.FieldGroup" Qualifier="OrgData">
    <Record Type="UI.FieldGroupType">
        <PropertyValue Property="Data">
            <Collection>
                <Record Type="UI.DataField">
                    <PropertyValue Property="Value" Path="SalesOrganization" />
                    <Annotation Term="UI.Hidden" Bool="true" />
                </Record>
               <Record Type="UI.DataField">
                   <PropertyValue Property="Value" Path="DistributionChannel" />
                   <Annotation Term="UI.Hidden" Path="Delivered" />
               </Record>
            </Collection>
        </PropertyValue>
    </Record>
</Annotation>
```

LANGUAGE: ABAP CDS
CODE:
```abap
@UI.fieldGroup: [
  {
    hidden: true,
    value: 'SALESORGANIZATION',
    type: #STANDARD,
    qualifier: 'OrgData'
  }
]
SALESORGANIZATION;

@UI.fieldGroup: [
  {
    hidden: #('Delivered'),
    value: 'DISTRIBUTIONCHANNEL',
    type: #STANDARD,
    qualifier: 'OrgData'
  }
]
DISTRIBUTIONCHANNEL;
```

LANGUAGE: CAP CDS
CODE:
```cds
FieldGroup #OrgData                             : [
{
        Label : 'Org Data',
        Data  : [
        {
            $Type             : 'UI.DataField',
            Value             : SalesOrganization,
            ![@UI.Hidden]     : true
        }
        {
            $Type             : 'UI.DataField',
            Value             : DistributionChannel,
            ![@UI.Hidden]     : Delivered
        }]
}]
```

STEP: 6 — Hide DataField Records in Facets (OrderData example)
DESCRIPTION: Hide DataField entries inside FieldGroup qualifiers used in facets. To hide an entire FieldGroup or Identification, either hide every DataField inside or hide the wrapper ReferenceFacet/DataFieldForAnnotation.
LANGUAGE: XML
CODE:
```xml
<Annotation Term="UI.FieldGroup" Qualifier="OrderData">
     <Record Type="UI.FieldGroupType">
         <PropertyValue Property="Data">
            <Collection>
                <Record Type="UI.DataField">
                    <PropertyValue Property="Value" Path="SoldToParty" />
                    <Annotation Term="UI.Hidden" Bool="true" />
                </Record>
                <Record Type="UI.DataField">
                    <PropertyValue Property="Value" Path="ImageUrl" />
                    <Annotation Term="UI.Hidden" Path="edit_Ac" />
                </Record>
                 …..
                   ……
            </Collection>
        </PropertyValue>
    </Record>
</Annotation>
```

LANGUAGE: ABAP CDS
CODE:
```abap
@UI.fieldGroup: [
  {
    hidden: true,
    value: 'SOLDTOPARTY',
    type: #STANDARD,
    qualifier: 'OrderData'
  }
]
SOLDTOPARTY;

@UI.fieldGroup: [
  {
    hidden: #('edit_Ac'),
    value: 'IMAGEURL',
    type: #STANDARD,
    qualifier: 'OrderData'
  }
]
IMAGEURL;
```

LANGUAGE: CAP CDS
CODE:
```cds
FieldGroup #OrderData                           : {Data : [
   {
        $Type             : 'UI.DataField',
        Value             : SoldToParty,
        ![@UI.Hidden]     : true
   },
   {
        $Type             : 'UI.DataField',
        Value             : ImageUrl,
        ![@UI.Hidden]     : edit_Ac
    },
    …..
   ……
]}
```

STEP: 7 — Hide DataField Records in Tables (LineItem)
DESCRIPTION: For table columns (LineItem), a column is not rendered when the static UI.Hidden is set to true on the DataField (DataFieldForAction or other DataField types). Even if all footer-determining actions are hidden, the footer may still render to display bound backend messages.
LANGUAGE: XML
CODE:
```xml
<Annotation Term="UI.LineItem">
    <Collection>
        <Record Type="UI.DataFieldForAction">
            <PropertyValue Property="Label" String="Bound Action with params" />
            <PropertyValue Property="Action" String="com.c_salesordermanage_sd_aggregate.CreateWithSalesOrderType" />
            <Annotation Term="UI.Hidden" Bool="true" />
        </Record>
    </Collection>
</Annotation>
```

LANGUAGE: ABAP CDS
CODE:
```abap
@UI.lineItem: [
  {
    hidden: true,
    label: 'Bound Action with params',
    dataAction: 'com.c_salesordermanage_sd_aggregate.CreateWithSalesOrderType',
    type: #FOR_ACTION
  },
]
TEST;
```

LANGUAGE: CAP CDS
CODE:
```cds
LineItem                                        : {
        $value             : [
        {
            $Type  : 'UI.DataFieldForAction',
            Label  : 'Bound Action with params',
            Action : 'com.c_salesordermanage_sd.CreateWithSalesOrderType',
            ![@UI.Hidden] : true
        },
]
```

STEP: 8 — Quick rules and gotchas
DESCRIPTION: Quick actionable reminders when applying UI.Hidden:
- UI.Hidden without Bool defaults to true (hidden).
- Use UI.Hidden Bool="false" to explicitly show.
- Path must point to a Boolean property (use edmJSON for expression-based conditions; SAPUI5 expression binding is not supported).
- edmJSON conditional annotations work only for SAP Fiori elements with OData V4.
- To hide a UI.FieldGroup or UI.Identification entirely, hide all DataField entries inside or hide the wrapper ReferenceFacet/DataFieldForAnnotation.
- Hiding actions in footer does not remove footer if backend-bound messages must be shown.

UI.Hidden
annotation
Fiori Elements
OData V4
XML Annotations
ABAP CDS
CAP CDS
object page
header facets
quick view
field group
line item


**TITLE**: Highlight Line Items in Tables by Criticality (Fiori Elements)

**INTRODUCTION**: Add semantic highlights (row colors and optional icons) to table line items based on a criticality property. Use the UI.Criticality annotation on the entity type's LineItem to map an existing property that returns the CriticalityType values (0,1,2,3,5). This applies to regular and analytical tables (see note for OData V2).

**TAGS**: fiori-elements, annotations, criticality, LineItem, UI.Criticality, CDS, CAP, XML, OData

STEP: 1 — Criticality value mapping
DESCRIPTION: Use the property that returns a CriticalityType numeric value. Map values to semantic meanings and colors as defined by com.sap.vocabularies.UI.v1.CriticalityType.
LANGUAGE: JSON
CODE:
```json
{
  "CriticalityTypeValues": {
    "0": "Neutral",
    "1": "Negative (red)",
    "2": "Critical (orange)",
    "3": "Positive (green)",
    "5": "New Item (blue) - highlight items created outside the app"
  }
}
```

STEP: 2 — Ensure data model exposes the criticality property
DESCRIPTION: Confirm your entity/view exposes a property that returns one of the CriticalityType values. For analytical tables in SAP Fiori elements for OData V2, the criticality field must be a property (not a dimension). If needed, add a derived/computed property in the backend/CDS that returns 0/1/2/3/5.
LANGUAGE: PlainText
CODE:
```text
Action: Add/verify a numeric property on the EntityType or CDS view that returns one of {0,1,2,3,5}.
Note: For OData V2 analytical tables this must be a property (not a dimension).
```

STEP: 3 — Add UI.LineItem criticality annotation (XML)
DESCRIPTION: Add the UI.Criticality annotation pointing to the property that supplies the criticality for the LineItem. Place this annotation on the entity type used by the table (e.g., in annotations XML file or metadata annotations).
LANGUAGE: XML
CODE:
```xml
<Annotation Term="UI.LineItem">
  <Annotation Term="UI.Criticality" Path="Element_transporting_criticality_of_complete_LineItem" />         //LineItem Criticality annotation
  <Collection>
    <Record Type="UI.DataField">
      ...
    </Record>
  </Collection>
</Annotation>
```

STEP: 4 — Add UI.lineItem criticality in ABAP CDS
DESCRIPTION: In ABAP CDS, set the criticality attribute inside @UI.lineItem for the view. Use the property name that returns the criticality.
LANGUAGE: ABAP
CODE:
```
@UI.lineItem: [{criticality: 'Element_transporting_criticality_of_complete_LineItem'}]
annotate view VIEWNAME with {

}
```

STEP: 5 — Add UI.LineItem criticality in CAP CDS
DESCRIPTION: In CAP CDS (service.cds), attach the UI.Criticality annotation to the UI.LineItem definition using the property name that supplies the criticality.
LANGUAGE: CDS
CODE:
```
UI.LineItem : {
    $value : [
        {
            $Type : 'UI.DataField'
        },
    ],
    ![@UI.Criticality] : Element_transporting_criticality_of_complete_LineItem
}
```

STEP: 6 — Icon representation and rendering behavior
DESCRIPTION: Default rendering: Fiori elements assumes DataField is marked with CriticalityRepresentationType/WithIcon and sets ObjectStatus icon automatically (for example com.sap.vocabularies.UI.v1.CriticalityType/Negative → 'sap-icon://status-negative'). If the field is marked with CriticalityRepresentationType/WithoutIcon, the field is rendered without an icon. Adjust CriticalityRepresentationType as needed in your annotations.
LANGUAGE: JSON
CODE:
```json
{
  "RepresentationBehavior": {
    "WithIcon": "Fiori sets ObjectStatus icon according to criticality (e.g., status-negative for Negative).",
    "WithoutIcon": "Field rendered without icon."
  }
}
```

STEP: 7 — Implementation checklist
DESCRIPTION: Quick actionable checklist to implement highlighting.
LANGUAGE: PlainText
CODE:
```text
1. Identify or create a property returning 0/1/2/3/5 on the EntityType/CDS view.
2. Ensure for OData V2 analytical tables the criticality is a property (not a dimension).
3. Add UI.Criticality on UI.LineItem pointing to that property (XML, ABAP CDS, or CAP CDS as applicable).
4. Verify CriticalityRepresentationType (WithIcon/WithoutIcon) if icons are required/undesired.
5. Test table UI: rows should be highlighted with corresponding semantic colors and icons (if enabled).
```

fiori-elements annotations criticality LineItem UI.Criticality CDS CAP XML OData


**TITLE**: Highlight numeric values using DataPoint with Criticality or CriticalityCalculation (Fiori Elements)

**INTRODUCTION**: Use the com.sap.vocabularies.UI.v1.DataPoint annotation to show numeric values with visual highlighting (colors/semantics) in Fiori Elements (Overview Pages, List/Detail cards, etc.). You can set a static Criticality or compute it with a CriticalityCalculation using thresholds and improvement direction. These annotations are placed in your OData annotation file (EDMX/Annotations) or equivalent annotation source.

**TAGS**: fiori-elements-framework, annotations, DataPoint, Criticality, CriticalityCalculation, OData, EDMX, JSON

**STEP**: 1 — Static Criticality on a DataPoint

**DESCRIPTION**: Set a fixed semantic color/criticality for a numeric DataPoint by adding a DataPoint annotation with the Criticality property set to one of the enum members (Positive, Negative, Critical, Neutral). Useful when the status is stored explicitly.

**LANGUAGE**: XML

**CODE**:
```xml
<!-- File: annotations.xml (or your service annotation file) -->
<Annotations Target="MyService.MyEntity">
  <Annotation Term="com.sap.vocabularies.UI.v1.DataPoint">
    <Record>
      <!-- Value: property containing the numeric value to display -->
      <PropertyValue Property="Value" Path="Amount"/>
      <!-- Static criticality: Positive, Negative, Critical, Neutral -->
      <PropertyValue Property="Criticality" EnumMember="com.sap.vocabularies.UI.v1.Criticality/Positive"/>
      <!-- Optional: unit, title, etc. -->
      <PropertyValue Property="ValueUnit" Path="Currency"/>
      <PropertyValue Property="Title" String="Total Amount"/>
    </Record>
  </Annotation>
</Annotations>
```

**STEP**: 2 — Compute Criticality using CriticalityCalculation (thresholds)

**DESCRIPTION**: Use CriticalityCalculation to derive Criticality from the numeric Value. Define ImprovementDirection (Maximize or Minimize) and CriticalityThresholds to map value ranges to Criticality enum members. This is applied inside the DataPoint annotation.

**LANGUAGE**: XML

**CODE**:
```xml
<!-- File: annotations.xml -->
<Annotations Target="MyService.MyEntity">
  <Annotation Term="com.sap.vocabularies.UI.v1.DataPoint">
    <Record>
      <PropertyValue Property="Value" Path="Amount"/>
      <PropertyValue Property="ValueUnit" Path="Currency"/>
      <PropertyValue Property="Title" String="Total Amount"/>
      <PropertyValue Property="CriticalityCalculation">
        <Record Type="com.sap.vocabularies.UI.v1.CriticalityCalculationType">
          <!-- ImprovementDirection: Maximize means higher = better -->
          <PropertyValue Property="ImprovementDirection" EnumMember="com.sap.vocabularies.UI.v1.ImprovementDirection/Maximize"/>
          <!-- Thresholds: evaluate in order; map ranges to Criticality enums -->
          <PropertyValue Property="CriticalityThresholds">
            <Collection>
              <!-- Below 50 => Negative -->
              <Record Type="com.sap.vocabularies.UI.v1.CriticalityThresholdType">
                <PropertyValue Property="Value" Int="50"/>
                <PropertyValue Property="Severity" EnumMember="com.sap.vocabularies.UI.v1.Criticality/Negative"/>
              </Record>
              <!-- 50..80 => Critical -->
              <Record Type="com.sap.vocabularies.UI.v1.CriticalityThresholdType">
                <PropertyValue Property="Value" Int="80"/>
                <PropertyValue Property="Severity" EnumMember="com.sap.vocabularies.UI.v1.Criticality/Critical"/>
              </Record>
              <!-- Above 80 => Positive -->
              <Record Type="com.sap.vocabularies.UI.v1.CriticalityThresholdType">
                <PropertyValue Property="Value" Int="81"/>
                <PropertyValue Property="Severity" EnumMember="com.sap.vocabularies.UI.v1.Criticality/Positive"/>
              </Record>
            </Collection>
          </PropertyValue>
        </Record>
      </PropertyValue>
    </Record>
  </Annotation>
</Annotations>
```

**STEP**: 3 — DataPoint annotation as an Annotation Element in EDMX metadata

**DESCRIPTION**: Wrap DataPoint annotations inside the standard EDMX/Annotations structure targeting the entity (or a specific property). Place this file where your service reads annotation files (e.g., annotations.xml referenced by the SAP Fiori launchpad or UI service).

**LANGUAGE**: XML

**CODE**:
```xml
<!-- File: annotations.xml (full example inside an EDMX document's annotations section) -->
<edmx:Edmx xmlns:edmx="http://docs.oasis-open.org/odata/ns/edmx" Version="4.0">
  <edmx:DataServices>
    <Schema xmlns="http://docs.oasis-open.org/odata/ns/edm" Namespace="MyService">
      <!-- EntityType and properties defined in the service model (not shown) -->
    </Schema>

    <!-- Annotations for the entity -->
    <Annotations Target="MyService.MyEntity">
      <Annotation Term="com.sap.vocabularies.UI.v1.DataPoint">
        <Record>
          <PropertyValue Property="Value" Path="Amount"/>
          <PropertyValue Property="ValueUnit" Path="Currency"/>
          <PropertyValue Property="Title" String="Total Amount"/>
          <PropertyValue Property="CriticalityCalculation">
            <Record Type="com.sap.vocabularies.UI.v1.CriticalityCalculationType">
              <PropertyValue Property="ImprovementDirection" EnumMember="com.sap.vocabularies.UI.v1.ImprovementDirection/Maximize"/>
              <PropertyValue Property="CriticalityThresholds">
                <Collection>
                  <Record Type="com.sap.vocabularies.UI.v1.CriticalityThresholdType">
                    <PropertyValue Property="Value" Int="50"/>
                    <PropertyValue Property="Severity" EnumMember="com.sap.vocabularies.UI.v1.Criticality/Negative"/>
                  </Record>
                  <Record Type="com.sap.vocabularies.UI.v1.CriticalityThresholdType">
                    <PropertyValue Property="Value" Int="80"/>
                    <PropertyValue Property="Severity" EnumMember="com.sap.vocabularies.UI.v1.Criticality/Critical"/>
                  </Record>
                  <Record Type="com.sap.vocabularies.UI.v1.CriticalityThresholdType">
                    <PropertyValue Property="Value" Int="81"/>
                    <PropertyValue Property="Severity" EnumMember="com.sap.vocabularies.UI.v1.Criticality/Positive"/>
                  </Record>
                </Collection>
              </PropertyValue>
            </Record>
          </PropertyValue>
        </Record>
      </Annotation>
    </Annotations>
  </edmx:DataServices>
</edmx:Edmx>
```

**STEP**: 4 — Equivalent CSDL JSON snippet (service annotations in JSON)

**DESCRIPTION**: If your service uses JSON representation of CSDL annotations, the structure mirrors the XML form. Use the same Terms, Records, PropertyValues and EnumMembers in JSON.

**LANGUAGE**: JSON

**CODE**:
```json
{
  "$Version": "4.0",
  "MyService.MyEntity": {
    "@com.sap.vocabularies.UI.v1.DataPoint": {
      "Value": { "Path": "Amount" },
      "ValueUnit": { "Path": "Currency" },
      "Title": { "String": "Total Amount" },
      "CriticalityCalculation": {
        "Record": {
          "Type": "com.sap.vocabularies.UI.v1.CriticalityCalculationType",
          "ImprovementDirection": { "EnumMember": "com.sap.vocabularies.UI.v1.ImprovementDirection/Maximize" },
          "CriticalityThresholds": {
            "Collection": [
              {
                "Record": {
                  "Type": "com.sap.vocabularies.UI.v1.CriticalityThresholdType",
                  "Value": { "Int": 50 },
                  "Severity": { "EnumMember": "com.sap.vocabularies.UI.v1.Criticality/Negative" }
                }
              },
              {
                "Record": {
                  "Type": "com.sap.vocabularies.UI.v1.CriticalityThresholdType",
                  "Value": { "Int": 80 },
                  "Severity": { "EnumMember": "com.sap.vocabularies.UI.v1.Criticality/Critical" }
                }
              },
              {
                "Record": {
                  "Type": "com.sap.vocabularies.UI.v1.CriticalityThresholdType",
                  "Value": { "Int": 81 },
                  "Severity": { "EnumMember": "com.sap.vocabularies.UI.v1.Criticality/Positive" }
                }
              }
            ]
          }
        }
      }
    }
  }
}
```

For more information, see com.sap.vocabularies.UI.v1.DataPoint in "Annotations Used in Overview Pages" (annotations-used-in-overview-pages-65731e6.md).

fiori-elements-framework annotations DataPoint Criticality CriticalityCalculation OData EDMX JSON


**TITLE**: How To Use SAP Fiori Elements

**INTRODUCTION**: Practical, code-focused guide for creating and extending SAP Fiori elements apps. Covers prerequisites (OData services), preparing UI annotations, building apps with SAP Fiori tools, and extending generated Fiori elements apps. Use the examples and file paths to implement or automate app generation and runtime customization.

**TAGS**: fiori-elements-framework, sap-fiori, odata, annotations, sap-fiori-tools, extension

**STEP**: 1 — Verify back-end OData prerequisites

**DESCRIPTION**: Ensure the back-end system exposes the required OData services (V2 or V4) and that service metadata and annotation files are accessible. Validate service endpoints and metadata before generating a Fiori elements app. Typical checks: reachable service URL, $metadata response, required entity sets, and the presence of UI annotations (inline or external).

**LANGUAGE**: Bash

**CODE**:
```bash
# Example: verify OData $metadata (basic connectivity check)
curl -I -u <USER>:<PASSWORD> "https://<BACKEND_HOST>/sap/opu/odata/sap/<SERVICE_NAME>/$metadata"

# Example: download metadata to inspect
curl -u <USER>:<PASSWORD> "https://<BACKEND_HOST>/sap/opu/odata/sap/<SERVICE_NAME>/$metadata" -o service-$metadata.xml
```

**STEP**: 2 — Prepare UI annotations for features and behavior

**DESCRIPTION**: Create or adapt OData annotation files to enable default Fiori elements features (list report, object page, quick view, etc.). You can place annotations inline in the service metadata or in external annotation files and reference them. Ensure correct Target values and UI terms (UI.LineItem, UI.FieldGroup, UI.Facets, UI.HeaderInfo). Use the appropriate annotation vocabulary (OData V2 or V4) depending on your service.

**LANGUAGE**: XML

**CODE**:
```xml
<!-- Example OData annotation snippet (OData V4-style XML) -->
<edmx:Edmx xmlns:edmx="http://docs.oasis-open.org/odata/ns/edmx" Version="4.0">
  <edmx:DataServices>
    <Annotations Target="MyService.Product">
      <Annotation Term="UI.HeaderInfo">
        <Record>
          <PropertyValue Property="TypeName" String="Product"/>
          <PropertyValue Property="Title" Path="Name"/>
        </Record>
      </Annotation>
      <Annotation Term="UI.LineItem">
        <Collection>
          <Record Type="UI.DataField">
            <PropertyValue Property="Value" Path="ProductID"/>
            <PropertyValue Property="Label" String="ID"/>
          </Record>
          <Record Type="UI.DataField">
            <PropertyValue Property="Value" Path="Name"/>
            <PropertyValue Property="Label" String="Product Name"/>
          </Record>
        </Collection>
      </Annotation>
    </Annotations>
  </edmx:DataServices>
</edmx:Edmx>
```

**STEP**: 3 — Generate and build a Fiori elements app with SAP Fiori tools

**DESCRIPTION**: Use SAP Fiori tools (VS Code extensions or SAP Business Application Studio) or the Yeoman generator to scaffold a Fiori elements app. Confirm the generated project contains expected files: webapp/manifest.json (app descriptor), webapp/annotations/*.xml or annotations/*.json, and local test mocks when applicable. Build and run locally or deploy to your cloud/ABAP runtime.

**LANGUAGE**: Bash

**CODE**:
```bash
# Install Yeoman and the SAP Fiori generator (global install)
npm install -g yo @sap/generator-fiori

# Scaffold a new Fiori elements app (interactive)
yo @sap/generator-fiori

# Typical project structure after generation:
# my-fiori-app/
# ├─ webapp/
# │  ├─ manifest.json            <-- app descriptor (configure dataSources, annotations)
# │  ├─ annotations/             <-- local annotation files (if generated)
# │  └─ Component.js
# └─ xs-app.json (if SAP BTP Cloud Foundry setup)

# To run locally (if web server available in project)
npm install
npm start
```

**STEP**: 4 — Configure manifest.json entry points and data source references

**DESCRIPTION**: Verify and modify webapp/manifest.json to reference your OData service and annotations. Set the correct dataSource URL and annotation references so the runtime can load metadata and UI annotations.

**LANGUAGE**: JSON

**CODE**:
```json
{
  "sap.app": {
    "id": "my.fiori.app"
  },
  "sap.ui5": {
    "models": {
      "": {
        "dataSource": "mainService",
        "settings": {
          "synchronizationMode": "None"
        }
      }
    }
  },
  "sap.app/dataSources": {
    "mainService": {
      "uri": "/sap/opu/odata/sap/<SERVICE_NAME>/",
      "type": "OData",
      "settings": {
        "odataVersion": "2.0",
        "localUri": "localService/metadata.xml"
      }
    }
  }
}
```

**STEP**: 5 — Extend Fiori elements apps when annotations/manifest are insufficient

**DESCRIPTION**: Use extensibility points to add custom logic: controller extensions, view fragments, or component extensions. Register controller extensions in webapp/manifest.json under sap.ui5 -> extends -> extensions to reference your custom controller. Implement custom UI logic in specific extension controller files and register fragments as needed.

**LANGUAGE**: JSON

**CODE**:
```json
{
  "sap.ui5": {
    "extends": {
      "extensions": {
        "sap.ui.controllerExtensions": {
          "sap.suite.ui.generic.template.ListReport.view.ListReport": {
            "controllerName": "my.namespace.extensions.ListReportExtension"
          }
        }
      }
    }
  }
}
```

**STEP**: 6 — Implement controller extension (example file path)

**DESCRIPTION**: Place extension controller files under webapp/ext/ or a similar namespace consistent with the manifest registration. Implement only the event handlers or lifecycle hooks you need.

**LANGUAGE**: JavaScript

**CODE**:
```javascript
// File: webapp/ext/ListReportExtension.controller.js
sap.ui.define(["sap/ui/core/mvc/Controller"], function(Controller) {
  "use strict";
  return Controller.extend("my.namespace.extensions.ListReportExtension", {
    onInit: function() {
      // custom initialization logic
    },
    onBeforeRebindTableExt: function(oEvent) {
      // example hook to modify filter/binding
    }
  });
});
```

**STEP**: 7 — References and further reading (preserve original links)

**DESCRIPTION**: Use official SAP docs and guides for deep dives and platform-specific instructions.

**LANGUAGE**: Markdown

**CODE**:
```markdown
- Prerequisites for Using SAP Fiori Elements:
  https://<SAP_DOC_HOST>/prerequisites-for-using-sap-fiori-elements-f2344b5.md

- Working With OData Annotations:
  https://<SAP_DOC_HOST>/working-with-odata-annotations-83c89cc.md

- Extending SAP Fiori Elements-Based Apps:
  https://<SAP_DOC_HOST>/extending-sap-fiori-elements-based-apps-358cf25.md

- SAP Fiori tools (extensions for Business Application Studio and VS Code):
  https://help.sap.com/viewer/product/SAP_FIORI_tools/Latest/en-US

- SAP Business Application Studio:
  https://help.sap.com/viewer/product/SAP%20Business%20Application%20Studio/Cloud/en-US
```

How To Use SAP Fiori Elements

fiori-elements-framework sap-fiori odata annotations sap-fiori-tools extension


**TITLE**: Hybrid View Configuration for Analytical List Page (ALP) in SAP Fiori Elements

**INTRODUCTION**: Configure and enable the hybrid view (chart + table) for the ALP content area. Use these steps to set the default hybrid display for OData V2 and V4 apps, and follow the UX and device constraints to ensure correct highlighting, filtering, and availability.

**TAGS**: fiori-elements-framework, analytical-list-page, ALP, hybrid-view, charttable, defaultPath, ODataV2, ODataV4, manifest

STEP: 1 — Purpose and interaction model

DESCRIPTION: The hybrid view displays analytical data (chart) and transactional data (table) simultaneously. Users can interact with the chart selection to filter and highlight related table records. Use this step to understand behavior and prerequisites before applying manifest/settings changes.

LANGUAGE: text

CODE:
```text
Purpose: Show chart at top and table at bottom. Chart dimension selection acts as a filter/highlight for table records.
```

STEP: 2 — OData V2: set default content view to chart+table

DESCRIPTION: Add the "settings.defaultContentView" property to your app configuration to make the hybrid view the default content display. Keep the code snippet exact in your manifest or settings file.

LANGUAGE: JSON

CODE:
```json
"settings": {
              "defaultContentView": "charttable",
}
```

STEP: 3 — OData V4: set defaultPath for views to both (chart + table)

DESCRIPTION: In the V4 manifest, set the views.paths[].defaultPath to "both" so the initial view loads with the chart above the table. Insert this into the existing "views" object; preserve any other properties in your paths array.

LANGUAGE: JSON

CODE:
```json
"views": {
    "paths": [{
...
        "defaultPath": "both"
    }]
},
```

STEP: 4 — Ensure chart context dimensions are visible in the table

DESCRIPTION: For accurate highlights and filtering, expose chart context dimensions as visible columns in the table's line item annotation or table configuration. If chart context dimensions are not visible, highlights and record association may be inaccurate.

LANGUAGE: text

CODE:
```text
Action: Verify UI.Chart chart context dimensions are included as visible columns in the table (UI.LineItem / table column configuration).
```

STEP: 5 — Configure and understand the auto-hide feature behavior

DESCRIPTION: The auto-hide feature controls whether the table shows only records affected by a chart selection or all records with highlights. When enabled, chart selection acts as an additional filter (table shows only affected/highlighted records). When disabled, table shows all records and highlights the ones affected by the chart selection.

LANGUAGE: text

CODE:
```text
Auto-hide ON  -> Table displays only records affected by chart selection (selection acts as filter).
Auto-hide OFF -> Table displays all records; affected records are highlighted.
```

STEP: 6 — Device, mode and resolution constraints

DESCRIPTION: Hybrid mode availability and behavior are constrained by device type, screen height, table type and mode (cozy/compact). Apply these rules when designing or enabling hybrid view:

- Not available on tablets or smartphones.
- Available on laptops with screen height > 900px.
- Disabled for analytical and grid table types in cozy mode when resolution < 900px.
- Restriction does NOT apply to responsive tables (responsive tables can still use hybrid view).

LANGUAGE: text

CODE:
```text
Constraints:
- Devices: Hybrid view disabled on tablets and smartphones.
- Screen height: Requires > 900px for hybrid view to appear on laptops.
- Table types: Analytical and Grid tables - hybrid disabled in cozy mode when resolution < 900px.
- Responsive tables: hybrid view available regardless of the above resolution restriction.
```

STEP: 7 — Related information and file references

DESCRIPTION: See the content area configuration guidance for detailed instructions on annotations and manifest configuration required to render the chart and table areas. Keep the referenced documentation path for further integration steps.

LANGUAGE: text

CODE:
```text
Related doc: configuring-the-content-area-fc7d73c.md
(Visualize data from the main entity set and define UI.Chart or UI.LineItem annotations. See "Configuring the Manifest for the Analytical List Page".)
```

fiori-elements-framework analytical-list-page ALP hybrid-view charttable defaultPath ODataV2 ODataV4 manifest