**TITLE**: Developing SAP Fiori Elements Apps (metadata-driven, no UI JS)

**INTRODUCTION**: Build SAP Fiori applications using Fiori elements: a template- and metadata-driven approach where SAPUI5 interprets OData metadata and annotations to assemble UI (predefined views/controllers). Use this guide to prepare OData services and annotations, scaffold a Fiori elements app, configure manifest.json, and reference annotation files and assets.

**TAGS**: fiori-elements-framework, sapui5, odata, annotations, metadata-driven, manifest.json, fiori-tools

**STEP**: 1 — Project layout and assets

**DESCRIPTION**: Use a standard webapp structure. Place the manifest.json in webapp/, annotation XML files in webapp/annotations/, and image assets in webapp/images/. Example file paths used by later steps are shown here.

**LANGUAGE**: text

**CODE**:
```text
Project root/
└─ webapp/
   ├─ manifest.json
   ├─ index.html
   ├─ annotations/
   │  └─ annotations.xml
   └─ images/
      └─ ImageMapEntryPage_dc8d2b1.png
```

**STEP**: 2 — Prepare an OData service with annotations

**DESCRIPTION**: Provide an OData service (V2 or V4) exposing entity sets and annotation references. Produce annotation XML (or EDMX/CDS) describing UI semantics (LineItem, FieldGroup, Identification, etc.). Store annotation files under webapp/annotations/ and ensure the service is reachable from the app.

**LANGUAGE**: XML

**CODE**:
```xml
<!-- webapp/annotations/annotations.xml -->
<edmx:Edmx xmlns:edmx="http://docs.oasis-open.org/odata/ns/edmx" Version="4.0">
  <edmx:Reference Uri="http://docs.oasis-open.org/odata/odata/v4.0/annotation">
    <edmx:Include Namespace="Org.OData.Core.V1" Alias="Core"/>
  </edmx:Reference>
  <edmx:DataServices>
    <Schema Namespace="MyService" xmlns="http://docs.oasis-open.org/odata/ns/edm">
      <EntityType Name="Product">
        <Key>
          <PropertyRef Name="ID"/>
        </Key>
        <Property Name="ID" Type="Edm.String"/>
        <Property Name="Name" Type="Edm.String"/>
        <Annotation Term="UI.LineItem">
          <Collection>
            <Record Type="UI.DataField">
              <PropertyValue Property="Value">
                <Path>Name</Path>
              </PropertyValue>
            </Record>
          </Collection>
        </Annotation>
      </EntityType>
    </Schema>
  </edmx:DataServices>
</edmx:Edmx>
```

**STEP**: 3 — Configure manifest.json dataSources and annotations

**DESCRIPTION**: In webapp/manifest.json, register the OData service under sap.app/dataSources and list annotation files. For Fiori elements apps, ensure "sap.ui5" and "sap.app" sections are set to use the OData dataSource and annotation files. Below is a minimal manifest snippet illustrating dataSource + annotation configuration.

**LANGUAGE**: JSON

**CODE**:
```json
{
  "sap.app": {
    "id": "my.fiori.elements.app",
    "type": "application",
    "applicationVersion": {
      "version": "1.0.0"
    }
  },
  "sap.ui5": {
    "models": {
      "": {
        "dataSource": "mainService",
        "settings": {
          "synchronizationMode": "None"
        }
      }
    }
  },
  "sap.app": {
    "dataSources": {
      "mainService": {
        "uri": "/sap/opu/odata/sap/MY_SERVICE_SRV/",
        "type": "OData",
        "settings": {
          "annotations": [
            {
              "type": "XML",
              "uri": "annotations/annotations.xml"
            }
          ]
        }
      }
    }
  },
  "sap.ui": {
    "technology": "UI5"
  }
}
```

**STEP**: 4 — Scaffold a Fiori elements app (Fiori tools / template)

**DESCRIPTION**: Use SAP Business Application Studio or the Fiori tools VS Code extension to generate a Fiori elements project (List Report/Object Page or Analytical List Page) referencing the OData service. The generator creates a manifest.json configured for the chosen floorplan and wiring to annotations, so no application-specific view JS is required.

**LANGUAGE**: text

**CODE**:
```text
Recommended tooling:
- SAP Business Application Studio: Application Generator (Fiori)
- VS Code + SAP Fiori tools: use 'Fiori: Create Project from Template' -> choose 'Fiori Elements' -> select floorplan and OData service -> provide annotations file
```

**STEP**: 5 — How SAPUI5 uses metadata and annotations at runtime

**DESCRIPTION**: At startup SAPUI5 reads the OData service metadata and annotation files referenced in manifest.json. It automatically selects predefined views and controllers (floorplans) and binds data according to annotations (no custom UI JS required for standard patterns). Verify behavior during development by running the app locally or in SAP Cloud Platform to ensure annotation-driven UI renders as expected.

**LANGUAGE**: text

**CODE**:
```text
Runtime behavior summary:
- SAPUI5 reads OData metadata (+ EDMX) and annotation XML referenced in manifest.json
- Fiori elements runtime selects predefined floorplan views/controllers
- UI is assembled based on UI annotations (e.g., UI.LineItem, UI.FieldGroup)
- Minimal or no custom UI5 JS code needed for standard scenarios
```

**STEP**: 6 — Asset / documentation image reference

**DESCRIPTION**: Include diagrams, images, or links in your app documentation. Reference images from webapp/images/. Example image referenced in original docs is included here.

**LANGUAGE**: text

**CODE**:
```text
Image path used in docs:
webapp/images/ImageMapEntryPage_dc8d2b1.png
```

fiori-elements-framework sapui5 odata annotations metadata-driven manifest.json fiori-tools


**TITLE**: Developing Reuse Components for SAP Fiori elements (Object Page Sections)

**INTRODUCTION**: Practical, code-focused guide for implementing reusable UI components (reuse components) that can be embedded as sections in SAP Fiori elements object pages. Covers project structure, property handling, model propagation, lifecycle hooks (stStart/stRefresh), extension API usage, lazy loading, subpage definition, and navigation. Includes complete sample code snippets ready for copy/paste.

**TAGS**: fiori-elements-framework, reuse-component, sapui5, UI5, OData, object-page, extensionAPI, manifest.json, embeddedComponents

STEP: 1 — Project / Packaging Guidelines

DESCRIPTION:
- Provide reuse components as libraries when they are consumed by multiple apps.
- For one-time reuse, deliver the component inside the same application project.
- Do not store instance-specific state in singletons—each reuse component instance must be instance-local.
- Ensure the view hosting the reuse component content has a stable ID and define the view declaratively in manifest.json.

LANGUAGE: text

CODE:
```text
# Action:
# - If multi-app reuse: create a library/package for the reuse component.
# - If single app use: provide component inside the application project.
# - Avoid singletons for instance-level state.
# - Define and reference the host view declaratively in manifest.json for stable IDs.
```

STEP: 2 — Property Handling & Reserved Names

DESCRIPTION:
- Reuse components expose properties (metadata) that the embedding app sets. Setter and getter methods are autogenerated. The embedding app does not get direct access to the component instance.
- To react to property changes programmatically, override setter methods inside the reuse component.
- Method names starting with "st" or "_st" are reserved by SAP Fiori elements — do not define custom methods with these prefixes except the documented ones (stStart, stRefresh).
- The method name getComponentModel is reserved by Fiori elements; beware when using component model features.
- When using ReuseComponentSupport.mixInto(this, modelName, bTwoWaySync?) you can:
  - Pass a model name (string) as second parameter — this creates a JSON model attached to the component retrievable via getComponentModel().
  - Optionally enable two-way sync (bTwoWaySync) to push JSON model changes back to the component properties (use with care).

LANGUAGE: JavaScript

CODE:
```javascript
sap.ui.define([
 "sap/ui/core/UIComponent",
 "sap/suite/ui/generic/template/extensionAPI/ReuseComponentSupport"
], function(UIComponent, ReuseComponentSupport) {
 "use strict";

 /* Definition of the reuse component */
 return UIComponent.extend("MyReuseComponent", {
  metadata: {
   manifest: "json",
   library: "myLibrary",
   properties: {
    /* Standard properties for reuse components */

    uiMode: {
     type: "string",
     group: "standard"
    },
    semanticObject: {
     type: "string",
     group: "standard"
    },
    stIsAreaVisible: {
     type: "boolean",
     group: "standard"
    },

    /* Component specific properties */

    documentNumber: {
     type: "string",
     group: "specific",
     defaultValue: ""
    }
   }
  },

  // Standard life time event of a component. Used to transform this component into a reuse component for Fiori Elements
  init: function(){
    //Transform this component into a reuse component for Fiori Elements:
    ReuseComponentSupport.mixInto(this, "myPropertiesModelName");
    // Defensive call of init of the super class:
    (UIComponent.prototype.init || jQuery.noop).apply(this, arguments);
  }
 });
});
```

STEP: 3 — Declarative Binding of Component Model in XML Views

DESCRIPTION: Use the component model created by mixInto for declarative bindings (read-only by default). Example shows binding to uiMode via the properties model name passed to mixInto.

LANGUAGE: XML

CODE:
```xml
<sfo:SmartForm xmlns:sfo="sap.ui.comp.smartform"
    editable="{= ${myPropertiesModelName>/uiMode} !== 'Display' }"
</sfo:SmartForm>
```

STEP: 4 — Two Techniques to React to Property Changes Programmatically

DESCRIPTION:
- Technique 1: Override the predefined setter (redefine setStIsAreaVisible).
- Technique 2: Use component model bindings and attach change handlers to property bindings.
- Place initialization and mixInto calls in init(); attach bindings after mixInto if you rely on the component model.

LANGUAGE: JavaScript

CODE:
```javascript
sap.ui.define([
 "sap/ui/core/UIComponent",
 "sap/suite/ui/generic/template/extensionAPI/ReuseComponentSupport"
], function(UIComponent, ReuseComponentSupport) {
 "use strict";

 /* Definition of the reuse component */
 return UIComponent.extend("MyReuseComponent", {
  metadata: {
   manifest: "json",
   library: "myLibrary",
   properties: {
    /* Standard properties for reuse components */

    uiMode: {
     type: "string",
     group: "standard"
    },
    semanticObject: {
     type: "string",
     group: "standard"
    },
    stIsAreaVisible: {
     type: "boolean",
     group: "standard"
    },

    /* Component specific properties */

    documentNumber: {
     type: "string",
     group: "specific",
     defaultValue: ""
    }
   }
  },

  // Technique 1: Redefine the predefined setter-method
  setStIsAreaVisible: function(bIsAreaVisible){
   if (bIsAreaVisible !== this.getStIsAreaVisible()){
     this.setProperty("stIsAreaVisible", bIsAreaVisible); // ensure that the property is updated accordingly
     // ... (any code that wants to consume the changed visibility of the reuse component)
   }
  },

  // Standard life time event of a component. Used to transform this component into a reuse component for Fiori Elements and do some initialization
  init: function(){
   // Defensive call of init of the super class:
   (UIComponent.prototype.init || jQuery.noop).apply(this, arguments);
    //Transform this component into a reuse component for Fiori Elements:
    ReuseComponentSupport.mixInto(this, "myPropertiesModelName");
    // Technique 2: Attach to changes of the component model
    var oMyPropertiesModel = this.getComponentModel();
    var oPropertyBinding = oMyPropertiesModel.bindProperty("/documentNumber");
    oPropertyBinding.attachChange(function(){
      var sDocumentNumber = oMyPropertiesModel.getProperty("/documentNumber");
      // ... (any code that wants to consume the changed document number)
    });
  }
 });
});
```

STEP: 5 — Model Propagation Rules

DESCRIPTION:
- The unnamed OData model and a JSON model named "ui" from the embedding application are propagated to the reuse component. Additional internal JSON models may be propagated but must not be accessed.
- The binding context for the unnamed model is preset. By default, the binding context of the object page is propagated; embedding app can apply a relative binding to change it.
- Model propagation is critical when the reuse component accesses the same OData service as the embedding app.

LANGUAGE: text

CODE:
```text
# Behavior:
# - Unnamed OData model + "ui" JSON model from app → propagated to reuse component.
# - Binding context from the object page → propagated to reuse component (can be modified by relative binding).
# - Do NOT access other internal propagated models.
```

STEP: 6 — Lifecycle Hooks: stStart and stRefresh (Signatures & Use)

DESCRIPTION:
- Implement stStart(oModel, oBindingContext, oExtensionAPI) and/or stRefresh(oModel, oBindingContext, oExtensionAPI) to react to binding context changes or refresh events.
- stRefresh is called when: new binding context for embedding page, binding context refresh forced, or embedding page key changes. Called only after model propagation.
- stStart is called once (first occurrence); if both implemented, first occurrence calls stStart, subsequent occurrences call stRefresh.
- Parameters:
  - oModel: standard OData model of the app.
  - oBindingContext: binding context of the current page (may be null/faulty in create scenarios).
  - oExtensionAPI: extension API instance attached to this reuse component instance.
- Recommendation: implement stRefresh for change scenarios and data refresh needs.

LANGUAGE: text

CODE:
```text
# Signatures:
# stStart(oModel, oBindingContext, oExtensionAPI)
# stRefresh(oModel, oBindingContext, oExtensionAPI)
# - Implement stRefresh for refresh scenarios.
```

STEP: 7 — Lazy Loading + Refresh Example (Combine stRefresh with stIsAreaVisible)

DESCRIPTION:
- Example shows how to combine lazy loading (stIsAreaVisible toggle) and stRefresh. setStIsAreaVisible triggers refreshImpl(); stRefresh stores model/context/extensionAPI and triggers refreshImpl() that loads data only when visible and context exists.

LANGUAGE: JavaScript

CODE:
```javascript
sap.ui.define([
 "sap/ui/core/UIComponent",
 "sap/suite/ui/generic/template/extensionAPI/ReuseComponentSupport"
], function(UIComponent, ReuseComponentSupport) {
 "use strict";

 /* Definition of the Reuse Component */
 return UIComponent.extend("MyReuseComponent", {
  metadata: {
   manifest: "json",
   library: "myLibrary",
   properties: {
    stIsAreaVisible: {
     type: "boolean",
     group: "standard"
    },
  },

  setStIsAreaVisible: function(bIsAreaVisible){
   if (bIsAreaVisible !== this.getStIsAreaVisible()){
     this.setProperty("stIsAreaVisible", bIsAreaVisible); // ensure that the property is updated accordingly
     this.refreshImpl();
   }
  },

  // Standard life time event of a component. Used to transform this component into a Reuse Component for Fiori Elements and do some initialization
  init: function(){
   // Defensive call of init of the super class:
   (UIComponent.prototype.init || jQuery.noop).apply(this, arguments);
    //Transform this component into a reuse component for Fiori Elements:
    ReuseComponentSupport.mixInto(this);
  },

  stRefresh: function(oModel, oBindingContext, oExtensionAPI) {
    this.oModel = oModel;
    this.oBindingContext = oBindingContext;
    this.oExtensionAPI = oExtensionAPI;
    this.refreshImpl();
  },

  refreshImpl: function(){
     if (this.oBindingContext && this.getStIsAreaVisible()){
       // ... (any code that loads the data for the Reuse Component according to this.oBindingContext)
       this.oBindingContext = null;
     }
  }
 });
});
```

STEP: 8 — Extension API Behavior & mixInto Return Value

DESCRIPTION:
- ReuseComponentSupport.mixInto returns a Promise resolving to the extension API instance attached to the reuse component instance.
- The extension API attached to each reuse component instance is a variant of the page extension API with modifications:
  - getNavigationController(): modified NavigationController able to navigate to pages defined in the reuse component and share a communication object.
  - getCommunicationObject(): getCommunicationObject(1) provides a communication object for communication with reuse component pages; subpages call getCommunicationObject() without parameters to retrieve it.
  - If embedded in an object page, extension API includes setSectionHidden(bHidden) to show/hide the section implemented by the reuse component.

LANGUAGE: text

CODE:
```text
# mixInto returns Promise -> resolves to extension API for reuse component instance.
# Extension API modifications:
# - getNavigationController(): supports internal navigation to reuse component pages.
# - getCommunicationObject(1): communication object to subpages.
# - setSectionHidden(bHidden): available for object page embedding.
```

STEP: 9 — Defining Subpages: Embedding App must include subpage manifest snippet

DESCRIPTION:
- The reuse component provider publishes a manifest snippet for subpages; each consumer must add that snippet inside their embedding declaration. The structure of "pages" must follow the pages structure used for object page subpages.

LANGUAGE: JSON

CODE:
```json
...
"embeddedComponents": {
    "myComponentEmbedding": {
        "id": "myComponentEmbedding",
        "componentName": "theEmbeddedComponent",
        "title": "{{I18N_KEY_FOR_REUSE_COMPONENT_TITLE}}",
        "settings": {
            "documentNumber": "{documentNumber}"
            },
        "pages":{
            // add sub-pages here
        }
    }
}
```

STEP: 10 — Use Standard Object Pages as Subpages (Manifest + Navigation)

DESCRIPTION:
- Prefer using standard object pages as subpages of the reuse component. The embedding app must define the subpage entry in embeddedComponents.pages with navigationProperty and component.Name set to the ObjectPage component.
- The reuse component must be provided with the name of the navigation property (e.g., via property theNavigationPropertyName). Use NavigationController.navigateInternal to trigger internal navigation to the subpage.

LANGUAGE: JSON

CODE:
```json
...
"embeddedComponents": {
    "myComponentEmbedding": {
        "id": "myComponentEmbedding",
        "componentName": "theEmbeddedComponent",
        "title": "{{I18N_KEY_FOR_REUSE_COMPONENT_TITLE}}",
        "settings": {
            "theNavigationPropertyName": "myNavigationProperty"         },
        "pages":{
                "ObjectPage|myNavigationProperty":{
                "navigationProperty": "myNavigationProperty",
                "entitySet": "myDependingEntitySet",
                "component": {
                    "name": "sap.suite.ui.generic.template.ObjectPage"
                }
            }
        }
    }
}
```

LANGUAGE: JavaScript

CODE:
```javascript
var oBindingContext = oEvent.getSource().getBindingContext();  // or any other way you have to get a binding context for the target page
var oNavigationController = oExtensionAPI.getNavigationController(); // oExtensionAPI is the instance of the extension api which has been discussed above
var sNavigationProperty = this.getOwnerComponent().getTheNavigationPropertyName();   // retrieve the name of the navigation property (see comments below)
var oNavigationData = {
    navigationProperty: sNavigationProperty
};
oNavigationController.navigateInternal(oBindingContext, oNavigationData);
```

STEP: 11 — Additional Notes for OData V4

DESCRIPTION:
- SAP Fiori elements for OData V4:
  - Does not provide an eventing API for reuse components to support draft handling (create/save draft).
  - You can implement reuse components with an internal OData V4 model independent of the embedding app. If doing so, give the internal model a unique name to avoid conflict with the propagated unnamed OData model.

LANGUAGE: text

CODE:
```text
# OData V4 notes:
# - No eventing API for draft handling in reuse components.
# - If reusing an internal OData V4 model, provide a unique model name to avoid conflicts with the propagated unnamed OData model.
```

fiori-elements-framework reuse-component sapui5 UI5 OData object-page extensionAPI manifest.json embeddedComponents


**TITLE**: Field Representation Variants for SAP Fiori elements (OData V4) — Annotation and Manifest Recipes

**INTRODUCTION**: Action-oriented reference of annotation and manifest examples to render OData V4 fields in SAP Fiori elements. Use these concise, copy-ready snippets to implement common field representations: plain text, currency/unit, forms, KPIs/DataPoints, rating/progress indicators, links, multiline text, micro charts, file streams, boolean controls, timezone-aware timestamps, and masked inputs.

**TAGS**: fiori-elements-framework, OData V4, annotations, UI.DataField, UI.FieldGroup, UI.DataPoint, UI.MultiLineText, UI.InputMask, Common.Masked, Measures.ISOCurrency, Measures.Unit, manifest.json

STEP: 1 — Plain Text Facet (UI.FieldGroup wrapping UI.DataField)

DESCRIPTION: Represent a field as a simple key-value plain text facet. Add a UI.DataField inside a UI.FieldGroup annotation (XML), or equivalent in ABAP CDS or CAP CDS.

LANGUAGE: XML

CODE:
```xml
<Annotation Term="UI.FieldGroup" Qualifier="PlainText">
     <Record>
          <PropertyValue Property="Data">
                <Collection>
                     <Record Type="UI.DataField">
                           <PropertyValue Property="Value" Path="description" />
                       </Record>
                 </Collection>
          </PropertyValue>
      </Record>
</Annotation>
```

LANGUAGE: ABAP CDS

CODE:
```abap
@UI.fieldGroup: [
  {
    value: 'DESCRIPTION',
    type: #STANDARD,
    qualifier: 'PlainText'
  }
];
```

LANGUAGE: CDS

CODE:
```cds
UI.FieldGroup #PlainText: {
Data : [{
              $Type : 'UI.DataField',
               Value : description
       }]
}
```

STEP: 2 — Amount with Currency or Unit of Measure

DESCRIPTION: Display numeric amounts with currency or unit by annotating the amount property and linking Measures.ISOCurrency or Measures.Unit on the currency/unit property. Use these annotations on your entity properties so Fiori renders aligned amount + currency/unit.

LANGUAGE: XML (usage hint)

CODE:
```xml
<!-- Annotate the numeric field and the related currency/unit field -->
<!-- Use Measures.ISOCurrency on the currency property and Measures.Unit on the unit property -->
<!-- Example concept: -->
<!-- Amount property: Path="price" -->
<!-- Currency property: @Org.OData.Measures.V1.ISOCurrency or @Org.OData.Measures.V1.Unit -->
```

STEP: 3 — Representation as Part of a Form (Field grouping)

DESCRIPTION: Group fields into a form using UI.FieldGroup annotations and link them to the object page form. See grouping-of-fields for complex patterns; sample FieldGroup is used in Step 1.

LANGUAGE: XML

CODE:
```xml
<!-- Use UI.FieldGroup with Data collection of UI.DataField records to define a form section -->
<Annotation Term="UI.FieldGroup" Qualifier="General">
  <Record>
    <PropertyValue Property="Data">
      <Collection>
        <Record Type="UI.DataField"><PropertyValue Property="Value" Path="field1"/></Record>
        <Record Type="UI.DataField"><PropertyValue Property="Value" Path="field2"/></Record>
      </Collection>
    </PropertyValue>
  </Record>
</Annotation>
```

STEP: 4 — Key Value Facet or KPI using UI.DataPoint

DESCRIPTION: Render a key value facet or KPI using UI.DataPoint. Use DataPoint properties Title, Value, Criticality and optionally CriticalityRepresentation. The DataPoint can be used in headers and facets.

LANGUAGE: XML

CODE:
```xml
<Annotation Term="UI.DataPoint" Qualifier="Availability">
      <Record Type="UI.DataPointType">
           <PropertyValue Property="Title" String="Availability" />
           <PropertyValue Property="Value" Path="stock/availability" />
           <PropertyValue Property="Criticality" Path="stock/availability"/>
       </Record>
</Annotation>
```

LANGUAGE: ABAP CDS

CODE:
```abap
@UI.dataPoint: {
  title: 'Availability',
  criticality: 'availability'
}
availability;
```

LANGUAGE: CDS

CODE:
```cds
UI.DataPoint #Availability                               : {
        Value                : stock.availability,
        Title                : 'Availability',
       Criticality         :  stock.availability
}
```

STEP: 5 — KPI via DataField with Criticality (object status control)

DESCRIPTION: Instead of DataPoint, mark a DataField with Criticality and CriticalityRepresentation to render as KPI/object status control.

LANGUAGE: XML

CODE:
```xml
<Record Type="SAP__UI.DataField">
    <PropertyValue Property="Criticality" Path="OvrlDeliveryStatusCriticality"/>
    <PropertyValue Property="CriticalityRepresentation" EnumMember="SAP__UI.CriticalityRepresentationType/WithoutIcon"/>
    <PropertyValue Property="Value" Path="OverallDeliveryStatus"/>
    <Annotation Term="SAP__UI.Importance" EnumMember="SAP__UI.ImportanceType/High"/>
</Record>
```

LANGUAGE: ABAP CDS

CODE:
```abap
@UI.dataPoint: {
  criticality: 'OvrlDeliveryStatusCriticality',
  criticalityRepresentation: #WITHOUT_ICON
}
OverallDeliveryStatus;
```

LANGUAGE: CDS

CODE:
```cds
{
        $Type : 'UI.DataField',
        Value : OverallDeliveryStatus,
       Criticality :  OvrlDeliveryStatusCriticality,
             ![@UI.CriticalityRepresentation ]        :  #WithoutIcon
}
```

STEP: 6 — Rating Indicator (UI.DataPoint Visualization = Rating)

DESCRIPTION: Render a rating indicator by setting UI.DataPoint Visualization to Rating and providing Value and TargetValue (max stars).

LANGUAGE: XML

CODE:
```xml
<Annotation Term="UI.DataPoint" Qualifier="averageRating">
      <Record>
           <PropertyValue Property="Value" Path="averageRating" />
            <PropertyValue Property="TargetValue" Decimal="5" />
            <PropertyValue Property="Visualization"EnumMember="UI.VisualizationType/Rating" />
      </Record>
</Annotation>
```

LANGUAGE: ABAP CDS

CODE:
```abap
@UI.dataPoint: {
  targetValue: 5,
  visualization: #RATING
}
averageRating;
```

LANGUAGE: CDS

CODE:
```cds
DataPoint #averageRating               : {
        Value         : averageRating,
        TargetValue   : 5.0,
        Visualization : #Rating
}
```

STEP: 7 — Progress Indicator (UI.DataPoint Visualization = Progress)

DESCRIPTION: Render progress bars by setting UI.DataPoint Visualization to Progress and providing Value and TargetValue.

LANGUAGE: XML

CODE:
```xml
<Annotation Term="UI.DataPoint" Qualifier="quantity">
      <Record>
           <PropertyValue Property="Value" Path="stock/quantity" />
            <PropertyValue Property="TargetValue" Decimal="100" />
            <PropertyValue Property="Visualization"EnumMember="UI.VisualizationType/Progress" />
       </Record>
</Annotation>
```

LANGUAGE: ABAP CDS

CODE:
```abap
@UI.dataPoint: {
  targetValue: 100,
  visualization: #PROGRESS
}
quantity;
```

LANGUAGE: CDS

CODE:
```cds
DataPoint #quantity               : {
        Value         : stock.quantity,
        TargetValue   : 100.0,
        Visualization : #Progress
}
```

STEP: 8 — Links: Semantic Link, Quick View, Contact Card, Contact Links, Basic Links

DESCRIPTION: Multiple link patterns — semantic object link for intent-based navigation, quick view and contact card (DataFieldForAnnotation pointing to Communication.Contact), contact links (IsPhoneNumber / IsEmailAddress), and basic hyperlinks (DataFieldWithUrl). Use the matching annotation style for ABAP CDS / CAP CDS.

LANGUAGE: XML (Semantic Object)

CODE:
```xml
<Annotations Target="clouds.products.CatalogService.Products/SoldToParty">
    <Annotation Term="Common.SemanticObject" String="supplier"/>
</Annotations>
```

LANGUAGE: ABAP CDS (Semantic Object)

CODE:
```abap
annotate view PRODUCTS.CATALOGSERVICE.PRODUCTS with {
@Consumption.semanticObject: 'supplier'
soldtoparty;
}
```

LANGUAGE: CDS (Semantic Object)

CODE:
```cds
SoldToParty                   : String(10)                            @(Common : {
SemanticObject                  : 'supplier'
});
```

LANGUAGE: XML (Quick View / Contact Card via DataFieldForAnnotation)

CODE:
```xml
<Annotations Target="clouds.products.CatalogService.Products">
    <Annotation Term="UI.LineItem">
        <Collection>
            <Record Type="UI.DataFieldForAnnotation">
                <PropertyValue Property="Label" String="Supplier"/>
                <PropertyValue Property="Target" AnnotationPath="supplier/@Communication.Contact"/>
            </Record>
        </Collection>
    </Annotation>
</Annotations>

<Annotations Target="sap.fe.manageitems.TechnicalTestingService.Supplier/phoneNumber">
    <Annotation Term="Common.Label" String="Mobile"/>
    <Annotation Term="Communication.IsPhoneNumber" Bool="true"/>
</Annotations>

<Annotations Target="sap.fe.manageitems.TechnicalTestingService.Supplier/emailAddress">
    <Annotation Term="Common.Label" String="Email"/>
    <Annotation Term="Communication.IsEmailAddress" Bool="true"/>
</Annotations>
```

LANGUAGE: ABAP CDS (Contact Card)

CODE:
```abap
annotate view PRODUCTS.CATALOGSERVICE.PRODUCTS with {
@UI.lineItem: [
  {
    label: 'Supplier',
    value: 'SUPPLIER',
    type: #AS_CONTACT,
    position: 1
  }
]
SupplierID;
}

annotate view FE.MANAGEITEMS.TECHNICALTESTINGSERVICE.SUPPLIER with {
    @Semantics.eMail.address: true
    @EndUserText.label: 'EMail'
    emailAddress;
    @Semantics.telephone.type:  [ #CELL ]
    @EndUserText.label: 'Mobile'
    phoneNumber;
}
```

LANGUAGE: CDS (Contact Card)

CODE:
```cds
UI.LineItem                         : [
    {
        $Type  : 'UI.DataFieldForAnnotation',
        Target : 'supplier/@Communication.Contact',
        Label  : 'Supplier'
    }
]
phoneNumber             : String(15)         @(
            title     : 'Mobile',
            Communication.IsPhoneNumber
);
emailAddress             : String(241)         @(
            title     : 'Email',
            Communication.IsEmailAddress
);
```

LANGUAGE: XML (Contact Links: phone/email)

CODE:
```xml
<Annotations Target="sap.fe.manageitems.TechnicalTestingService.LineItems/phoneNumber">
    <Annotation Term="Common.Label" String="Mobile"/>
    <Annotation Term="Communication.IsPhoneNumber" Bool="true"/>
</Annotations>
```

```xml
<Annotations Target="sap.fe.manageitems.TechnicalTestingService.LineItems/emailAddress">
    <Annotation Term="Common.Label" String="Email"/>
    <Annotation Term="Communication.IsEmailAddress" Bool="true"/>
</Annotations>
```

LANGUAGE: XML (Basic link with DataFieldWithUrl)

CODE:
```xml
<Annotation Term="UI.FieldGroup" Qualifier="DataFieldUrl">
    <Record Type="UI.FieldGroupType">
        <PropertyValue Property="Data">
            <Collection>
                <Record Type="UI.DataFieldWithUrl">
                    <PropertyValue Property="Url" String="www.sap.com"/>
                    <PropertyValue Property="Value" String="This is an URL"/>
                    <PropertyValue Property="IconUrl" String="sap-icon://arrow-right"/>
                </Record>
                <Record Type="UI.DataFieldWithUrl">
                    <PropertyValue Property="Url" String="www.sap.com"/>
                    <PropertyValue Property="Value" String=""/>
                    <PropertyValue Property="IconUrl" Path="oneIcon"/>
                </Record>
                <Record Type="UI.DataFieldWithUrl">
                    <PropertyValue Property="Url" Path="oneUrl"/>
                    <PropertyValue Property="Value" String="This is an URL three"/>
                    <PropertyValue Property="IconUrl" String="sap-icon://arrow-right"/>
                </Record>
            </Collection>
        </PropertyValue>
    </Record>
</Annotation>
```

LANGUAGE: ABAP CDS (Basic link)

CODE:
```abap
@UI.fieldGroup: [
  {
    iconUrl: 'sap-icon://arrow-right'
    type: #WITH_URL,
    position: 1 ,
    qualifier: 'DataFieldUrl'
  },
  {
    url: 'ONEURL',
    value: 'ONEURL',
    type: #WITH_URL,
    position: 2 ,
    qualifier: 'DataFieldUrl'
  }
]
```

LANGUAGE: CDS (Basic link)

CODE:
```cds
UI.FieldGroup #DataFieldUrl: {
Data : [{
              $Type : 'UI.DataFieldWithUrl',
              Url   : 'www.sap.com',
              Value : 'This is an URL',
              IconUrl: 'sap-icon://arrow-right',
       },
       {
              $Type  : 'UI.DataFieldWithUrl',
              Url    : oneDisplay,
              Value  : oneUrl,
              IconUrl: oneIcon
}
}]
```

STEP: 9 — TextArea / ExpandableText (UI.MultiLineText + manifest controlConfiguration)

DESCRIPTION: Use UI.MultiLineText on a property to render TextArea in edit mode and ExpandableText in display. Configure defaults and custom lengths via manifest.json controlConfiguration > fields/columns. Use formatOptions keys: textLinesEdit, textMaxLines, textMaxCharactersDisplay, textExpandBehaviorDisplay, textMaxLength.

LANGUAGE: XML

CODE:
```xml
<Annotations Target="com.c_salesordermanage_sd.SalesOrderManage">
    <Annotation Term="Common.Label" String="Customer Reference"/>
    <Annotation Term="UI.MultiLineText" Bool="true"/>
</Annotations>
```

LANGUAGE: JSON

CODE:
```json
{
  "sap.ui5": {
    "routing": {
      "targets": {
        "SalesOrderManageObjectPage": {
          "options": {
            "settings": {
              "controlConfiguration": {
                "@com.sap.vocabularies.UI.v1.FieldGroup#myQualifier": {
                  "fields": {
                    "DataField::myFormTextField": {
                      "formatOptions": {
                        "textLinesEdit": "6",
                        "textMaxCharactersDisplay": "Infinity"
                      }
                    }
                 }
              },
              "myEntity/@com.sap.vocabularies.UI.v1.LineItem": {
                  "columns": {
                    "DataField::myTableTextField": {
                      "formatOptions": {
                        "textLinesEdit": "3",
                        "textMaxLines": "5",
                        "textMaxCharactersDisplay": "400",
                        "textExpandBehaviorDisplay" : "Popover"
                      }
                    }
                  }
                }
             }
           }
         }
       }
     }
  }
}
```

LANGUAGE: Text (formatOptions summary)

CODE:
```text
formatOptions keys:
- textLinesEdit: number/string -> visible lines in edit mode (default 4)
- textMaxLines: number/string -> maximum growth lines in edit mode
- textMaxCharactersDisplay: number/string or "Infinity" -> chars shown before "More"
- textExpandBehaviorDisplay: "InPlace" | "Popover" -> how full text is displayed
- textMaxLength: number/string -> max characters allowed in edit input
```

STEP: 10 — Micro Chart Facet

DESCRIPTION: Annotate a field to render a micro chart facet; use the Micro Chart facet and related annotations to show critical measures/criticality. See micro-chart-facet and adding-a-micro-chart-to-a-table for patterns.

LANGUAGE: XML (hint)

CODE:
```xml
<!-- Example: add a micro chart annotation referencing a chart facet annotation on the entity -->
<!-- See Micro Chart Facet docs for full examples -->
```

STEP: 11 — File Upload/Download (Edm.Stream)

DESCRIPTION: Enable Edm.Stream on entity properties to allow file upload/download in object page forms. Follow Enabling Stream Support doc for required OData service and annotations.

LANGUAGE: XML (hint)

CODE:
```xml
<!-- Annotate the property as Edm.Stream in the service metadata and add form binding to display upload/download controls -->
```

STEP: 12 — Boolean Properties: Checkbox or Radio Buttons

DESCRIPTION: Boolean property renders as checkbox by default. To render as immediate-action radio buttons (Yes/No), set formatOptions.useRadioButtonsForBoolean either in XML view macros or in manifest controlConfiguration.

LANGUAGE: XML (View macros)

CODE:
```xml
<macros:Field metaPath="BooleanProperty" >
    <macros:formatOptions>
        <macrosF:FieldFormatOptions useRadioButtonsForBoolean="true"/>
    </macros:formatOptions>
</macros:Field>
```

LANGUAGE: JSON (manifest.json controlConfiguration)

CODE:
```json
{
  "controlConfiguration": {
    "@com.sap.vocabularies.UI.v1.FieldGroup#GeneralInformation": {
      "fields": {
        "DataField::booleanField": {
          "formatOptions": {
            "useRadioButtonsForBoolean": true
          }
        }
      }
    }
  }
}
```

STEP: 13 — Timestamp with Timezone (Common.IsTimezone)

DESCRIPTION: Annotate a property that contains a timezone code with @Common.IsTimezone so the UI shows timezone text in display mode. Use with datetime fields to render timezone information.

LANGUAGE: XML (hint)

CODE:
```xml
<!-- Annotate timezone code property -->
<!-- Example: @Common.IsTimezone on the timezone property associated with a timestamp -->
```

STEP: 14 — Masked Input Field (UI.InputMask) and Masked Display (Common.Masked)

DESCRIPTION: Use UI.InputMask on properties to enforce input format on the client. Define Mask, PlaceholderSymbol, and Rules for MaskSymbol regular expressions. For display masking (password-style), use Common.Masked to visually conceal values. Ensure placeholder symbol != mask symbols and use ^ (caret) to escape rule characters as immutable.

LANGUAGE: XML (UI.InputMask examples)

CODE:
```xml
<Annotations Target="sap.fe.core.MaskInputMassEdit.MainEntity/MaskedInputPhone">
          <Annotation Term="UI.InputMask">
              <Record>
                   <PropertyValue Property="Mask" String="(***) *** ******"/>
                   <PropertyValue Property="PlaceholderSymbol" String="_"/>
              </Record>
          </Annotation>
          <Annotation Term="UI.Placeholder" String="Enter twelve-digit number"/>
</Annotations>

<Annotations Target="sap.fe.core.MaskInputMassEdit.MainEntity/MaskedInputRegistration">
          <Annotation Term="UI.InputMask">
                <Record>
                   <PropertyValue Property="Mask" String="I____-__"/>
                   <PropertyValue Property="PlaceholderSymbol" String="_"/>
                   <PropertyValue Property="Rules">
                        <Collection>
                                  <Record>
                                       <PropertyValue Property="MaskSymbol" String="_"/>
                                       <PropertyValue Property="RegExp" String="[0-9]"/>
                                  </Record>
                        </Collection>
                   </PropertyValue>
               </Record>
          </Annotation>
</Annotations>
```

LANGUAGE: CDS (CAP InputMask examples)

CODE:
```cds
MaskedInputPhone   : String          @(
      UI.InputMask  : {
         Mask       : '(***) *** ******',
         PlaceholderSymbol: '_',
      },
      UI.Placeholder: 'Enter twelve-digit number'
      );
     MaskedInputRegistration    : String          @(
      UI.InputMask  : {
        Mask       : 'I****-**',
        PlaceholderSymbol: '_',
        Rules      : [{
         MaskSymbol: '*',
         RegExp    : '[0-9]'
        }]
      },
      UI.Placeholder: 'Enter digits registration number'
);
     MaskedInputSAP            : String          @(
  UI.InputMask  : {
    Mask             : 'S^AP-AA-999',
    PlaceholderSymbol: '_',
    Rules            : [
      {
        MaskSymbol: '9',
        RegExp    : '[0-9]'
      },
      {
        MaskSymbol: 'A',
        RegExp    : '[A-Z]'
      }
    ]
  },
  UI.Placeholder: 'Starts with SAP followed by two uppercase letter and three digits'
);
```

LANGUAGE: XML (Common.Masked)

CODE:
```xml
<Annotations Target="sap.fe.core.FieldDisplayStyles.RootEntity/MaskedField">
        <Annotation Term="Common. Masked" Bool="true"/>
</Annotations>
```

LANGUAGE: CDS (Common.Masked)

CODE:
```cds
MaskedField  : String  @Common : {Masked: true};
```


**TITLE**: Disabling the Editing Status Filter

**INTRODUCTION**: Disable the default Editing Status filter that appears on list report pages for draft-enabled Fiori elements applications. Use annotation changes (XML or CAP CDS) to remove the DraftAdministrativeData filter so end users cannot filter by editing status.

**TAGS**: fiori-elements-framework, annotations, draft, filter, list-report, EditingStatus

**STEP**: 1 — When to use this change

**DESCRIPTION**: Use this when you want to remove the Editing Status filter from list reports in draft-enabled applications. Note: removing this filter prevents end users from filtering objects by editing/draft status.

**LANGUAGE**: text

**CODE**:
```text
Purpose: Remove the Editing Status (DraftAdministrativeData) filter from list reports.
Consequence: End users can no longer filter objects based on editing status.
```

**STEP**: 2 — Add XML annotation to disable the Editing Status filter

**DESCRIPTION**: Add the following XML annotation to your app's annotation file (the XML annotation file your app consumes) to set Filterable=false on the DraftAdministrativeData navigation property. This uses the Capabilities.NavigationRestrictions / RestrictedProperties / NavigationPropertyRestriction / FilterRestrictions structure.

**LANGUAGE**: XML

**CODE**:
```xml
<Annotations Target="TravelService.EntityContainer/Travel">
   <Annotation Term="Capabilities.NavigationRestrictions">
      <Record Type="Capabilities.NavigationRestrictionsType">
         <PropertyValue Property="RestrictedProperties">
            <Collection>
               <Record Type="Capabilities.NavigationPropertyRestriction">
                  <PropertyValue Property="NavigationProperty" NavigationPropertyPath="DraftAdministrativeData"/>
                  <PropertyValue Property="FilterRestrictions">
                     <Record Type="Capabilities.FilterRestrictionsType">
                        <PropertyValue Property="Filterable" Bool="false"/>
                     </Record>
                  </PropertyValue>
               </Record>
           </Collection>
        </PropertyValue>
      </Record>
   </Annotation>
</Annotations>
```

**STEP**: 3 — Add CAP CDS annotation to disable the Editing Status filter

**DESCRIPTION**: For CAP-based services, add this CDS annotate block to the service model so that DraftAdministrativeData is marked as not filterable. Place it in your service CDS file or an appropriate annotation CDS file that is deployed with the service.

**LANGUAGE**: CDS

**CODE**:
```c
annotate TravelService.Travel with @(
Capabilities: {
   NavigationRestrictions : {
       $Type : 'Capabilities.NavigationRestrictionsType',
       RestrictedProperties : [
           {
               $Type : 'Capabilities.NavigationPropertyRestriction',
               NavigationProperty : DraftAdministrativeData,
               FilterRestrictions : {
                   $Type : 'Capabilities.FilterRestrictionsType',
                   Filterable : false,
               },
           },
       ],
   },
});
```

**STEP**: 4 — ABAP CDS annotation guidance

**DESCRIPTION**: No ABAP CDS sample is provided. If you are using ABAP CDS and need the same behavior, implement the equivalent annotation in your local XML annotation file consumed by the UI.

**LANGUAGE**: ABAP CDS

**CODE**:
```text
No ABAP CDS annotation sample is available. Please use the local XML annotation.
```

**STEP**: 5 — Verify and consider user impact

**DESCRIPTION**: After deploying the annotation change, verify the list report UI: the Editing Status filter should no longer appear. Inform stakeholders because end users will no longer be able to filter by editing status (draft/active).

Disabling the Editing Status Filter

fiori-elements-framework annotations draft filter list-report EditingStatus


**TITLE**: Displaying and Controlling Actions on the Object Page (Fiori Elements)

**INTRODUCTION**: This document summarizes rules and actionable examples for where and how actions are displayed on the Object Page in SAP Fiori elements (OData V4). It explains display order, mode-based placement, how to set action criticality using annotations, and how to change order using the "position" property (manifest-based or annotation-based actions). Use the snippets as templates and adapt to your service/manifest structure.

**TAGS**: fiori-elements, object-page, actions, annotations, manifest, odata-v4, criticality, semantic-actions

STEP: 1 — Default order of actions in the Object Page header

DESCRIPTION: The Object Page header displays actions in a specific default order. Use this to anticipate where actions appear by default and where to override placement if needed.

- Default display order:
  1. Generic actions (e.g., Save, Edit)
  2. Application-specific actions (order as defined in metadata)
  3. Manifest-based custom actions
  4. Related Apps button
  5. Other generic actions (e.g., Share)

- Note: For OData V4, if semantic actions (with criticality) are defined, they are automatically placed first and may change emphasis of standard generic actions.

LANGUAGE: None

CODE:
```text
# No code for this step — conceptual rules only.
# Reference: Adding Custom Actions Using Extension Points (see section "Additional Features in SAP Fiori elements for OData V4")
# Related docs:
# - enabling-actions-in-the-object-page-header-5fe4396.md
# - adding-custom-actions-using-extension-points-7619517.md
```

STEP: 2 — Display of actions depending on mode (Display vs Edit/Create)

DESCRIPTION: Actions appear in different toolbars depending on the current object page mode. Implement or place actions accordingly:

- Display mode: actions are shown in the header toolbar.
- Edit/Create mode: relevant actions are moved to the footer bar (e.g., Edit mode -> Save, Cancel; Create mode -> Create, Cancel).

LANGUAGE: None

CODE:
```text
# No code for this step — behavioral rules only.
# Visual reference: Object Page Footer Bar (Edit Mode) screenshot (images/Object_Page_Footer_Bar_Edit_Mode_2c8767f.png)
```

STEP: 3 — Set action criticality via OData annotations (OData V4) — XML example

DESCRIPTION: Add criticality to actions using annotations so the runtime can style and treat them as semantic actions (these may be prioritized). The example below shows an OData V4 annotation using UI.v1.DataFieldForAction with a Criticality enum value. Adapt Target, Action name, and enum to your model.

LANGUAGE: XML

CODE:
```xml
<Annotations Target="YourServiceNamespace.YourEntityType">
  <Annotation Term="com.sap.vocabularies.UI.v1.LineItem">
    <Collection>
      <Record Type="com.sap.vocabularies.UI.v1.DataFieldForAction">
        <PropertyValue Property="Action" String="Approve"/>
        <PropertyValue Property="Label" String="Approve"/>
        <!-- Use the appropriate Criticality enum member for your case -->
        <PropertyValue Property="Criticality" EnumMember="com.sap.vocabularies.UI.v1.CriticalityType/High"/>
      </Record>
    </Collection>
  </Annotation>
</Annotations>
```

STEP: 4 — Set action criticality via CDS annotations (CAP/ABAP CDS style example)

DESCRIPTION: If you use CDS annotations, declare the action and annotate the entity to mark the action as a line-item action with criticality. This example shows the concept (adapt to your exact CDS syntax / tooling):

LANGUAGE: CDS

CODE:
```cds
entity SalesOrder {
  key ID : UUID;
  // fields...
}

// Define action (service or entity action)
action approve() returns Boolean;

// Annotate the action for UI with criticality
annotate SalesOrder with {
  @UI.lineItem : [
    { type           : #DataFieldForAction,
      label          : 'Approve',
      action         : 'approve',
      criticality    : #High
    }
  ]
};
```

STEP: 5 — Change order of actions using "position" (manifest-based and annotation-based)

DESCRIPTION: You can change the order of action buttons defined in the manifest or annotations by specifying a "position" property. Use position to place actions before/after other actions or at particular positions in the header/footer. The snippet below shows a manifest-based configuration skeleton — adapt keys, page structure and property names to your project manifest layout and Fiori elements version. Consult "Adding Custom Actions Using Extension Points" for exact manifest schema for your FE version.

LANGUAGE: JSON

CODE:
```json
{
  "sap.ui.generic.app": {
    "pages": [
      {
        "entitySet": "SalesOrders",
        "component": "sap.suite.ui.generic.template.ObjectPage",
        "settings": {
          "header": {
            "actions": {
              "ZCustomAction": {
                "label": "My Custom",
                "target": "ZCustomAction",
                "press": "onCustomAction",
                "position": "After" /* Example values: "Before" | "After" | "First" | "Last" — check your FE version docs */
              }
            }
          }
        }
      }
    ]
  }
}
```

STEP: 6 — Additional considerations and references

DESCRIPTION: Summary of important operational notes and where to look for more detail:

- Semantic/criticality-enabled actions (OData V4) are placed automatically before generic actions — this can change emphasis behavior.
- You can reorder both manifest-based and annotation-based actions via "position".
- Related topics to implement or review:
  - Enabling Actions in the Object Page Header (enabling-actions-in-the-object-page-header-5fe4396.md)
  - Adding Custom Actions Using Extension Points (adding-custom-actions-using-extension-points-7619517.md)
  - Adding Action Buttons to Forms in Sections (adding-action-buttons-to-forms-in-sections-e64efda.md)
  - Defining Determining Actions (defining-determining-actions-1743323.md)
  - Setting the Criticality for Actions (setting-the-criticality-for-actions-12f2ba2.md)
  - Generic Action Buttons in Tables on the Object Page: Additional Considerations (generic-action-buttons-in-tables-on-the-object-page-additional-considerations-d27ae99.md)

LANGUAGE: None

CODE:
```text
# Use the linked documentation files for full schema and exact property names for your Fiori elements version:
# - adding-custom-actions-using-extension-points-7619517.md
# - setting-the-criticality-for-actions-12f2ba2.md
# - enabling-actions-in-the-object-page-header-5fe4396.md
```

fiori-elements object-page actions annotations manifest odata-v4 criticality semantic-actions


**TITLE**: Configuring Decimal Alignment and Display for Currency and Unit of Measure in SAP Fiori Elements (OData V4)

**INTRODUCTION**: This document explains how to control decimal alignment and decimal display for currency and unit-of-measure fields in SAP Fiori elements (OData V4) tables. Use manifest.json keys to set decimal padding for alignment, preserve backend-decimal precision for currency, and restrict unit decimals to the unit's defined scale.

**TAGS**: fiori-elements-framework, sap.fe, manifest.json, currency, unitOfMeasure, decimalPadding, preserveDecimalsForCurrency, showOnlyUnitDecimals, OData V4

**STEP**: 1 — Alignment behavior and default padding

**DESCRIPTION**: Understand default visual behavior and padding used for alignment in table display mode:
- Amounts are aligned on the decimal separator.
- Currency or unit-of-measure labels are right-aligned.
- Default decimal padding used to align amounts: currency = 5, unitOfMeasure = 3.

Use these defaults as a baseline before overriding in manifest.json.

**LANGUAGE**: JSON

**CODE**:
```json
{
  "alignment": {
    "amountAlignedOn": "decimalSeparator",
    "labelAlignedOn": "right",
    "defaults": {
      "currencyDecimalPadding": 5,
      "unitOfMeasureDecimalPadding": 3
    }
  }
}
```

**STEP**: 2 — Change decimal padding for currency and unit-of-measure

**DESCRIPTION**: Override the default decimalPadding values for currency and unitOfMeasure to control the padding (number of decimal positions reserved for alignment). Add these keys under "sap.fe.macros.table" in your app's manifest.json.

File: manifest.json

**LANGUAGE**: JSON

**CODE**:
```json
"sap.fe": {
    "macros": {
        "table": {
            "currency": {
                "decimalPadding": 5
            },
            "unitOfMeasure": {
                "decimalPadding": 3
            }
        }
    }
}
```

**STEP**: 3 — Preserve exact decimal places returned from the backend for currency

**DESCRIPTION**: To display currency values with the exact number of decimal places provided by the backend (do not round or trim), enable the preserveDecimalsForCurrency flag under "sap.fe.app" in manifest.json.

File: manifest.json

**LANGUAGE**: JSON

**CODE**:
```json
"sap.fe": {
    "app": {
        "preserveDecimalsForCurrency": true
    }
}
```

**STEP**: 4 — Limit decimals to the unit definition for unit-of-measure values

**DESCRIPTION**: To restrict displayed decimals for unit-of-measure fields to the number defined for the unit (i.e., show only the unit's decimals), enable showOnlyUnitDecimals under "sap.fe.app" in manifest.json.

File: manifest.json

**LANGUAGE**: JSON

**CODE**:
```json
"sap.fe": {
    "app": {
       "showOnlyUnitDecimals": true
    }
}
```

fiori-elements-framework
sap.fe
manifest.json
currency
unitOfMeasure
decimalPadding
preserveDecimalsForCurrency
showOnlyUnitDecimals
OData V4


**TITLE**: Display an Illustrated Message or Text When a Table Has No Data (SAP Fiori elements)

**INTRODUCTION**: This document shows how to control the illustrated "No Data" message (or replace it with plain text) for tables in SAP Fiori elements pages. It includes default behavior, how to override default texts via i18n, how to enable text-only messages via the manifest, and how to add custom actions to the illustrated message using the beforeRebindTable extension point.

**TAGS**: fiori-elements, no-data, illustrated-message, i18n, manifest.json, extension-point, beforeRebindTable, OData V4, UI5, SAP Fiori

STEP: Default behavior and contexts

DESCRIPTION: Understand the default illustrated message behavior and contexts in which different illustrations/titles/descriptions are shown. Use this knowledge to decide whether to override texts, switch to text-only messages, or add custom actions.

- List report: Illustrated message size adapts to available table space.
- Object page anchor bar mode: Reduced illustrated message size to keep information density.
- Icon tab bar mode: If section contains only a table, illustrated message adapts like list report.
- Default displayed texts (examples):
  - Opening a list report without autoload: Title "Let’s get some results", Description "Start by providing your search or filter criteria."
  - No filters and no data on list report: Title "No results found", Description "Start by providing your search or filter criteria."
  - Filters applied and no results: Title "No results found", Description "Try changing your filter criteria."
  - Multi-view mode table with no data: Title "No no results found", Description "Try changing the view or filter criteria."
  - Object page with no search/filters and no data: Title "No items available", Description "When there are, you'll find them here."

LANGUAGE: N/A

CODE:
```text
(Informational defaults described above — no code)
```

STEP: Override default illustrated message texts via i18n

DESCRIPTION: Override standard illustrated message texts by adding specific i18n keys to the list report and object page i18n files. See the Localization of UI Texts documentation for the complete list of keys to provide.

LANGUAGE: N/A

CODE:
```text
File: i18n/<YourPage>.properties
# Add keys referenced in "Localization of UI Texts" (see localization-of-ui-texts-b8cb649.md)
# Example (pseudo-keys — replace with exact keys from Localization doc):
NO_RESULTS_TITLE=No results found
NO_RESULTS_DESCRIPTION=Try changing your filter criteria.
# Use the real keys and translations for your app
```

STEP: Show text instead of illustrated message (manifest setting)

DESCRIPTION: Use the manifest setting useTextForNoDataMessages to display plain text messages instead of illustrated messages on an object page. This setting applies to all tables on the page. When enabled, you must override default texts using i18n keys (see Localization of UI Texts).

LANGUAGE: JSON

CODE:
```json
"SalesOrderManageObjectPage": {
    "type": "Component",
    "id": "SalesOrderManageObjectPage",
    "name": "sap.fe.templates.ObjectPage",
    "options": {
        "settings": {
            "contextPath": "/SalesOrderManage",
            "enhanceI18n": "i18n/SalesOrderObjectPage.properties",
            "variantManagement": "Control",
            "showRelatedApps": true,
            "sectionLayout": "Tabs",
            "useTextForNoDataMessages": true,
            "controlConfiguration": {
...
            }
        }
    }
}
```

STEP: Add actions to an illustrated message using beforeRebindTable

DESCRIPTION: Add contextual actions (buttons) to the IllustratedMessage shown when a table has no data. Use the beforeRebindTable extension point to set a custom IllustratedMessage on the table instance via table.setNoData(...). Configure the extension point in manifest.json and implement the callback in a ControllerExtension module. The manifest mapping must point to your controller extension and method, and the controller must construct and apply the IllustratedMessage based on filter/search state.

LANGUAGE: JSON

CODE:
```json
"targets": {
    "sample": {
        "type": "Component",
        "id": "Default",
        "name": "sap.fe.templates.ObjectPage",
        "level": 1,
        "options": {
            "settings": {
                "contextPath": "/RootEntity",
                "editableHeaderContent": false,
                "variantManagement": "Control",
                "controlConfiguration": {
                    "_Child/@com.sap.vocabularies.UI.v1.LineItem": {
                        "tableSettings": {
                            "beforeRebindTable": ".extension.sap.fe.core.fpmExplorer.OPExtend.onTableRefresh"
                        }
                    }
                }
            }
        }
    }
}
```

STEP: Implement the ControllerExtension callback to set IllustratedMessage and actions

DESCRIPTION: Implement the beforeRebindTable callback to inspect the collectionBindingInfo (filters and $search) and set a customized sap.m.IllustratedMessage on the table. Use table.setNoData(illustratedMessage) to apply it. The sample below is a full controller extension module demonstrating two different messages and actions (one for filter/search applied and one for no filters/search and edit mode).

LANGUAGE: JavaScript

CODE:
```javascript
sap.ui.define(
    [
        "sap/ui/core/mvc/ControllerExtension",
        "sap/ui/model/Filter",
        "sap/ui/model/FilterOperator",
        "sap/m/IllustratedMessage",
        "sap/m/IllustratedMessageType",
        "sap/m/Button",
        "sap/m/MessageToast",
        "sap/m/IllustratedMessageSize"
    ],
    function (
        ControllerExtension,
        Filter,
        FilterOperator,
        IllustratedMessage,
        IllustratedMessageType,
        Button,
        MessageToast,
        IllustratedMessageSize
    ) {
        "use strict";

        return ControllerExtension.extend("sap.fe.core.fpmExplorer.OPExtend", {
            onTableRefresh: function (event) {
                var collectionBindingInfoAPI = event.getParameter("collectionBindingInfo");
                var table = this.getView().byId("fe::table::_Child::LineItem::Table");
                var illustratedMessage = new IllustratedMessage();
                var showDialogNoData = function () {
                    return MessageToast.show("Action when No Data in edit mode");
                };
                var showDialogFilterSearch = function () {
                    return MessageToast.show("Action when No Data with filter or search");
                };

                //Filters or Search applied
                if (
                    (collectionBindingInfoAPI.getFilters() && collectionBindingInfoAPI.getFilters().aFilters.length > 0) ||
                    collectionBindingInfoAPI.collectionBindingInfo.parameters.$search
                ) {
                    illustratedMessage.setTitle("No Data");
                    illustratedMessage.setDescription("Change Search or filter criteria.");
                    illustratedMessage.setIllustrationType(IllustratedMessageType.NoSearchResults);
                    illustratedMessage.setIllustrationSize(sap.m.IllustratedMessageSize.Dot);
                    illustratedMessage.addAdditionalContent(new Button({ text: "My Action", press: showDialogFilterSearch }));
                    table.setNoData(illustratedMessage);
                } else {
                    //No filter or search and table in edit mode
                    illustratedMessage.setTitle("No Item found");
                    illustratedMessage.setDescription("Please create some.");
                    illustratedMessage.setIllustrationType(IllustratedMessageType.NoSearchResults);
                    illustratedMessage.setIllustrationSize(sap.m.IllustratedMessageSize.Dot);
                    illustratedMessage.addAdditionalContent(
                        new Button({ text: "Create New Item", visible: "{ui>/isEditable}", press: showDialogNoData })
                    );
                    table.setNoData(illustratedMessage);
                }
            }
        });
    }
);
```

STEP: References and live examples

DESCRIPTION: For keys to override and exact localization key names, consult "Localization of UI Texts". For live examples and API references for table NoData handling, see the SAP Fiori development portal links (Table - Extensions - Table APIs).

LANGUAGE: N/A

CODE:
```text
See:
- Localization of UI Texts: localization-of-ui-texts-b8cb649.md
- Building Blocks - Table - Extensions - Table APIs: https://ui5.sap.com/test-resources/sap/fe/core/fpmExplorer/index.html#/buildingBlocks/table/tableNoData
```

fiori-elements
no-data
illustrated-message
i18n
manifest.json
extension-point
beforeRebindTable
OData V4
UI5
SAP Fiori


**TITLE**: Displaying Fields in Smartforms on Small Devices (UI.Importance for SAP Fiori elements V2)

**INTRODUCTION**: Use the UI.Importance annotation to control visibility of individual data fields inside Smartforms on small-screen devices. This applies only to SAP Fiori elements for OData V2. Set importance per data field (High / Medium / Low) to determine whether the field is shown on desktops, tablets, and mobiles.

**TAGS**: sap-fiori, fiori-elements, annotations, ui.importance, smartforms, odata-v2, cds, abap, xml, cap

**STEP**: Applicability and default behavior

**DESCRIPTION**: Confirm this approach is only valid for SAP Fiori elements (OData V2). If UI.Importance is not specified for a field, the default is None (treated as Medium importance).

**LANGUAGE**: Text

**CODE**:
```Text
Applicability: SAP Fiori elements for OData V2 only.
Default behavior: If UI.Importance is not specified, default = None -> treated as Medium.
```

**STEP**: Importance -> Visibility mapping

**DESCRIPTION**: Use these mappings when deciding which importance to assign to a data field.

**LANGUAGE**: Text

**CODE**:
```Text
UI.Importance = High   -> Visible on desktops, tablets, and mobiles.
UI.Importance = Medium -> Visible on desktops and tablets (hidden on mobiles).
UI.Importance = Low    -> Visible on desktops and tablets (hidden on mobiles).
```

**STEP**: XML Annotation example (UI.FieldGroup with UI.Importance on data fields)

**DESCRIPTION**: Add UI.Importance annotations to UI.DataField records inside a UI.FieldGroup. This example shows High, Medium, Low and an unspecified field (defaults to Medium). Use this XML in your annotation file or CDS-to-XML export for OData V2 services.

**LANGUAGE**: XML

**CODE**:
```xml
<Annotation Term="UI.FieldGroup" Qualifier="GeneralInformation">
    <Record>
        <PropertyValue Property="Data">
            <Collection>
                <Record Type="UI.DataField">
                    <PropertyValue Property="Value" Path="SalesOrder"/>
                    <Annotation Term="UI.Importance" EnumMember="UI.ImportanceType/High"/>
                </Record>
                <Record Type="UI.DataField">
                    <PropertyValue Property="Label" String="Business Partner ID"/>
                    <PropertyValue Property="Value" Path="BusinessPartnerID"/>
                    <Annotation Term="UI.Importance" EnumMember="UI.ImportanceType/Low"/>
                </Record>
                <Record Type="UI.DataField">
                    <PropertyValue Property="Label" String="Opportunity ID"/>
                    <PropertyValue Property="Value" Path="OpportunityID"/>
                    <Annotation Term="UI.Importance" EnumMember="UI.ImportanceType/Medium"/>
                </Record>
                <Record Type="UI.DataField">
                    <PropertyValue Property="Label" String="Enabled"/>
                    <PropertyValue Property="Value" Path="EnabledStatus"/>
                </Record>
            </Collection>
        </PropertyValue>
        <PropertyValue Property="Label" String="General Information"/>
    </Record>
</Annotation>
```

**STEP**: ABAP CDS Annotation example (UI.fieldGroup with importance per element)

**DESCRIPTION**: Apply @UI.fieldGroup annotations in ABAP CDS. Set importance: #HIGH, #MEDIUM, #LOW per element. The annotated element follows the field-level importance on runtime Smartforms for OData V2.

**LANGUAGE**: ABAP CDS

**CODE**:
```
@UI.fieldGroup: [
  {
    importance: #HIGH,
    position: 10,
    qualifier: 'GeneralInformation',
    groupLabel: 'General Information'
  }
]
SALESORDER;

@UI.fieldGroup: [
  {
    importance: #LOW,
    label: 'Business Partner ID',
    position: 20,
    qualifier: 'GeneralInformation'
  }
]
BUSINESSPARTNERID;

@UI.fieldGroup: [
  {
    importance: #MEDIUM,
    label: 'Opportunity ID',
    position: 30,
    qualifier: 'GeneralInformation'
  }
]
OPPORTUNITYID;

@UI.fieldGroup: [
  {
    label: 'Enabled',
    position: 40,
    qualifier: 'GeneralInformation'
  }
]
ENABLEDSTATUS;
```

**STEP**: CAP CDS Annotation example (UI.FieldGroup with importance flags)

**DESCRIPTION**: In CAP CDS, define UI.FieldGroup with a Data collection. Use ![@UI.Importance] : #High/#Medium/#Low to set importance per UI.DataField. This example preserves the same visibility semantics for OData V2 Smartforms.

**LANGUAGE**: CDS

**CODE**:
```
UI.FieldGroup #GeneralInformation : {
    Data : [
        {
            $Type : 'UI.DataField',
            Value : SalesOrder,
            ![@UI.Importance] : #High
        },
        {
            $Type : 'UI.DataField',
            Label : 'Business Partner ID',
            Value : BusinessPartnerID,
            ![@UI.Importance] : #Low
        },
        {
            $Type : 'UI.DataField',
            Label : 'Opportunity ID',
            Value : OpportunityID,
            ![@UI.Importance] : #Medium
        },
        {
            $Type : 'UI.DataField',
            Label : 'Enabled',
            Value : EnabledStatus
        }
    ],
    Label : 'General Information'
}
```

**STEP**: Important implementation notes

**DESCRIPTION**: Follow these constraints when using UI.Importance in Smartforms.

**LANGUAGE**: Text

**CODE**:
```Text
- You must set UI.Importance on each data field inside a FieldGroup; you cannot hide an entire FieldGroup or Identification section by setting UI.Importance on the group itself.
- UI.Importance affects only data fields rendered inside the smartform.
- Use per-field importance to guarantee predictable mobile behavior.
```

sap-fiori fiori-elements annotations ui.importance smartforms odata-v2 cds abap xml cap


**TITLE**: Displaying Images in Tables (Fiori Elements)

**INTRODUCTION**: This guide shows the required annotations to display images inside table line items in SAP Fiori Elements. It covers: adding the data field to the line item, marking a property as an image URL, using Common.Text for accessibility (alt text), and handling media properties for OData V4 (stream and binary). Use the exact annotation snippets in your local annotation file or CDS definitions.

**TAGS**: fiori-elements-framework, annotations, images, OData-v4, CDS, XML, ABAP

STEP: 1 — Add an image data field to the line item

DESCRIPTION: Add a UI.DataField lineItem entry that references the property containing the image URL. Mark its importance as needed. Provide one of the following annotation formats depending on your technology (XML local annotations, ABAP CDS, or CAP CDS).

LANGUAGE: XML
CODE:
```xml
<Record Type="UI.DataField">
    <PropertyValue Property="Value" Path="ProductPictureURL"/>
    <Annotation Term="UI.Importance" EnumMember="UI.ImportanceType/High"/>
</Record>
```

LANGUAGE: ABAP CDS
CODE:
```abap
@UI.lineItem: [{ importance: #HIGH }]
PRODUCTPICTUREURL;
```

LANGUAGE: CAP CDS
CODE:
```cap
{
    $Type : 'UI.DataField',
    Value : ProductPictureURL,
    ![@UI.Importance] : #High
}
```

STEP: 2 — Annotate the property as an image URL and provide alt text (optional)

DESCRIPTION: Annotate the property that contains the image URL using UI.IsImageUrl (XML) or equivalent CDS annotations. Optionally add Common.Text to supply alt text (screen-reader accessible, assigned to sap.m.Image@alt). Use the example for the appropriate format. Preserve the target property path exactly (example: STTA_PROD_MAN.STTA_C_MP_ProductType/ProductPictureURL).

LANGUAGE: XML
CODE:
```xml
<Annotations Target="STTA_PROD_MAN.STTA_C_MP_ProductType/ProductPictureURL">
    <Annotation Term="UI.IsImageUrl" />
    <Annotation Term="Common.Text" String="{Product}" />
</Annotations>
```

LANGUAGE: ABAP CDS
CODE:
```abap
@Semantics.imageUrl: true
@UI.textArrangement: #TEXT_ONLY
PRODUCTPICTUREURL;
```

LANGUAGE: CAP CDS
CODE:
```cap
annotate STTA_PROD_MAN.STTA_C_MP_ProductType with {
  @UI.IsImageUrl : true
  @Common.Text : '{Product}'
  ProductPictureURL
};
```

STEP: 3 — OData V4: Use a stream property (image served via URL)

DESCRIPTION: For OData V4, a stream-typed property can be used when the property provides a URL to the media. In local XML annotations, set Core.IsURL = true and Core.MediaType to the correct image MIME type (e.g. image/jpg). Include Common.Text for alt text. Stream properties are read-only (media read from the URL only). See the OData v4 JSON format documentation for stream properties if needed.

LANGUAGE: XML
CODE:
```xml
<Annotations Target="STTA_PROD_MAN.STTA_C_MP_ProductType/ProductPictureURL">
   <Annotation Term="Common.Text" String="{Product}" />
   <Annotation Term="Core.IsURL" Bool="true"/>
   <Annotation Term="Core.MediaType" String="image/jpg"/>
</Annotations>
```

LANGUAGE: CAP CDS
CODE:
```cap
annotate STTA_PROD_MAN.STTA_C_MP_ProductType with {
  @Common.Text : '{Product}'
  @Core.IsURL : true
  @Core.MediaType : 'image/jpg'
  ProductPictureURL
};
```

STEP: 4 — Use binary media data (image content as binary) with MediaType

DESCRIPTION: If your service exposes binary media content (not a URL), annotate only the Media Content Type for the property in the local annotation or CAP CDS. Include Common.Text for alt text. Example uses image/png.

LANGUAGE: XML
CODE:
```xml
<Annotations Target="STTA_PROD_MAN.STTA_C_MP_ProductType/ProductPictureURL">
   <Annotation Term="Common.Text" String="{Product}" />
   <Annotation Term="Core.MediaType" String="image/png"/>
</Annotations>
```

LANGUAGE: CAP CDS
CODE:
```cap
annotate STTA_PROD_MAN.STTA_C_MP_ProductType with {
  @Common.Text : '{Product}'
  @Core.MediaType : 'image/png'
  ProductPictureURL
};
```

STEP: 5 — Notes and accessibility

DESCRIPTION: - Common.Text is optional but recommended to populate the alt attribute of sap.m.Image for screen readers. - Stream properties are supported for read-only scenarios only (media is read from the URL). - For more on stream properties in OData V4, consult: http://docs.oasis-open.org/odata/odata-json-format/v4.0/os/odata-json-format-v4.0-os.html#_Toc372793075

fiori-elements-framework annotations images OData-v4 CDS XML ABAP


**TITLE**: Display Text and ID for Value Help Input Fields (Edit & Display Modes)

**INTRODUCTION**: Configure object pages in SAP Fiori Elements to show both descriptive text and ID for value-help bound fields in Edit and Display modes. This guide provides actionable annotation samples (XML, ABAP CDS, CAP CDS) and behavior rules for OData V2 and V4 scenarios. Use these snippets directly in service metadata, annotation files, or CDS definitions.

**TAGS**: fiori-elements-framework, OData, value-help, textArrangement, SmartField, annotations, CDS, CAP, XML, ABAP

**STEP**: 1 — Edit Mode: Define textArrangement at Entity Level

**DESCRIPTION**: Apply a TextArrangement at the entity level so value help displays text and ID for bound fields. Field-level annotations override entity-level settings.

**LANGUAGE**: XML

**CODE**:
```xml
<Annotations Target="STTA_SALES_ORDER_ND_SRV_01.STTA_C_SO_SalesOrder_NDType">
     <Annotation Term="com.sap.vocabularies.UI.v1.TextArrangement" EnumMember="com.sap.vocabularies.UI.v1.TextArrangementType/TextLast"/>
 </Annotations>
```

**STEP**: 2 — Edit Mode: Define textArrangement at Entity Level (ABAP CDS)

**DESCRIPTION**: Equivalent entity-level configuration using ABAP CDS annotation.

**LANGUAGE**: ABAP CDS

**CODE**:
```
@UI.TextArrangement: #TEXT_LAST
annotate view STTA_C_SO_SALESORDER_ND with {

}
```

**STEP**: 3 — Edit Mode: Define textArrangement at Entity Level (CAP CDS)

**DESCRIPTION**: Equivalent entity-level configuration for CAP CDS services.

**LANGUAGE**: CAP CDS

**CODE**:
```
annotate STTA_SALES_ORDER_ND_SRV_01.STTA_C_SO_SalesOrder_NDType @(
  UI.TextArrangement : #TextLast
);
```

**STEP**: 4 — Edit Mode: Define textArrangement at Field Level (XML)

**DESCRIPTION**: Apply TextArrangement to a specific property. Field-level annotation takes precedence over entity-level.

**LANGUAGE**: XML

**CODE**:
```xml
 <Annotations Target="STTA_SALES_ORDER_ND_SRV_01.STTA_C_SO_SalesOrder_NDType/BusinessPartnerID">
       <Annotation Term="com.sap.vocabularies.UI.v1.TextArrangement" EnumMember="com.sap.vocabularies.UI.v1.TextArrangementType/TextOnly"/>
 </Annotations>
```

**STEP**: 5 — Edit Mode: Define textArrangement at Field Level (ABAP CDS)

**DESCRIPTION**: Example of field-level ABAP CDS annotation to force TextOnly for a property.

**LANGUAGE**: ABAP CDS

**CODE**:
```
annotate view STTA_C_SO_SALESORDER_ND with {
  @UI.TextArrangement: #TEXT_ONLY
  businesspartnerid;
}
```

**STEP**: 6 — Edit Mode: Define textArrangement at Field Level (CAP CDS)

**DESCRIPTION**: Field-level CAP CDS annotation example.

**LANGUAGE**: CAP CDS

**CODE**:
```
annotate STTA_SALES_ORDER_ND_SRV_01.STTA_C_SO_SalesOrder_NDType {
  @UI.TextArrangement : #TextOnly
  BusinessPartnerID
};
```

**STEP**: 7 — Client Validation Against Value Help (ValueListForValidation)

**DESCRIPTION**: Configure client-side validation against a ValueList. Use Common.ValueListForValidation at the property level. Note that ValueListForValidation only works with an empty qualifier (String="") and user input not matching the list is not stored in backend drafts.

**LANGUAGE**: XML

**CODE**:
```xml
<Annotations Target="STTA_PROD_MAN.STTA_C_MP_ProductType/Supplier" xmlns="http://docs.oasis-open.org/odata/ns/edm">
	<Annotation Term="Common.ValueListForValidation" String=""/>
	<Annotation Term="Common.ValueList">
		...Definition of ValueList...
	</Annotation>
</Annotations>
```

**STEP**: 8 — OData V2 — Edit Mode: Default and Conditions for TextInEditModeSource

**DESCRIPTION**: By default object page forms allow entering values not in value help using TextInEditModeSource = ValueListNoValidation. The sap.ui.comp.smartfield.TextInEditModeSource.ValueList behavior is supported only when all of the following hold:
- SmartField value property is bound to EDM property type Edm.String or Edm.Guid.
- com.sap.vocabularies.UI.v1.TextArrangement is specified for the bound EDM property or entity.
- SmartField value binding is two-way.
- The description field used is filterable.
If any condition fails, only the ID is shown.

**LANGUAGE**: Configuration

**CODE**:
```
TextInEditModeSource = ValueListNoValidation
```

**STEP**: 9 — OData V2 — Display Mode: Use sap:text to fetch description via navigation path

**DESCRIPTION**: To display text + ID in Display mode, model sap:text on the property to point to the navigation property description (navigation path). Also specify TextArrangement on the entity.

**LANGUAGE**: XML

**CODE**:
```
   <Property Name="BusinessPartnerID" Type="Edm.String" Nullable="false" MaxLength="10" sap:display-format="UpperCase" sap:text="to_BusinessPartner/CompanyName" sap:label="Business Partner ID" sap:value-list="standard">

<Annotations Target="STTA_SALES_ORDER_ND_SRV_01.STTA_C_SO_SalesOrder_NDType">
         <Annotation Term="com.sap.vocabularies.UI.v1.TextArrangement" EnumMember="com.sap.vocabularies.UI.v1.TextArrangementType/TextLast"/>
 </Annotations>
```

**STEP**: 10 — OData V2 — Display Mode: Value Help Entity Modeling with sap:text property

**DESCRIPTION**: Alternative: model the value-help entity so the ID property includes sap:text pointing to a text property (CostCenter_Text). Add TextArrangement annotation on the value-help entity type.

**LANGUAGE**: XML

**CODE**:
```
<EntityType Name="C_CostCenterVHType" sap:label="Cost Center Value Help" sap:value-list="true"
                sap:content-version="1">
                <Key>
                    <PropertyRef Name="CostCenter" />
                </Key>
                <Property Name="CostCenter" Type="Edm.String" Nullable="false" MaxLength="10"
                    sap:display-format="UpperCase" sap:text="CostCenter_Text" sap:label="Cost Center" />
                <Property Name="CostCenter_Text" Type="Edm.String" MaxLength="20" sap:label="Cost Center Name"
                    sap:creatable="false" sap:updatable="false" />
</EntityType>

<Annotations Target="COST_CENTERS_SRV.C_CostCenterVHType"
                xmlns="http://docs.oasis-open.org/odata/ns/edm">
     <Annotation Term="com.sap.vocabularies.UI.v1.TextArrangement"
                    EnumMember="com.sap.vocabularies.UI.v1.TextArrangementType/TextLast" />
</Annotations>
```

**STEP**: 11 — OData V2 — Default UI Behavior Rules and Exceptions

**DESCRIPTION**: Rules and exceptions to apply when controlling text+ID display:
- DataField rendered as SmartLink (SemanticObject) or quick view: shows descriptive text + ID by default.
- DataFieldWithNavigationPath bound to value help: shows descriptive text + ID by default.
- Applies to tables, object page headers, and object page forms.
- Change ordering using TextArrangement values: TextFirst, TextLast, TextOnly.
- Unsupported record types for this behavior: DataFieldWithIntentBasedNavigation, Communication.Contact.
- If TextArrangement is defined as textSeparate, only the ID is displayed.

**LANGUAGE**: Notes

**CODE**:
```
Supported record types: DataField (SmartLink/QuickView), DataFieldWithNavigationPath.
Unsupported: DataFieldWithIntentBasedNavigation, Communication.Contact.
TextArrangement options: TextFirst, TextLast, TextOnly, textSeparate (ID only).
```

**STEP**: 12 — OData V4 — Display Mode Behavior

**DESCRIPTION**: For OData V4, the same default applies: DataField rendered as link via SemanticObject or quick view and DataFieldWithNavigationPath bound to value help show descriptive text + ID by default across tables, object page headers, and object page forms. Control ordering via TextArrangement (TextFirst, TextLast, TextOnly). See "Further Features of the Field" for additional configuration options.

**LANGUAGE**: Notes

**CODE**:
```
OData V4: Default behavior mirrors V2 for DataField and DataFieldWithNavigationPath.
Use UI.TextArrangement to change display order.
Reference: further-features-of-the-field-f49a0f7.md
```

fiori-elements-framework OData value-help textArrangement SmartField annotations CDS CAP XML ABAP


**TITLE**: Donut Chart Card

**INTRODUCTION**: How to configure and use a Donut Chart Card in Fiori Elements. Covers data-model constraints, rendering percentages, enabling stable coloring with a color map, required chart annotations, and handling the "Others" sector navigation filter.

**TAGS**: fiori-elements-framework, donut-chart, chart, sap, colorPalette, stable-colors, annotation, OData, card-settings

**STEP**: 1 — Data model requirements

**DESCRIPTION**: Donut charts require exactly one measure and one or more dimensions. If multiple dimensions are provided they are stacked: each unique combination of dimension values becomes one colored section. Optionally disable navigation from the chart if you don't want drill-through.

**LANGUAGE**: JSON

**CODE**:
```json
{
  "requirements": {
    "measures": "exactly 1",
    "dimensions": "one or more (stacked: combinations become sections)",
    "navigation": "optional (can be disabled in card settings)"
  }
}
```

**STEP**: 2 — Show values as percentages in the chart

**DESCRIPTION**: To render data labels as percentages in the donut chart, set the ChartProperties -> plotArea -> dataLabel type to "percentage". Keep this snippet exactly as-is in your chart properties block.

**LANGUAGE**: JSON

**CODE**:
```json
"ChartProperties" : {
			"plotArea" : {
				dataLabel: {
					"type" : "percentage"
					}
				}
			}
```

**STEP**: 3 — Enable stable coloring (assign fixed colors to specific dimension values)

**DESCRIPTION**: Stable coloring requires:
- a color map in the descriptor configuration (colorPalette) that maps dimension values to colors,
- enabling bEnableStableColors in the card settings,
- the chart dimension Role must be Category,
- the dimension property must have com.sap.vocabularies.Common.v1.Text defined for readable legend labels.

Follow the examples below for each configuration piece.

**LANGUAGE**: JSON

**CODE**:
```json
// Example: descriptor configuration – colorPalette maps dimension property values to colors
{
  "descriptor": {
    "configuration": {
      "colorPalette": {
        "Country": {
          "Germany": "#0a6ed1",
          "USA": "#e26a1a",
          "India": "#8bc34a",
          "Others": "#9e9e9e"
        }
      }
    }
  }
}
```

**STEP**: 3.1 — Turn on stable coloring in the card settings

**DESCRIPTION**: Set bEnableStableColors to true in the card settings (sap.card or your card settings location).

**LANGUAGE**: JSON

**CODE**:
```json
{
  "sap.card": {
    "type": "List" ,
    "settings": {
      "bEnableStableColors": true
    }
  }
}
```

**STEP**: 3.2 — Chart annotation: set dimension Role to Category

**DESCRIPTION**: Ensure the chart annotation defines the dimension Role as "Category". This example shows the typical annotation Record used to declare a dimension with Role equal to Category.

**LANGUAGE**: XML

**CODE**:
```xml
<PropertyValue Property="Dimensions">
  <Collection>
    <Record Type="UI.ChartDimension">
      <PropertyValue Property="PropertyPath" String="Country" />
      <PropertyValue Property="Role" String="Category" />
    </Record>
  </Collection>
</PropertyValue>
```

**STEP**: 3.3 — Define com.sap.vocabularies.Common.v1.Text annotation for the dimension property

**DESCRIPTION**: Add com.sap.vocabularies.Common.v1.Text annotation on the dimension property inside the entity type so legend labels are rendered properly.

**LANGUAGE**: XML

**CODE**:
```xml
<Property Name="Country" Type="Edm.String">
  <Annotation Term="com.sap.vocabularies.Common.v1.Text">
    <String>Country</String>
  </Annotation>
</Property>
```

**STEP**: 4 — Others sector: navigation filter behavior

**DESCRIPTION**: The "Others" section lets you navigate to a target application with a filter that excludes the explicitly shown dimension values (A, B, C). Compose the navigation filter so the target receives a "not in (A, B, C)" condition.

**LANGUAGE**: OData / Query

**CODE**:
```
// Example OData $filter representing "not in (A,B,C)"
$filter=not (Dimension eq 'A' or Dimension eq 'B' or Dimension eq 'C')
```

Donut Chart Card

fiori-elements-framework donut-chart chart sap colorPalette stable-colors annotation OData card-settings


**TITLE**: Draft Handling — Configurations and Integration Guide for SAP Fiori Elements

**INTRODUCTION**: Practical, code-focused reference for implementing and configuring draft handling in SAP Fiori elements (OData V2 and V4). Includes manifest.json samples and actionable notes for behavior (Apply, Save, Discard, PreparationAction, side effects, collaborative drafts, and hiding draft UI). Use these snippets directly in your app manifest and controller-extension workflows.

**TAGS**: draft, manifest.json, sap.fe, OData V2, OData V4, DraftRoot, PreparationAction, DiscardAction, hideDraft, dataSaveFrequency, collaborative draft, editFlow

STEP: 1 — Draft behavior summary and key terms

DESCRIPTION: Concise, actionable summary of core runtime behavior and terms to use when writing code or configuring services and annotations.
LANGUAGE: Text
CODE:
```
# Core draft handling behavior (for quick reference)
- Draft created automatically when user starts Create or Edit (background).
- Apply (subobject footer): applies UI changes to the draft and navigates one step up.
- Save: persists draft changes to the active entity.
- DiscardAction: if defined in DraftRoot annotation, call DiscardAction to delete a draft; otherwise the Delete OData call is used.
- PreparationAction: backend validation action available on DraftRoot; triggered on Enter or explicit Validate.
- TriggerAction: a global side-effect action annotation that can replace PreparationAction when annotated in global side effects.
- Side effects: may trigger automatic saves, validation, and additional backend calls.
- Validation errors: technical inconsistencies (e.g., wrong data type, overflow) block saving and prompt users to fix errors before Save or Apply.
```

STEP: 2 — Configure immediate draft save frequency (OData V2 special case)

DESCRIPTION: Change automatic draft merge/save timing from the default delayed behavior to immediate saves. Place this in your application manifest.json under "sap.ui.generic.app" -> "settings" -> "draftSettings".
LANGUAGE: JSON
CODE:
```json
"sap.ui.generic.app": {
    "settings": {
        "draftSettings": {
            "dataSaveFrequency": "immediate"
        }
    }
}
```

STEP: 3 — Hide draft-related UI elements while keeping draft functionality (global hideDraft)

DESCRIPTION: Hide draft UI affordances (filters, Apply button, Draft updated footer message) while keeping draft handling active in the background. Use "sap.fe.app.hideDraft" settings in manifest.json. Examples show basic hiding, keeping user on current page after Save/Cancel, and hiding Create Next button.
LANGUAGE: JSON
CODE:
```json
// Basic enable hideDraft
"sap.fe": {
  "app": {
    "hideDraft": {
      "enabled": true
    }
  }
}

// Keep user on same object page after Save or Cancel
"sap.fe": {
  "app": {
    "hideDraft": {
      "enabled": true,
      "stayOnCurrentPageAfterSave": true,
      "stayOnCurrentPageAfterCancel": true
    }
  }
}

// Hide the Create Next button when hideDraft is enabled
"sap.fe": {
  "app": {
    "hideDraft": {
      "enabled": true,
      "hideCreateNext": true
    }
  }
}
```

STEP: 4 — Handling DiscardAction vs Delete (annotation behavior)

DESCRIPTION: Ensure correct annotation placement on the DraftRoot entity. If DraftRoot has a DiscardAction annotation, the framework calls that action to delete/discard the draft; otherwise the framework calls the standard Delete operation. Use this when implementing custom discard logic in the backend or when annotating service metadata.
LANGUAGE: Text
CODE:
```
// Implementation note (no strict code sample provided in original):
// - Annotate DraftRoot with DiscardAction to route the discard behavior to a custom backend action.
// - If DiscardAction is absent, framework triggers the Delete call for the draft entity.
// - Ensure your service metadata (annotations) expose DiscardAction on the DraftRoot entity.
```

STEP: 5 — Triggering PreparationAction and global side effects (Enter key behavior)

DESCRIPTION: PreparationAction on DraftRoot validates draft values backend-side and returns messages. On Enter:
- OData V2: PreparationAction is triggered by default; saved pending changes are sent first.
- TriggerAction in global side effects replaces PreparationAction if configured (except for side effects that use SourceProperties where PreparationAction remains).
- Side effects annotated for a field may cause immediate draft save when leaving a virtual field group.
LANGUAGE: Text
CODE:
```
// Behavior summary for implementation:
- Define PreparationAction on the DraftRoot entity to enable server-side draft validation.
- Define global side effects (TriggerAction) if you want Enter to execute different backend logic.
- If side effects reference SourceProperties with TriggerAction, PreparationAction is not suppressed.
- Ensure UI-side pending changes are saved before issuing PreparationAction.
```

STEP: 6 — OData V2 automatic background save timing and immediate actions

DESCRIPTION: OData V2 drafts auto-save every 20 seconds by default while editing. Immediate save occurs when:
- The user executes an action.
- A field with a side effect is modified and the user moves out of the side effect’s virtual field group.
Use Step 2 to change behavior to immediate saves globally.
LANGUAGE: Text
CODE:
```
// OData V2 default behavior:
- Auto-save interval: 20 seconds for pending changes in edit mode.
- Immediate save triggers:
  * Action executions
  * Leaving a virtual field group containing a field annotated with a side effect
// Use manifest.dataSaveFrequency to force immediate saves if required (see Step 2).
```

STEP: 7 — OData V4 specific draft features and collaborative drafts

DESCRIPTION: For OData V4:
- Two draft modes: exclusive (single user) and collaborative (shared draft).
- Collaborative draft requires ShareAction annotation on the service and uses WebSocket for synchronization.
- Field-level locks and live updates are supported (avatars, lock indicators).
- Restrictions: collaborative draft supported only with ABAP RAP; mass edit not supported on object pages when collaborative draft is enabled. For freestyle extensions, use sap.fe.macros.CollaborativeDraftHandler API.
LANGUAGE: Text
CODE:
```
// Collaborative draft implementation notes:
- Ensure service supports ShareAction annotation on DraftRoot to enable collaborative draft.
- When collaborative draft is enabled:
  * All drafts are shared automatically with users who have draft access.
  * Field-level locks appear when a user focuses/edits a field.
  * Updates are broadcast via WebSocket; this extends browser session until users leave.
- Restrictions:
  * Supported only with ABAP RAP services.
  * For freestyle app extensions, integrate sap.fe.macros.CollaborativeDraftHandler API.
  * Mass edit on object pages is not supported with collaborative draft.
```

STEP: 8 — Filtering draft-related data (OData V4)

DESCRIPTION: Draft-related filters are available by default in OData V4: Draft Created By/On and Draft Last Changed By/On. Time filters use semantic operators showing past values. This feature is not available with CAP services.
LANGUAGE: Text
CODE:
```
// Filtering draft metadata (OData V4):
- Available filters (default): "Draft Created By", "Draft Created On", "Draft Last Changed By", "Draft Last Changed On"
- Time filters use semantic operators (e.g., past ranges).
- Note: CAP services do not support this feature by default.
```

STEP: 9 — editFlow API (controller extension entry points for custom draft logic)

DESCRIPTION: Use the editFlow controller-extension API to add custom logic for standard draft lifecycle actions (create, edit, save, discard) or to implement draft handling on custom pages. The API is sap.fe.core.controllerextensions.EditFlow. Consult the API reference and examples in the SAP Fiori dev portal.
LANGUAGE: Text
CODE:
```
// Integration pointers:
- API: sap.fe.core.controllerextensions.EditFlow
- Use editFlow to:
  * Add custom logic before/after draft actions (create, edit, save, discard)
  * Implement draft handling in custom pages and custom controls
- Reference / live examples:
  * EditFlow examples: https://ui5.sap.com/test-resources/sap/fe/core/fpmExplorer/index.html#/controllerExtensions/editFlow
  * API Reference: https://ui5.sap.com/#/api/sap.fe.core.controllerextensions.EditFlow
```

STEP: 10 — Useful references (links to docs and design guidance)

DESCRIPTION: Keep these references handy when implementing or debugging draft handling.
LANGUAGE: Text
CODE:
```
- Draft design guidance: https://experience.sap.com/fiori-design-web/draft-handling/
- SAP ABAP docs: https://help.sap.com/docs/SAP_NETWEAVER_AS_ABAP_752/cc0c305d2fab47bd808adcad3ca7ee9d/d36820f082c84085b6634be4576e351a.html
- Confirmation Popups: confirmation-popups-9a53662.md
- Using Global Side Effects: using-global-side-effects-955ae31.md
- Toggling Between Draft and Saved Values: toggling-between-draft-and-saved-values-fd3950a.md
- Draft Validation live example: https://ui5.sap.com/test-resources/sap/fe/core/fpmExplorer/index.html#/advancedFeatures/guidance/draftValidation
```

draft
manifest.json
sap.fe
OData V2
OData V4
DraftRoot
PreparationAction
DiscardAction
hideDraft
dataSaveFrequency
collaborative draft
editFlow


**TITLE**: Dual Combination Chart Card (UI.Chart Annotation)

**INTRODUCTION**: Use this UI.Chart OData annotation to define a Dual Combination Chart card for Fiori Elements. The chart displays two value axes (columns + lines) so you can combine multiple measures (one axis as columns, the other as lines). Apply this annotation in your service metadata extensions or local annotation files to render the chart in Fiori Elements cards.

**TAGS**: fiori-elements-framework, UI.Chart, DualCombination, chart, annotation, OData, SAPUI5

STEP: 1 — Add UI.Chart annotation for Dual Combination Chart

DESCRIPTION: Insert a UI.Chart annotation that specifies a CombinationDual chart. Define the Title, ChartType, Measures, Dimensions, MeasureAttributes (assigning measures to Axis1/Axis2), and DimensionAttributes (assigning Category role). Place this Record in your OData metadata extension file or local annotation file that Fiori Elements reads (e.g., annotations.xml, annotations.cds, or metadata extension).

LANGUAGE: XML

CODE:
```xml
<Annotation Term="UI.Chart" Qualifier="Eval_by_CtryCurr_Dual_Combo">
    <Record Type="UI.ChartDefinitionType">
        <PropertyValue Property="Title" String="Dual Combination Chart" />
        <PropertyValue Property="ChartType" EnumMember="UI.ChartType/CombinationDual"/>
        <PropertyValue Property="Measures">
            <Collection>
                <PropertyPath>Sales</PropertyPath>
                <PropertyPath>SalesShare</PropertyPath>
                <PropertyPath>TotalSales</PropertyPath>
            </Collection>
        </PropertyValue>
        <PropertyValue Property="Dimensions">
            <Collection>
                <PropertyPath>Product</PropertyPath>
                <PropertyPath>Quarter</PropertyPath>
            </Collection>
        </PropertyValue>
        <PropertyValue Property="MeasureAttributes">
            <Collection>
                <Record Type="UI.ChartMeasureAttributeType">
                    <PropertyValue Property="Measure" PropertyPath="Sales"/>
                    <PropertyValue Property="Role"
                        EnumMember="UI.ChartMeasureRoleType/Axis1"/>
                </Record>
                <Record Type="UI.ChartMeasureAttributeType">
                    <PropertyValue Property="Measure" PropertyPath="TotalSales" />
                    <PropertyValue Property="Role" EnumMember="UI.ChartMeasureRoleType/Axis1"/>
                </Record>
                <Record Type="UI.ChartMeasureAttributeType">
                    <PropertyValue Property="Measure" PropertyPath="SalesShare" />
                    <PropertyValue Property="Role" EnumMember="UI.ChartMeasureRoleType/Axis2"/>
                </Record>
            </Collection>
        </PropertyValue>
        <PropertyValue Property="DimensionAttributes">
            <Collection>
                <Record Type="UI.ChartDimensionAttributeType">
                    <PropertyValue Property="Dimension" PropertyPath="Product" />
                    <PropertyValue Property="Role" EnumMember="UI.ChartDimensionRoleType/Category"/>
                </Record>
            </Collection>
        </PropertyValue>
    </Record>
</Annotation>
```

STEP: 2 — Implementation rules and recommendations

DESCRIPTION: Follow these concrete rules when authoring the annotation so the Dual Combination Chart renders correctly:
- Use ChartType = UI.ChartType/CombinationDual to enable two axes.
- Configure at least two measures. All measures must be listed under Measures and then assigned to an axis via MeasureAttributes.
- Assign measures to the feed's UID value axis (use Axis1 for primary axis and Axis2 for secondary axis).
- The first measure will render as a column; subsequent measures can render as lines—define roles accordingly.
- Assign at least one role to the category axis via DimensionAttributes. Any dimension given the Role = UI.ChartDimensionRoleType/Category is used as the category axis; Category is the default role.
- Prefer one time-based dimension for the category axis (e.g., Quarter) to get proper time-series behavior.
- Place this annotation in the metadata extension file or local annotation file referenced by your Fiori Elements application so it is consumed at runtime.

LANGUAGE: JSON (example of recommended placement metadata — conceptual)
CODE:
```json
{
  "notes": "Place the above UI.Chart XML Record in your OData annotations file (annotations.xml or metadata extension). Ensure the annotation file is registered in the manifest or service metadata."
}
```

STEP: 3 — Validation checklist before deployment

DESCRIPTION: Validate these items programmatically or manually before deploying:
- Measures exist in the entity type (Sales, SalesShare, TotalSales).
- Dimensions exist (Product, Quarter) and Quarter is time-aware if used as time axis.
- The annotation Qualifier (Eval_by_CtryCurr_Dual_Combo) does not conflict with other chart annotations or is referenced where needed.
- The annotation file is reachable by the Fiori Elements app (manifest.json annotation configuration).

LANGUAGE: JSON (checklist example)
CODE:
```json
{
  "validation": [
    "Measures defined in EntityType: Sales, SalesShare, TotalSales",
    "Dimensions defined in EntityType: Product, Quarter",
    "Annotation Qualifier is unique: Eval_by_CtryCurr_Dual_Combo",
    "Annotation file referenced in manifest or metadata extension"
  ]
}
```

fiori-elements-framework UI.Chart DualCombination chart annotation OData SAPUI5