**TITLE**: Value Help Annotations for fiori-elements Framework

**INTRODUCTION**: Concise reference for implementing value help (value list and mapping) and client-side validation in fiori-elements apps. Includes XML, CAP CDS, and ABAP CDS examples for: Common.ValueList, Common.ValueListMapping, Common.ValueListReference, Common.ValueListForValidation, Common.ValueListRelevantQualifiers, and InitialValueIsSignificant. Use these snippets as drop-in annotation definitions in service metadata (XML) or CDS files.

**TAGS**: value-help, annotations, Common.ValueList, Common.ValueListMapping, ValueListForValidation, ValueListReference, InitialValueIsSignificant, CAP, ABAP, XML, fiori-elements

STEP: 1 - ValueList annotation (entity defined in main metadata, CAP apps)
DESCRIPTION: Use Common.ValueList when the value help entity is present in the same service metadata (typical for CAP model). Apply this annotation on the target property to provide CollectionPath, Label, SearchSupported, FetchValues, and Parameters mappings (IN/OUT/DisplayOnly/Constant). Place XML in the service metadata file or use CAP CDS annotate syntax in CDS files.
LANGUAGE: XML
CODE:
```XML
<Annotations Target="MyService.Travel/AgencyId">
    <Annotation Term="Common.ValueList">
        <Record>
            <PropertyValue Property="CollectionPath" String="TravelAgency" />
            <PropertyValue Property="Label" String="Travel Agency" />
            <PropertyValue Property="SearchSupported" Bool="true" />
            <PropertyValue Property="FetchValues" Int="2" />
            <PropertyValue Property="Parameters">
                <Collection>
                    <Record Type="Common.ValueListParameterInOut">
                        <PropertyValue Property="LocalDataProperty" PropertyPath="AgencyId" />
                        <PropertyValue Property="ValueListProperty" String="Agency_Id" />
                        <PropertyValue Property="Importance" EnumMember="Common.ImportanceType/High" />
                    </Record>
                    <Record Type="Common.ValueListParameterInOut">
                        <PropertyValue Property="LocalDataProperty" PropertyPath="_TourOperator/RegionId" />
                        <PropertyValue Property="ValueListProperty" String="Region_Id" />
                        <PropertyValue Property="InitialValueIsSignificant" Bool="true" />
                    </Record>
                    <Record Type="Common.ValueListParameterDisplayOnly">
                        <PropertyValue Property="ValueListProperty" String="AgencyName" />
                        <PropertyValue Property="Importance" EnumMember="Common.ImportanceType/High" />
                    </Record>
                    <Record Type="Common.ValueListParameterOut">
                        <PropertyValue Property="LocalDataProperty" PropertyPath="CountryIndicator" />
                        <PropertyValue Property="ValueListProperty" String="Country_Flag" />
                    </Record>
                    <Record Type="Common.ValueListParameterConstant">
                        <PropertyValue Property="Constant" String="001" />
                        <PropertyValue Property="ValueListProperty" String="PredefinedField" />
                    </Record>
                </Collection>
            </PropertyValue>
        </Record>
    </Annotation>
</Annotations>
```

LANGUAGE: CAP CDS
CODE:
```CAP CDS
annotate MyService.Travel with
{
    AgencyId @Common.ValueList: {
        CollectionPath : 'TravelAgency',
        Label          : 'Travel Agency',
        SearchSupported,
        FetchValues    : 2,
        Parameters     : [
            {
                $Type             : 'Common.ValueListParameterInOut',
                LocalDataProperty : AgencyId,
                ValueListProperty : 'Agency_Id',
                ![@UI.Importance] : #High,
            },
            {
                $Type                    : 'Common.ValueListParameterInOut',
                LocalDataProperty        : to_TourOperator.RegionId,
                ValueListProperty        : 'Region_Id',
                InitialValueIsSignificant
            },
            {
                $Type             : 'Common.ValueListParameterDisplayOnly',
                ValueListProperty : 'AgencyName',
                ![@UI.Importance] : #High,
            },
            {
                $Type             : 'Common.ValueListParameterOut',
                LocalDataProperty : CountryIndicator,
                ValueListProperty : 'Country_Flag'
            }
            {
                $Type            : 'Common.ValueListParameterConstant',
                Constant: '001',
                ValueListProperty: 'PredefinedField'
            }
        ]
    };
};
```

STEP: 2 - ValueListMapping annotation (external value help metadata, RAP/RESTful ABAP)
DESCRIPTION: Use Common.ValueListMapping when the value help entity metadata is external to the main service (RAP model). Behavior and parameters mirror Common.ValueList. Apply in local XML metadata that references external service metadata.
LANGUAGE: XML
CODE:
```XML
<Annotations Target="MyService.Travel/AgencyId">
    <Annotation Term="Common.ValueListMapping">
        <Record>
            <PropertyValue Property="CollectionPath" String="TravelAgency" />
            <PropertyValue Property="Label" String="Travel Agency" />
            <PropertyValue Property="SearchSupported" Bool="true" />
            <PropertyValue Property="FetchValues" Int="2" />
            <PropertyValue Property="Parameters">
                <Collection>
                    <Record Type="Common.ValueListParameterInOut">
                        <PropertyValue Property="LocalDataProperty" PropertyPath="AgencyId" />
                        <PropertyValue Property="ValueListProperty" String="Agency_Id" />
                        <PropertyValue Property="Importance" EnumMember="Common.ImportanceType/High" />
                    </Record>
                    <Record Type="Common.ValueListParameterInOut">
                        <PropertyValue Property="LocalDataProperty" PropertyPath="_TourOperator/RegionId" />
                        <PropertyValue Property="ValueListProperty" String="Region_Id" />
                        <PropertyValue Property="InitialValueIsSignificant" Bool="true" />
                    </Record>
                    <Record Type="Common.ValueListParameterDisplayOnly">
                        <PropertyValue Property="ValueListProperty" String="AgencyName" />
                        <PropertyValue Property="Importance" EnumMember="Common.ImportanceType/High" />
                    </Record>
                    <Record Type="Common.ValueListParameterOut">
                        <PropertyValue Property="LocalDataProperty" PropertyPath="CountryIndicator" />
                        <PropertyValue Property="ValueListProperty" String="Country_Flag" />
                    </Record>
                    <Record Type="Common.ValueListParameterConstant">
                        <PropertyValue Property="Constant" String="001" />
                        <PropertyValue Property="ValueListProperty" String="PredefinedField" />
                    </Record>
                </Collection>
            </PropertyValue>
        </Record>
    </Annotation>
</Annotations>
```

STEP: 3 - ValueListReference (referencing external metadata path)
DESCRIPTION: When using Common.ValueListMapping, reference the external service metadata via Common.ValueListReferences on the same target. The string is the path relative to the main metadata file that contains the reference.
LANGUAGE: XML
CODE:
```XML
<Annotations Target="Self.TravelType/AgencyId">
  <Annotation Term="Common.ValueListReferences">
    <Collection>
      <String>../../../../srvd_f4/sap/myentityname/0001;ps='srvd-sadl_gw_apptravel_definition-0001';va='com.sap.gateway.srvd.sadl_gw_apptravel_definition.v0001.et-c_mdbu_v4_travel.agencyid'/$metadata</String>
    </Collection>
  </Annotation>
</Annotations>
```

STEP: 4 - Common ValueList properties (quick reference)
DESCRIPTION: Use these properties when defining Common.ValueList or Common.ValueListMapping.
- Label: dialog title (used by value help dialog).
- CollectionPath: entity set used as value help data source.
- SearchSupported: show/hide search bar in the value help dialog.
- Parameters: define IN, OUT, INOUT mappings and display-only or constant fields (control how value help interacts with local fields).
- FetchValues: controls data loading in value help table:
  - 1 = load immediately when dialog opens (default).
  - 2 = load after user applies filters.
- Importance: marks fields for type-ahead suggestion.

STEP: 5 - Note: default behavior and drafts
DESCRIPTION: Implementation notes to include in metadata:
- Value help for draft-enabled entities shows only active documents.
- Value help appears in filter fields even if Common.ValueList or Common.ValueListMapping are not defined; in that case only the "Define Conditions" tab is shown.

STEP: 6 - Client validation using ValueListForValidation (hard-coded mapping)
DESCRIPTION: Configure client-side validation against a value help by adding Common.ValueListForValidation on the target property. To validate against the default (unqualified) ValueList use an empty string (""). To validate against a qualified value list supply qualifier string.
LANGUAGE: XML
CODE:
```XML
<Annotations Target="serviceNamespace.BookingType/FlightDate">
    …….
    <Annotation Term="Common.ValueListForValidation" String=""/>
    <Annotation Term="Common.ValueList">
        ...Definition of ValueList...
    </Annotation>
</Annotations>
```

LANGUAGE: ABAP CDS
CODE:
```ABAP CDS
annotate schema.Booking {
  @Common.ValueListForValidation : ''
  @Common.ValueList : {
      $Type : 'Common.ValueListType',
      CollectionPath : 'Flight',
  }
  FlightDate;
}
```

LANGUAGE: CAP CDS
CODE:
```CAP CDS
annotate schema.Booking {
  @Common.ValueListForValidation : ''
  @Common.ValueList : {
      $Type : 'Common.ValueListType',
      CollectionPath : 'Flight',
  }
  FlightDate;
}
```

STEP: 7 - Client validation using conditional settings (runtime qualifier selection)
DESCRIPTION: Use a conditional expression in Common.ValueListForValidation to return a qualifier at runtime. The expression must evaluate to a single valid ValueList or ValueListMapping qualifier (or empty string). Place the conditional expression in XML or CDS as shown.
LANGUAGE: XML
CODE:
```XML
<Annotations Target="com.c_salesordermanage_sd.HeaderPartner/BusinessPartner">
    <Annotation Term="com.sap.vocabularies.Common.v1.ValueListForValidation">
        <If>
            <Eq>
                <Path>PartnerFunction</Path>
                <String>WE</String>
            </Eq>
            <String>BusinessPartnerQualifier</String>
            <String />
        </If>
    </Annotation>
</Annotations>
```

LANGUAGE: CAP CDS
CODE:
```CAP CDS
annotate schema.HeaderPartner {
  @Common.ValueListForValidation: {$edmJson: {$If: [
    {$Eq: [
      {$Path: 'PartnerFunction'},
      'WE'
    ]},
    'BusinessPartnerQualifier',
    ''
  ]}}
  BusinessPartner;
}

OR

annotate schema.HeaderPartner with {
   @Common.ValueListForValidation :
    (PartnerFunction = 'WE' ? 'BusinessPartnerQualifier' : '')
   BusinessPartner;
};
```

STEP: 8 - Context-dependent value help (ValueListRelevantQualifiers)
DESCRIPTION: Use Common.ValueListRelevantQualifiers to choose valid qualifiers based on another property value. Provide a collection of qualifier strings and conditional If elements. Define both the unqualified Common.ValueList and any qualified Common.ValueList#Qualifier entries.
LANGUAGE: XML
CODE:
```XML
<Annotations Target="com.c_salesordermanage_sd.HeaderPartner/BusinessPartner">
    <Annotation Term="com.sap.vocabularies.Common.v1.ValueListRelevantQualifiers">
        <Collection>
            <String/>
            <If>
                <Eq>
                    <Path>PartnerFunction</Path>
                    <String>WE</String>
                </Eq>
                <String>BusinessPartnerQualifier</String>
            </If>
        </Collection>
    </Annotation>
    <Annotation Term="Common.ValueList" Qualifier="BusinessPartnerQualifier">
        ...Definition of ValueList...
    </Annotation>
    <Annotation Term="Common.ValueList">
        ...Definition of ValueList w/o qualifier...
    </Annotation>
</Annotations>
```

LANGUAGE: CAP CDS
CODE:
```CAP CDS
annotate schema.HeaderPartner with {
  @Common.ValueListRelevantQualifiers:
    (PartnerFunction = 'WE' ? 'BusinessPartnerQualifier' : '')
  @Common.ValueList: {
    $Type: 'Common.ValueListType',
    . . .
  }
  @Common.ValueList#BusinessPartnerQualifier: {
    $Type: 'Common.ValueListType',
    . . .
  }
  BusinessPartner;
};
```

STEP: 9 - InitialValueIsSignificant (treat empty/null as significant IN filter)
DESCRIPTION: Use InitialValueIsSignificant on an IN parameter (Edm.String only) to treat initial empty values as a meaningful filter value. Restriction: supported only on object page and only for Edm.String parameters. This causes value help to filter for records where the corresponding value help property is "" or null (if nullable).
LANGUAGE: XML
CODE:
```XML
<Annotations Target="com.c_salesordermanage_sd.SalesOrderManage/ShippingCondition">
    <Annotation Term="Common.ValueList">
        <Record Type="Common.ValueListType">
            <PropertyValue Property="CollectionPath" String="ShippingCondition"/>
            <PropertyValue Property="Label" String="Shipping Condition"/>
            <PropertyValue Property="Parameters">
                <Collection>
                    <Record Type="Common.ValueListParameterInOut">
                        <PropertyValue Property="LocalDataProperty" PropertyPath="ShippingCondition"/>
                        <PropertyValue Property="ValueListProperty" String="ShippingCondition"/>
                    </Record>
                    <Record Type="Common.ValueListParameterIn">
                        <PropertyValue Property="LocalDataProperty" PropertyPath="SoldToParty"/>
                        <PropertyValue Property="ValueListProperty" String="SoldToParty"/>
                        <PropertyValue Property="InitialValueIsSignificant" Bool="true"/>
                    </Record>
                    <Record Type="Common.ValueListParameterDisplayOnly">
                        <PropertyValue Property="ValueListProperty" String="ShippingCondition_Text"/>
                    </Record>
                </Collection>
            </PropertyValue>
        </Record>
    </Annotation>
</Annotations>
```

LANGUAGE: CAP CDS
CODE:
```CAP CDS
Context-dependent value help doesn't support individual In/Out parameters for the different ShippingCondition

    ValueList       : {
        Label          : 'Shipping Condition',
        CollectionPath : 'ShippingCondition',
        Parameters     : [
        {
            $Type             : 'Common.ValueListParameterInOut',
            LocalDataProperty : ShippingCondition,
            ValueListProperty : 'ShippingCondition'
        },
        {
            $Type             : 'Common.ValueListParameterIn',
            LocalDataProperty : SoldToParty,
            ValueListProperty : 'SoldToParty',
            InitialValueIsSignificant: true
        },
        {
            $Type             : 'Common.ValueListParameterDisplayOnly',
            ValueListProperty : 'ShippingCondition_Text'
        }
        ]
    }
});
```

STEP: 10 - Restrictions and final notes
DESCRIPTION: Implementation constraints and behaviors to enforce in code:
- InitialValueIsSignificant: only on object page; only Edm.String parameters.
- Parameterized value help service is not supported.
- If ValueListForValidation is not specified for filter fields, the default (unqualified) ValueList is used for validation.
- Value help for draft-enabled entities shows only active documents.
- If Common.ValueList or Common.ValueListMapping is absent for filter fields, the Define Conditions tab is shown (no selection list).

value-help annotations Common.ValueList Common.ValueListMapping ValueListForValidation ValueListReference InitialValueIsSignificant CAP ABAP XML fiori-elements


**TITLE**: Vertical Bullet Chart Card (Fiori Elements / OVP)

**INTRODUCTION**: Use a Vertical Bullet Chart Card to display one or more measures against a dimension — typically to compare actual values (columns) to a target (line). This card requires at least one dimension and one measure. Configure dimension(s) with the axis category and measures with roles axis1 (actual) and axis2 (target).

**TAGS**: fiori-elements-framework, OVP, vertical-bullet-chart, card, chart, measure, dimension, axis, axis1, axis2

**STEP**: 1 — Minimum data requirements

**DESCRIPTION**: Ensure the payload/model contains at least one dimension and one measure. All dimensions are assigned to the axis category. Measures must include at least one axis1 (actual value) and optionally an axis2 (target value).

**LANGUAGE**: text

**CODE**:
```text
Minimum requirements:
- At least 1 dimension (assigned to "axis")
- At least 1 measure
  - axis1: actual value (rendered as solid-colored column)
  - axis2: target value (rendered as solid black line, optional)
```

**STEP**: 2 — Conceptual mapping example (dimension and measures)

**DESCRIPTION**: Map your model properties to the dimension and measure roles. Use the axis role for dimensions. Assign the actual measure to axis1 and the target measure to axis2.

**LANGUAGE**: json

**CODE**:
```json
{
  "dimension": {
    "path": "ProductCategory",
    "role": "axis"
  },
  "measures": [
    {
      "path": "SalesActual",
      "role": "axis1"   // rendered as solid-colored column (actual)
    },
    {
      "path": "SalesTarget",
      "role": "axis2"   // rendered as solid black line (target)
    }
  ]
}
```

**STEP**: 3 — Visual rendering rules

**DESCRIPTION**: Implement UI logic or card template settings to render:
- axis1 measures as solid-colored vertical columns (actual values)
- axis2 measures as a solid black line (target values)
If multiple axis1 measures exist, they appear as separate solid columns; axis2 is a single-line overlay.

**LANGUAGE**: text

**CODE**:
```text
Rendering rules:
- axis1 -> solid-colored columns (actual)
- axis2 -> solid black line (target)
- All dimensions -> axis category (x-axis grouping)
- Card requires >= 1 dimension and >= 1 measure
```

**STEP**: 4 — Example conceptual card configuration (for manifest/OVP)

**DESCRIPTION**: Example structure to include in a card manifest or card-settings object. Adapt keys to your framework's card schema; primary purpose is to show how to wire dimension/measure roles to the card.

**LANGUAGE**: json

**CODE**:
```json
{
  "card": {
    "template": "verticalBulletChart", // adapt to actual OVP/template key
    "settings": {
      "title": "Sales vs Target",
      "dimensions": [
        { "path": "ProductCategory", "role": "axis" }
      ],
      "measures": [
        { "path": "SalesActual", "role": "axis1" },
        { "path": "SalesTarget", "role": "axis2" }
      ]
    },
    "data": {
      "dataModelPath": "/SalesData"
    }
  }
}
```

**STEP**: 5 — Reference assets

**DESCRIPTION**: Include visual example and internal comment reference for documentation or asset linking.

**LANGUAGE**: text

**CODE**:
```text
Documentation comment: <!-- loiof4a899fec55246578a3387625f0a9fb3 -->
Example image path: ../01_Whats-New/images/WhatsNew_138_OVP_VerticalBullet_f2d9418.png
```

fiori-elements-framework OVP vertical-bullet-chart card chart measure dimension axis axis1 axis2


**TITLE**: Visual Filters — Annotation and Configuration Cookbook for Code Generation

**INTRODUCTION**: Action-oriented reference for implementing visual filters in SAP Fiori elements (OData V2/V4). Includes annotated code snippets (XML, ABAP CDS, CAP CDS, manifest.json, and JavaScript extension) for configuring ValueList, PresentationVariant, Chart, DataPoint, SelectionVariant, SelectionFields, TextArrangement, lazy loading, grouping, UoM text, semantic coloring, and number formatting. Use these snippets directly when generating or modifying metadata/annotations and controller extensions.

**TAGS**: visual-filter, valueList, presentationVariant, chart, dataPoint, selectionVariant, textArrangement, lazyLoad, manifest.json, CAP, ABAP, ODataV2, ODataV4, semantic-coloring, uom

STEP: Configure ValueList Annotation for Visual Filter
DESCRIPTION: Enhance the ValueList annotation on the filter field to enable visual filters. Ensure the value help entity set used here returns the same records as the regular filter field value help for sync. Map IN/OUT parameters so the chart dimension matches the ValueListProperty. Set PresentationVariantQualifier and SelectionVariantQualifier to point to chart and selection configuration.
LANGUAGE: XML
CODE:
```xml
<Annotations xmlns="http://docs.oasis-open.org/odata/ns/edm" Target="SEPMRA_ALP_SO_ANA_SRV.SEPMRA_C_ALP_SlsOrdItemCubeALPResult/SalesOrderOverallStatus">
   <Annotation Term="Common.ValueList" Qualifier="VisualFilter">
      <Record>
         <PropertyValue Property="Label" String="Overall Status" />
         <PropertyValue Property="CollectionPath" String="SEPMRA_C_ALP_SlsOrdItemCubeALPResults" />
         <PropertyValue Property="SearchSupported" Bool="false" />
         <PropertyValue Property="PresentationVariantQualifier" String="FilterNumberOfSalesOrdersByStatus" />
         <PropertyValue Property="SelectionVariantQualifier" String="SVForStatus" />
         <PropertyValue Property="Parameters">
            <Collection>
               <Record Type="Common.ValueListParameterInOut">
                  <PropertyValue Property="LocalDataProperty" PropertyPath="SalesOrderOverallStatus" />
                  <PropertyValue Property="ValueListProperty" String="SalesOrderOverallStatus" />
               </Record>
               <Record Type="Common.ValueListParameterInOut">
                  <PropertyValue Property="LocalDataProperty" PropertyPath="MainProductCategory" />
                  <PropertyValue Property="ValueListProperty" String="MainProductCategory" />
               </Record>
               <Record Type="Common.ValueListParameterInOut">
                  <PropertyValue Property="LocalDataProperty" PropertyPath="ProductCategory" />
                  <PropertyValue Property="ValueListProperty" String="ProductCategory" />
               </Record>
            </Collection>
         </PropertyValue>
      </Record>
   </Annotation>
</Annotations>
```

LANGUAGE: CAP CDS
CODE:
```cds
annotate SEPMRA_ALP_SO_ANA_SRV.SEPMRA_C_ALP_SlsOrdItemCubeALPResult with {
  @Common.ValueList #VisualFilter : {
    Label : 'Overall Status',
    CollectionPath : 'SEPMRA_C_ALP_SlsOrdItemCubeALPResults',
    SearchSupported : false,
    PresentationVariantQualifier : 'FilterNumberOfSalesOrdersByStatus',
    SelectionVariantQualifier : 'SVForStatus',
    Parameters : [
        {
            $Type : 'Common.ValueListParameterInOut',
            LocalDataProperty : SalesOrderOverallStatus,
            ValueListProperty : 'SalesOrderOverallStatus'
        },
        {
            $Type : 'Common.ValueListParameterInOut',
            LocalDataProperty : MainProductCategory,
            ValueListProperty : 'MainProductCategory'
        },
        {
            $Type : 'Common.ValueListParameterInOut',
            LocalDataProperty : ProductCategory,
            ValueListProperty : 'ProductCategory'
        }
    ]
  }
  SalesOrderOverallStatus
};
```

STEP: Define PresentationVariant Qualifier (chart definition entry point)
DESCRIPTION: Create a PresentationVariant with qualifier referenced from ValueList.PresentationVariantQualifier. PresentationVariant.SortOrder controls visual filter sorting. PresentationVariant.Visualizations points to UI.Chart annotation (@UI.Chart#Qualifier); the visual filter picks the first chart in Visualizations.
LANGUAGE: XML
CODE:
```xml
<Annotation Term="UI.PresentationVariant" Qualifier="FilterNumberOfSalesOrdersByStatus">
   <Record>
      <PropertyValue Property="Text" String="Filter: Number of Sales Order by Status" />
      <PropertyValue Property="SortOrder">
         <Collection>
            <Record Type="Common.SortOrderType">
               <PropertyValue Property="Property" PropertyPath="NumberOfSalesOrders" />
               <PropertyValue Property="Descending" Bool="true" />
            </Record>
         </Collection>
      </PropertyValue>
      <PropertyValue Property="Visualizations">
         <Collection>
            <AnnotationPath>@UI.Chart#FilterNumberOfSalesOrdersByStatus</AnnotationPath>
         </Collection>
      </PropertyValue>
   </Record>
</Annotation>
```

LANGUAGE: ABAP CDS
CODE:
```abap
@UI.PresentationVariant: [
  {
    text: 'Filter: Number of Sales Order by Status',
    sortOrder: [
      {
        by: 'NUMBEROFSALESORDERS',
        direction: #DESC
      }
    ],
    visualizations: [
      {
        type: #AS_CHART,
        qualifier: 'FilterNumberOfSalesOrdersByStatus'
      }
    ],
    qualifier: 'FilterNumberOfSalesOrdersByStatus'
  }
]
annotate view VIEWNAME with {

}
```

LANGUAGE: CAP CDS
CODE:
```cds
UI.PresentationVariant #FilterNumberOfSalesOrdersByStatus : {
    Text : 'Filter: Number of Sales Order by Status',
    SortOrder : [
        {
            $Type : 'Common.SortOrderType',
            Property : NumberOfSalesOrders,
            Descending : true
        },
    ],
    Visualizations : [
        '@UI.Chart#FilterNumberOfSalesOrdersByStatus'
    ]
},
```

STEP: Define Chart Annotation (first chart in PresentationVariant is used)
DESCRIPTION: Define UI.Chart with ChartType, Dimensions (first dimension is used), Measures (first measure is used), DimensionAttributes, and MeasureAttributes. Link measure to a DataPoint using AnnotationPath/DataPoint to enable formatting, scale, and semantic coloring.
LANGUAGE: XML
CODE:
```xml
<Annotation Term="UI.Chart" Qualifier="FilterNumberOfSalesOrdersByStatus">
   <Record Type="UI.ChartDefinitionType">
      <PropertyValue Property="Title" String="Sales Orders by Status" />
      <PropertyValue Property="Description" String="Number of Sales Orders by Status" />
      <PropertyValue Property="ChartType" EnumMember="UI.ChartType/Donut" />
      <PropertyValue Property="Dimensions">
         <Collection>
            <PropertyPath>SalesOrderOverallStatus</PropertyPath>
         </Collection>
      </PropertyValue>
      <PropertyValue Property="DimensionAttributes">
         <Collection>
            <Record Type="UI.ChartDimensionAttributeType">
               <PropertyValue Property="Dimension" PropertyPath="SalesOrderOverallStatus" />
               <PropertyValue Property="Role" EnumMember="UI.ChartDimensionRoleType/Category" />
            </Record>
         </Collection>
      </PropertyValue>
      <PropertyValue Property="Measures">
         <Collection>
            <PropertyPath>NumberOfSalesOrders</PropertyPath>
         </Collection>
      </PropertyValue>
      <PropertyValue Property="MeasureAttributes">
         <Collection>
            <Record Type="UI.ChartMeasureAttributeType">
               <PropertyValue Property="Measure" PropertyPath="NumberOfSalesOrders" />
               <PropertyValue Property="Role" EnumMember="UI.ChartMeasureRoleType/Axis1" />
               <PropertyValue Property="DataPoint" AnnotationPath="@UI.DataPoint#NumberOfSalesOrders" />
            </Record>
         </Collection>
      </PropertyValue>
   </Record>
</Annotation>
```

LANGUAGE: ABAP CDS
CODE:
```abap
@UI.Chart: [
  {
    title: 'Sales Orders by Status',
    description: 'Number of Sales Orders by Status',
    chartType: #DONUT,
    dimensions: [
      'SALESORDEROVERALLSTATUS'
    ],
    dimensionAttributes: [
      {
        dimension: 'SalesOrderOverallStatus',
        role: #CATEGORY
      }
    ],
    measures: [
      'NUMBEROFSALESORDERS'
    ],
    measureAttributes: [
      {
        measure: 'NumberOfSalesOrders',
        role: #AXIS_1,
		asDataPoint: true
      }
    ],
    qualifier: 'FilterNumberOfSalesOrdersByStatus'
  }
]
annotate view VIEWNAME with {

}
```

LANGUAGE: CAP CDS
CODE:
```cds
UI.Chart #FilterNumberOfSalesOrdersByStatus : {
    $Type : 'UI.ChartDefinitionType',
    Title : 'Sales Orders by Status',
    Description : 'Number of Sales Orders by Status',
    ChartType : #Donut,
    Dimensions : [
        SalesOrderOverallStatus
    ],
    DimensionAttributes : [
        {
            $Type : 'UI.ChartDimensionAttributeType',
            Dimension : SalesOrderOverallStatus,
            Role : #Category
        }
    ],
    Measures : [
        NumberOfSalesOrders
    ],
    MeasureAttributes : [
        {
            $Type : 'UI.ChartMeasureAttributeType',
            Measure : NumberOfSalesOrders,
            Role : #Axis1,
            DataPoint : '@UI.DataPoint#NumberOfSalesOrders'
        }
    ]
}
```

STEP: DataPoint: ScaleFactor and ValueFormat (affects chart title and scale)
DESCRIPTION: Define UI.DataPoint with Value.Path and ValueFormat.ScaleFactor to control chart title unit (K, M) and scaling. Avoid hard-coded scale unless fixed value ranges are guaranteed.
LANGUAGE: XML
CODE:
```xml
<Annotation Term="UI.DataPoint" Qualifier="LineChartTimeDataPoint">
    <Record Type="UI.DataPointType">
        <PropertyValue Property="Criticality" EnumMember="UI.CriticalityType/Positive"/>
        <PropertyValue Property="Title" String="Total Pricing"/>
        <PropertyValue Property="Value" Path="totalPricing"/>
        <PropertyValue Property="ValueFormat">
            <Record Type="UI.NumberFormat">
                <PropertyValue Property="ScaleFactor" Decimal="1000"/>
            </Record>
        </PropertyValue>
    </Record>
</Annotation>
```

STEP: SelectionFields (control visual filter order)
DESCRIPTION: Define UI.SelectionFields on the main entity to determine the ordering of filters displayed in the visual filter bar. Mandatory filter fields not included appear first automatically.
LANGUAGE: XML
CODE:
```xml
<Annotation Term="UI.SelectionFields">
  <Collection>
    <PropertyPath>DeliveryCalendarYear</PropertyPath>
    <PropertyPath>SoldToParty</PropertyPath>
    <PropertyPath>Product</PropertyPath>
    <PropertyPath>MainProductCategory</PropertyPath>
    <PropertyPath>DeliveryCalendarQuarter</PropertyPath>
  </Collection>
</Annotation>
```

LANGUAGE: ABAP CDS
CODE:
```abap
@UI.SelectionField: [{ position: 10 }]
DELIVERYCALENDARYEAR;

@UI.SelectionField: [{ position: 20 }]
SOLDTOPARTY;

@UI.SelectionField: [{ position: 30 }]
PRODUCT;

@UI.SelectionField: [{ position: 40 }]
MAINPRODUCTCATEGORY;

@UI.SelectionField: [{ position: 50 }]
DELIVERYCALENDARQUARTER;
```

LANGUAGE: CAP CDS
CODE:
```cds
UI.SelectionFields : [
    DeliveryCalendarYear,
    SoldToParty,
    Product,
    MainProductCategory,
    DeliveryCalendarQuarter
]
```

STEP: SelectionVariant (default/fixed filter values and parametrized collection paths)
DESCRIPTION: Provide default SelectOptions/Parameters via UI.SelectionVariant and reference it from ValueList.SelectionVariantQualifier. For date values in SelectionVariant use UTC format (e.g., "2018-10-15T00:00:00Z"). When using parametrized collection paths, provide parameter values here; values in smart filter bar override SelectionVariant.
LANGUAGE: XML
CODE:
```xml
<Annotation Term="UI.SelectionVariant" Qualifier="SVForStatus">
   <Record>
      <PropertyValue Property="Parameters">
         <Collection>
            <Record Type="UI.Parameter">
               <PropertyValue Property="PropertyName" PropertyPath="CompanyCurrency" />
               <PropertyValue Property="PropertyValue" String="EUR" />
            </Record>
         </Collection>
      </PropertyValue>
      <PropertyValue Property="SelectOptions">
         <Collection>
            <Record Type="UI.SelectOptionType">
               <PropertyValue Property="PropertyName" PropertyPath="SalesOrderOverallStatus" />
               <PropertyValue Property="Ranges">
                  <Collection>
                     <Record Type="UI.SelectionRangeType">
                        <PropertyValue EnumMember="UI.SelectionRangeSignType/E" Property="Sign" />
                        <PropertyValue EnumMember="UI.SelectionRangeOptionType/EQ" Property="Option" />
                        <PropertyValue Property="Low" String="D" />
                     </Record>
                  </Collection>
               </PropertyValue>
            </Record>
            <Record Type="UI.SelectOptionType">
               <PropertyValue Property="PropertyName" PropertyPath="Product" />
               <PropertyValue Property="Ranges">
                  <Collection>
                     <Record Type="UI.SelectionRangeType">
                        <PropertyValue EnumMember="UI.SelectionRangeSignType/E" Property="Sign" />
                        <PropertyValue EnumMember="UI.SelectionRangeOptionType/EQ" Property="Option" />
                        <PropertyValue Property="Low" String="HT-1502" />
                     </Record>
                  </Collection>
               </PropertyValue>
            </Record>
         </Collection>
      </PropertyValue>
   </Record>
</Annotation>
```

LANGUAGE: ABAP CDS
CODE:
```abap
@UI.selectionVariant: [
  {
    qualifier: 'SVForStatus',
	parameters: [{name: 'PropertyName', value: 'CompanyCurrency' },{ name: 'PropertyValue', value: 'EUR'}]
  }
]
```

LANGUAGE: CAP CDS
CODE:
```cds
UI.SelectionVariant #SVForStatus : {
    Parameters : [
        {
            $Type : 'UI.Parameter',
            PropertyName : CompanyCurrency,
            PropertyValue : 'EUR'
        }
    ],
    SelectOptions : [
        {
            $Type : 'UI.SelectOptionType',
            PropertyName : SalesOrderOverallStatus,
            Ranges : [
                {
                    $Type : 'UI.SelectionRangeType',
                    Sign : #E,
                    Option : #EQ,
                    Low : 'D'
                }
            ]
        },
        {
            $Type : 'UI.SelectOptionType',
            PropertyName : Product,
            Ranges : [
                {
                    $Type : 'UI.SelectionRangeType',
                    Sign : #E,
                    Option : #EQ,
                    Low : 'HT-1502'
                }
            ]
        }
    ]
}
```

STEP: Chart Type Behavior and AccumulativeMeasure for V2
DESCRIPTION: Chart selection behavior: Bar shows top/bottom 3, Line shows first/last 6 points, Donut (V2 only) shows top/bottom 2. For Donut overlay behavior when measures have negative values in OData V2, set Analytics.AccumulativeMeasure to false on measure.
LANGUAGE: XML
CODE:
```xml
<Annotations Target="SEPMRA_ALP_SO_ANA_SRV.Z_SEPMRA_C_ALP_QUARTERVHType/DifferenceAmount">
    <Annotation Term="Analytics.Measure" Bool="true" />
    <Annotation Term="Analytics.AccumulativeMeasure" Bool="false" />
</Annotations>
```

STEP: TextArrangement (format visual filter labels)
DESCRIPTION: Use UI.TextArrangement on the main entity set to control how sap:text and ID are shown in visual filters: TextFirst, TextLast, TextOnly, TextSeparate.
LANGUAGE: XML
CODE:
```xml
<Annotations Target="ProductType">
  <Annotation Term="com.sap.vocabularies.UI.v1.TextArrangement" EnumMember="com.sap.vocabularies.UI.v1.TextArrangementType/TextFirst"/>
</Annotations>
```

LANGUAGE: ABAP CDS
CODE:
```abap
@UI.textArrangement: #TEXT_FIRST
annotate view ProductType with {

}
```

LANGUAGE: CAP CDS
CODE:
```cds
annotate ProductType @(
  UI.TextArrangement : #TextFirst
);
```

STEP: Lazy Loading of Visual Filters (manifest.json)
DESCRIPTION: Enable lazyLoadVisualFilter in manifest.json for OData V2 to defer batch call until user switches to visual filter bar. OData V4: lazy loading enabled by default and cannot be disabled.
LANGUAGE: JSON
CODE:
```json
"settings": {
              "qualifier": "MainContent",
              "defaultContentView": "charttable",
              "smartVariantManagement": true,
              "showGoButtonOnFilterBar": true,
              "multiSelect": true,
              "lazyLoadVisualFilter":true,
              "tableType": "AnalyticalTable"
}
```

STEP: Grouping Visual Filter Calls (controller extension for batch grouping)
DESCRIPTION: Implement onBeforeRebindVisualFilterExtension in controller to assign oContext.groupId for grouping visual filter OData calls into batches. groupId values must be keys in oContext and are string identifiers for grouping.
LANGUAGE: JavaScript
CODE:
```javascript
onBeforeRebindVisualFilterExtension: function(sEntityType, sDimension, sMeasure, oContext){
    'use strict';
    var Log = sap.ui.require("sap/base/Log");
    if (sDimension === "Product") {
        oContext.groupId = "Group1";
    }
    if (sDimension === "DeliveryCalendarMonth" || sDimension === "DeliveryCalendarQuarter") {
        oContext.groupId = "Group2";
    }
    Log.info("onBeforeRebindVisualFilterExtension called!");
}
```

STEP: Unit of Measure Text Lookup (main entity vs value list)
DESCRIPTION: If unit (e.g., currency) has sap:text, that text is displayed next to the unit in visual filter. Preference: main entity sap:text is used first; if missing and a value list entity set defines sap:text, the value list text is fetched and shown.
LANGUAGE: XML
CODE:
```xml
<!-- Main Entity Set: DisplayCurrency doesn't contain sap:text -->
<EntityType Name="ZEPM_C_SALESORDERITEMQUERYResult" sap:semantics="aggregate" sap:content-version="1">
    <Key>
        <PropertyRef Name="ID"/>
    </Key>
    <Property Name="DisplayCurrency" Type="Edm.String" MaxLength="5" sap:aggregation-role="dimension" sap:creatable="false" sap:label="Display Currency" sap:updatable="false" sap:semantics="currency-code"/>
</EntityType>

<!-- Value List Entity Set: DisplayCurrency contains sap:text mapping -->
<EntityType Name="ZEPM_C_SALESORDERITEMQUERYValueHelpResult" sap:semantics="aggregate" sap:content-version="1">
    <Key>
        <PropertyRef Name="ID"/>
    </Key>
    <Property Name="DisplayCurrency" Type="Edm.String" MaxLength="5" sap:aggregation-role="dimension" sap:creatable="false" sap:label="Display Currency" sap:updatable="false" sap:semantics="currency-code" sap:text="DisplayCurrencyText"/>
    <Property Name="DisplayCurrencyText" Type="Edm.String" MaxLength="60" sap:filterable="false"/>
</EntityType>
```

STEP: Number Formatting (NumberOfFractionalDigits via DataPoint.ValueFormat)
DESCRIPTION: Control fractional digits shown in visual filters using UI.DataPoint.ValueFormat.NumberOfFractionalDigits. Rules: decimals not shown by default; annotations can request 1 or 2 digits. V2/V4 behavior differences noted (V4 caps to 2 digits).
LANGUAGE: XML
CODE:
```xml
<Annotation Term="com.sap.vocabularies.UI.v1.DataPoint" Qualifier="Price">
    <Record Type="com.sap.vocabularies.UI.v1.DataPointType">
        <PropertyValue Property="Value" Path="Price"/>
        <PropertyValue Property="ValueFormat">
            <Record Type="com.sap.vocabularies.UI.v1.NumberFormat">
                <PropertyValue Property="NumberOfFractionalDigits" Int="1"/>
            </Record>
        </PropertyValue>
    </Record>
</Annotation>
```

LANGUAGE: ABAP CDS
CODE:
```abap
@UI.dataPoint: {
   valueFormat.numberOfFractionalDigits: 1
}
price;
```

LANGUAGE: CAP CDS
CODE:
```cds
UI.DataPoint #Price : {
    $Type : 'UI.DataPointType',
    Value : Price,
    ValueFormat : {
        $Type : 'UI.NumberFormat',
        NumberOfFractionalDigits : 1
    }
}
```

STEP: Semantic Coloring for Visual Filters (dimension and measure)
DESCRIPTION: Use ValueCriticality (for dimension values) or DataPoint.Criticality/CriticalityCalculation (for measures) to apply semantic coloring. Measure coloring takes precedence over dimension coloring. For OData V4 only hard-coded criticality values are supported for measures—ensure DataPoint exists and criticality is configured.
LANGUAGE: XML
CODE:
```xml
<Annotation Term="UI.Chart" Qualifier="BarChartSoldToParty">
     <Record Type="UI.ChartDefinitionType">
          <PropertyValue Property="Title" String="Bar Chart"/>
          <PropertyValue Property="Description" String="Testing Bar Chart"/>
          <PropertyValue Property="ChartType" EnumMember="UI.ChartType/Bar"/>
          <PropertyValue Property="Measures">
               <Collection>
                    <PropertyPath>totalPricing</PropertyPath>
               </Collection>
          </PropertyValue>
          <PropertyValue Property="Dimensions">
               <Collection>
          <PropertyPath>SoldToParty</PropertyPath>
               </Collection>
          </PropertyValue>
          <PropertyValue Property="MeasureAttributes">
               <Collection>
                    <Record Type="UI.ChartMeasureAttributeType">
                         <PropertyValue Property="Measure" PropertyPath=" totalPricing"/>
                         <PropertyValue Property="Role" EnumMember="UI.ChartMeasureRoleType/Axis1"/>
                         <PropertyValue Property="DataPoint" AnnotationPath="@UI.DataPoint#LineChartTimeDataPoint"/>
                    </Record>
               </Collection>
          </PropertyValue>
          <PropertyValue Property="DimensionAttributes">
               <Collection/>
          </PropertyValue>
     </Record>
</Annotation>

<Annotation Term="UI.DataPoint" Qualifier="LineChartTimeDataPoint">
     <Record Type="UI.DataPointType">
          <PropertyValue Property="Value" Path="totalPricing"/>
          <PropertyValue Property="Title" String="Total Pricing"/>
          <PropertyValue Property="Criticality" EnumMember="UI.CriticalityType/Positive"/>
     </Record>
</Annotation>
```

LANGUAGE: ABAP CDS
CODE:
```abap
@UI.chart: [
  {
    chartType: #BAR,
    title: 'Bar Chart',
    description: 'Testing Bar Chart',
    dimensions: [
      'SoldToParty'
    ],
    measures: [
      'totalPricing'
    ],
    measureAttributes: [{measure: 'totalPricing', role: #AXIS_1, asDataPoint: true }],
  }
]

@UI.dataPoint: {
     title: 'Total Pricing',
     criticalityValue: #POSITIVE
 }
totalPricing;
```

LANGUAGE: CAP CDS
CODE:
```cds
Chart #BarChartSoldToParty               : {
            $Type             : 'UI.ChartDefinitionType',
            Title             : 'Bar Chart',
            Description       : 'Testing Bar Chart',
            ChartType         : #Bar,
            Measures          : [totalPricing],
            Dimensions        : [SoldToParty],
            MeasureAttributes : [{
                $Type     : 'UI.ChartMeasureAttributeType',
                Measure   : totalPricing,
                Role      : #Axis1,
                DataPoint : '@UI.DataPoint#LineChartTimeDataPoint'
            }],
DimensionAttributes: []
        },
DataPoint #LineChartTimeDataPoint              : {
            Value       : totalPricing,
            Title       : 'Total Pricing',
            Criticality : #Positive,
            ValueFormat : {
                ScaleFactor: 1000
            }
```

STEP: OData V4 Specifics and Guidelines
DESCRIPTION: Ensure a manifest property exists per visual filter (required in V4). Line charts in V4 render only for time-based dimensions (Edm.Date, Edm.Time, Edm.DateTimeOffset). Date/time handling: Edm.Date is not converted to local timezone; other date/time formats are converted to local timezone. Follow guideline: show each filter dimension with exactly one measure in visual filter; do not show the same dimension with multiple measures simultaneously.

CODE:
```text
- Ensure manifest.json contains entries for each visual filter (see Configuring the Visual Filter Bar documentation).
- Use only one representation per dimension in visual filter bar to keep sync with regular filter bar.
- Line charts: dimension types must be Edm.Date, Edm.Time, or Edm.DateTimeOffset in OData V4.
```

Related Information: Configuring the Visual Filter Bar and Enhancing ValueList Annotations for Visual Filters should be consulted for full end-to-end implementation patterns and service-side requirements.

visual-filter valueList presentationVariant chart dataPoint selectionVariant textArrangement lazyLoad manifest.json CAP ABAP ODataV2 ODataV4 semantic-coloring uom


**TITLE**: Waterfall Chart Card (Fiori Elements) — Annotation Examples and Requirements

**INTRODUCTION**: Use the Waterfall Chart Card to visualize cumulative value changes (initial to final state). This guide provides concise, action-oriented annotation rules and three concrete code examples (XML UI annotation, ABAP CDS, CAP CDS) to implement waterfall charts in Fiori Elements. Includes required roles, allowed waterfallType values, legend behavior, and semantic coloring notes.

**TAGS**: fiori-elements, UI.Chart, Waterfall, chart, CDS, CAP, ABAP, XML, annotation, criticality, waterfallType

STEP: 1 — Requirements & Dimension/Measure Roles

DESCRIPTION: Implement a waterfall chart only if you map at least one measure and one dimension. Assign dimension and measure roles explicitly to determine axes and cumulative groups. Follow these rules when authoring annotations:

- Waterfall charts require at least one measure and one dimension.
- Dimension roles:
  - Category role => used for x-axis (category axis). If no role specified, the first dimension becomes the x-axis.
  - Series role => used to create cumulative data points. Only one dimension per role is allowed.
  - waterfallType UID mapping => use to mark intermediate totals and subtotals. Valid values:
    - null
    - subtotal:2 (combines the previous two datapoints and shows a subtotal column)
    - total (combines all datapoints and shows a total column)
- Measure role:
  - Measures map to the y-axis (value axis).
- Chart types supported:
  - Waterfall without time dimension
  - Waterfall with time dimension (represents cumulative change over time)
- Semantic coloring:
  - Use datapoint annotations com.sap.vocabularies.UI.v1.CriticalityCalculation or com.sap.vocabularies.UI.v1.Criticality to enable semantic coloring.

LANGUAGE: text

CODE:
```text
Rules Summary:
- At least 1 measure and 1 dimension required.
- Dimensions with Role=Category -> x-axis (first dimension used if none specified).
- Dimensions with Role=Series -> cumulative data points (only one per role).
- waterfallType UID valid values: null, subtotal:2, total.
- Measures -> y-axis.
- Semantic coloring via datapoint annotations: com.sap.vocabularies.UI.v1.CriticalityCalculation or com.sap.vocabularies.UI.v1.Criticality.
```

STEP: 2 — Legend Behavior and Semantic Waterfall Notes

DESCRIPTION: Understand legend defaults and semantic waterfall behavior before adding annotations:

- Legend default: shows the measure name mapped to the chart and two fixed groups "<0" and ">0".
- If more than one measure is provided, the legend displays all measures (instead of the measure name).
- Semantic waterfall charts use criticality annotations on datapoints (CriticalityCalculation or Criticality) to determine coloring of positive/negative/subtotal/total bars.
- Use time dimension if you must represent cumulative changes over time.

LANGUAGE: text

CODE:
```text
Legend & Semantic Notes:
- Default legend: [MeasureName] with groups "<0" and ">0".
- Multiple measures -> legend lists measures individually.
- Semantic coloring: apply datapoint Criticality/Calculation annotations per data point.
- Use a time-dimension as the Category dimension to show changes over time.
```

STEP: 3 — XML Annotation Example (UI.Chart)

DESCRIPTION: Copy this XML annotation into your OData service metadata extensions/annotations XML (or manifest annotation file) to define a Waterfall chart with one measure (Finances) and two dimensions (SpendType as Category, Type as Series). Adjust PropertyPath, Qualifier, Title, roles, and measure names to your data model.

LANGUAGE: XML

CODE:
```xml
<Annotation Term="UI.Chart" Qualifier="Waterfall_Eval_by_Country">
    <Record Type="UI.ChartDefinitionType">
        <PropertyValue Property="Title" String="Revenue Waterfall" />
        <PropertyValue Property="ChartType" EnumMember="UI.ChartType/Waterfall"/>
        <PropertyValue Property="MeasureAttributes">
            <Collection>
                <Record Type="UI.ChartMeasureAttributeType">
                    <PropertyValue Property="Measure" PropertyPath="Finances" />
                    <PropertyValue Property="Role" EnumMember="UI.ChartMeasureRoleType/Axis2" />
                </Record>
            </Collection>
        </PropertyValue>
        <PropertyValue Property="DimensionAttributes">
            <Collection>
                <Record Type="UI.ChartDimensionAttributeType">
                    <PropertyValue Property="Dimension" PropertyPath="SpendType" />
                    <PropertyValue Property="Role" EnumMember="UI.ChartDimensionRoleType/Category" />
                </Record>
                <Record Type="UI.ChartDimensionAttributeType">
                    <PropertyValue Property="Dimension" PropertyPath="Type" />
                    <PropertyValue Property="Role" EnumMember="UI.ChartDimensionRoleType/Series" />
                </Record>
            </Collection>
        </PropertyValue>
    </Record>
</Annotation>
```

STEP: 4 — ABAP CDS Annotation Example (@UI.Chart)

DESCRIPTION: Add this @UI.Chart annotation to your ABAP CDS view to declare a Waterfall chart. Replace VIEWNAME and field names as needed. The qualifier is Waterfall_Eval_by_Country; the annotation maps Finances to AXIS_2, SpendType to CATEGORY and Type to SERIES.

LANGUAGE: ABAP

CODE:
```abap
@UI.Chart: [
  {
    title: 'Revenue Waterfall',
	chartType: #WATERFALL,
    measureAttributes: [
      {
        measure: 'Finances',
        role: #AXIS_2
      }
    ],
    dimensionAttributes: [
      {
        dimension: 'SpendType',
        role: #CATEGORY
      },
      {
        dimension: 'Type',
        role: #SERIES
      }
    ],
    qualifier: 'Waterfall_Eval_by_Country'
  }
]
annotate view VIEWNAME with { }
```

STEP: 5 — CAP CDS Annotation Example (Service Model)

DESCRIPTION: Use this CAP CDS snippet in your service-level annotations file to define the same Waterfall chart for a CAP-based project. Adjust entity field names (Finances, SpendType, Type) and the qualifier as required.

LANGUAGE: CDS

CODE:
```cds
UI.Chart #Waterfall_Eval_by_Country : {
    $Type : 'UI.ChartDefinitionType',
    Title : 'Revenue Waterfall',
    ChartType : #Waterfall,
    MeasureAttributes : [
        {
            $Type : 'UI.ChartMeasureAttributeType',
            Measure : Finances,
            Role : #Axis2
        },
    ],
    DimensionAttributes : [
        {
            $Type : 'UI.ChartDimensionAttributeType',
            Dimension : SpendType,
            Role : #Category
        },
        {
            $Type : 'UI.ChartDimensionAttributeType',
            Dimension : Type,
            Role : #Series
        }
    ]
}
```

fiori-elements UI.Chart Waterfall chart CDS CAP ABAP XML annotation criticality waterfallType


**TITLE**: Why Use SAP Fiori Elements?

**INTRODUCTION**: Brief summary of the benefits and recommended use cases for SAP Fiori Elements. Use this as guidance when generating apps: choose Fiori Elements to accelerate UI development with metadata-driven templates, maintain consistent UX, and deliver enterprise-ready applications with minimal custom UI code.

**TAGS**: fiori-elements, sapui5, ui5, annotations, odata, developer-productivity, ux-consistency, enterprise-readiness

**STEP**: 1 — Developer Productivity

**DESCRIPTION**: Use SAP Fiori Elements to minimize manual UI coding and focus on backend/business logic. Actionable guidance for code generation:
- Prefer metadata-driven UI: design OData service and annotations (CDS/annotation files) first.
- Use Fiori Elements templates (ListReport, ObjectPage, OverviewPage) instead of freestyle SAPUI5 views.
- Generate apps from templates (SAP Business Application Studio / Yeoman generator) to bootstrap projects.
- Create reusable annotation models and shared libraries for common patterns to reduce per-app effort.
- Automate repetitive tasks (scaffolding, tests, CI) so developers can concentrate on service logic and custom actions.

**LANGUAGE**: Markdown

**CODE**:
```markdown
![](images/StopWatch_f6dd642.png)
- Focus on **business logic** and back-end services
- Write **less UI code**
- **Reduce** development and maintenance **costs**
```

**STEP**: 2 — UX Consistency

**DESCRIPTION**: Rely on Fiori Elements to automatically enforce SAP Fiori design guidelines across apps. Actionable recommendations for generated code:
- Drive UI layout and features through annotations to ensure uniform behavior (search, filtering, table/list behavior).
- Use centralized theming and design tokens; integrate apps in Fiori Launchpad for unified navigation and role-based access.
- Keep UI customizations minimal and implement extensibility through extension points or controller extensions when necessary to preserve consistency.

**LANGUAGE**: Markdown

**CODE**:
```markdown
![](images/Data_Consistency_ba4b763.png)
- Comply with the **latest SAP Fiori design** specification
- Deliver a **centrally managed** user experience
- Include **uniform** layout, navigation, search, filtering, and more
```

**STEP**: 3 — Enterprise Readiness

**DESCRIPTION**: Use the framework to deliver production-quality applications with built-in enterprise features. Actionable implementation notes:
- Leverage built-in accessibility, mobile responsiveness, and translation (i18n) support — configure during generation.
- Choose optimized templates to get stable, performant UI code out-of-the-box (ListReport/ObjectPage).
- Integrate testing (unit, e2e), performance checks, and CI/CD pipelines at project generation to enforce enterprise standards.

**LANGUAGE**: Markdown

**CODE**:
```markdown
![](images/GrothUpArrows_5d9c969.png)
- Deliver **high-quality** SAPUI5 applications to end users
- Ensure **stable, optimized** UI code out of the box
- Include **standard enterprise features** (accessibility, mobile, translation support, and more)
```

**STEP**: 4 — Note on Initial Effort and Long-term Benefits

**DESCRIPTION**: Acknowledge initial investment required and provide actionable steps to amortize that cost across projects:
- Expect a higher initial setup (annotation modeling, service design, template selection).
- Reuse metadata models, create an internal catalog of templates, and automate app generation to reduce per-app overhead.
- Once patterns and automation are in place, new apps inherit framework benefits immediately.

**LANGUAGE**: Text

**CODE**:
```
Note:
The initial effort for creating an app using SAP Fiori elements might be higher than creating a freestyle SAPUI5 app. However, you will be richly rewarded for this effort after you've created more apps this way because your apps will benefit from using the framework and the included features.
```

Why Use SAP Fiori Elements?

fiori-elements sapui5 ui5 annotations odata developer-productivity ux-consistency enterprise-readiness


**TITLE**: Working With OData Annotations

**INTRODUCTION**: Practical reference for defining and managing OData annotations used by SAP Fiori elements to generate UI automatically. Includes XML, ABAP CDS, and CAP CDS examples for common annotation tasks (labels, list columns), guidance on vocabularies, and rules for back-end vs front-end annotation placement and override behavior.

**TAGS**: fiori-elements-framework, odata, annotations, CDS, CAP, ABAP, UI.LineItem, Common.Label, manifest.json, sap-fiori-tools

STEP: Vocabularies

DESCRIPTION: Use standard vocabularies to define OData annotation terms. Reference the official SAP and OASIS collections to ensure correct terms and semantics.

LANGUAGE: text

CODE:
```text
SAP defined vocabularies: https://github.com/sap/odata-vocabularies
OASIS vocabularies: https://github.com/oasis-tcs/odata-vocabularies
```

STEP: 1 — Specify a Label for the Name Property (XML annotation)

DESCRIPTION: Add a Common.Label annotation in an annotation XML to set the UI label for the Name property of the Products entity.

LANGUAGE: XML

CODE:
```xml
<Annotations Target="namespace.ServiceName.Products/Name">
  <Annotation Term="Common.Label" String="Name"/>
</Annotations>
```

STEP: 2 — Specify a Label for the Name Property (ABAP CDS annotation)

DESCRIPTION: In ABAP CDS, add an @EndUserText.label to provide the UI label for the Name field in the CDS view.

LANGUAGE: ABAP CDS

CODE:
```
@EndUserText.label: 'Name'
name          as Name,
```

STEP: 3 — Specify a Label for the Name Property (CAP CDS annotation)

DESCRIPTION: In CAP CDS, annotate the model property with @title to set the UI label.

LANGUAGE: CAP CDS

CODE:
```
Name: String(100) @title: 'Name';
```

STEP: 4 — Define Which Columns Are Shown in a Table (XML annotation using UI.LineItem)

DESCRIPTION: Use UI.LineItem in XML annotations to declare which properties appear as columns in list/table UIs. Each Record of type UI.DataField references the property via PropertyValue/Path.

LANGUAGE: XML

CODE:
```xml
<Annotation Term="UI.LineItem">
    <Collection>
        <Record Type="UI.DataField">
            <PropertyValue Property="Value" Path="Name"/>
        </Record>
        <Record Type="UI.DataField">
            <PropertyValue Property="Value" Path="Category"/>
        </Record>
        <Record Type="UI.DataField">
            <PropertyValue Property="Value" Path="Price"/>
        </Record>
        <Record Type="UI.DataField">
            <PropertyValue Property="Value" Path="Availability"/>
        </Record>
    </Collection>
</Annotation>
```

STEP: 5 — Define Which Columns Are Shown in a Table (ABAP CDS UI.lineItem)

DESCRIPTION: Annotate each field with @UI.lineItem in ABAP CDS to specify positions and include fields in the table LineItem.

LANGUAGE: ABAP CDS

CODE:
```
@UI.lineItem: [{ position: 10 }]
Name;

@UI.lineItem: [{ position: 20 }]
Category;

@UI.lineItem: [{ position: 30 }]
Price;

@UI.lineItem: [{ position: 40 }]
Availability;
```

STEP: 6 — Define Which Columns Are Shown in a Table (CAP CDS UI.LineItem)

DESCRIPTION: Use CAP CDS annotate syntax to attach a UI.LineItem collection to the service entity. Each entry is a UI.DataField with Value referencing the model property.

LANGUAGE: CAP CDS

CODE:
```
annotate ServiceName.Products with @(UI.LineItem: [
    {
        $Type: 'UI.DataField',
        Value: Name,
    },
    {
        $Type: 'UI.DataField',
        Value: Category
    },
    {
        $Type: 'UI.DataField',
        Value: Price,
    },
    {
        $Type: 'UI.DataField',
        Value: Availability,
    }
]);
```

STEP: 7 — Back-End vs Front-End Annotations — placement, use cases, and override behavior

DESCRIPTION: Guidelines for where to maintain annotations and when to use front-end annotation files.

- Maintain annotations in the back end (CDS) whenever possible to keep data model and semantics together and enable reuse across UIs.
- Back ends that support CDS-based annotations: CAP, RAP (including metadata extensions), ABAP Programming Model for SAP Fiori.
- Front-end annotations: provide additional `.xml` files in the UI application and register them as additional annotation sources in the app's manifest.json.
- Override rules:
  - When an annotation term (for example, UI.LineItem) exists in an additional front-end annotation source, it overwrites the same term defined in the back end (CDS).
  - When using both back-end and front-end annotations simultaneously, front-end annotations override back-end annotations on a term-by-term basis.
- When to use front-end annotations:
  - Annotation not available in the back end (only applicable to RAP).
  - No back-end access to maintain annotations.
  - Need to override annotations for a single UI without changing the back end.
- Disadvantages of front-end annotations: risk of discrepancies between front-end annotations and the data model (e.g., after renaming properties), which can cause errors.

LANGUAGE: text

CODE:
```text
These `.xml` files for front-end annotations are maintained in the `manifest.json` file of the UI application as additional annotation sources.
Note: When an annotation term, such as `UI.LineItem`, is defined in an additional annotation source on the front end, it overwrites the annotation term which is defined in the back end (CDS), if one exists.
Tip: It is recommended to maintain annotations in the back end. This keeps the data model definition and semantic information in the same place and enables reuse.
```

STEP: 8 — SAP Fiori Tools Support

DESCRIPTION: Use SAP Fiori tools extensions in VS Code or Business Application Studio to create, edit, and validate local annotations. Tools provide Page Map, Guided Development, and editors for CAP CDS and XML annotation files. For ABAP CDS, use Guided Development.

LANGUAGE: text

CODE:
```text
SAP Fiori Tools Documentation: https://help.sap.com/docs/SAP_FIORI_tools/17d50220bcd848aa854c9c182d65b699/55bfb91591d84f658e6c9474a3c657c4.html?locale=en-US
Feature Showcase Apps and Samples: https://ui5.sap.com/#/topic/521405cc719e4e699a25366461a516cb
RESTful Application Programming Model: https://help.sap.com/docs/abap-cloud/abap-rap/abap-restful-application-programming-model
CAP Annotation Documentation: https://cap.cloud.sap/docs/advanced/fiori#fiori-annotations
```

STEP: 9 — Quick Implementation Checklist

DESCRIPTION: Action-oriented checklist to implement annotations in a project.

LANGUAGE: text

CODE:
```text
- Choose vocabulary/term from SAP or OASIS vocabularies (links above).
- Prefer back-end CDS annotations where possible.
- If front-end annotation required:
  - Add XML annotation file to UI project.
  - Register the XML file as an annotation source in manifest.json.
  - Verify that front-end annotations override back-end terms as intended.
- Use SAP Fiori Tools for editing and validation.
- Test UI behavior and metadata ($metadata) to ensure annotations appear and are applied.
```

Working With OData Annotations

fiori-elements-framework odata annotations CDS CAP ABAP UI.LineItem Common.Label manifest.json sap-fiori-tools


**TITLE**: Worklist (Fiori Elements) — Quick Implementation and Manifest Configuration

**INTRODUCTION**: This document provides concise, code-focused instructions to create a Fiori Elements Worklist app and to configure key manifest flags required by Worklist floorplan behavior. It highlights generator usage and manifest.json settings for variant management (table-level and page-level). Use these snippets when scaffolding or modifying a Worklist app.

**TAGS**: fiori, fiori-elements, worklist, odata, manifest.json, variants, smart-table, generator

**STEP**: 1 — Generate a Worklist App using the SAP Fiori generator

**DESCRIPTION**: Use the SAP Fiori application generator (Yeoman generator) to scaffold a Worklist Page. When prompted by the generator, select the Worklist Page template. This creates the project structure and initial manifest.json for a Worklist floorplan.

**LANGUAGE**: Shell

**CODE**:
```bash
# Install generator if not present
npm install -g @sap/generator-fiori

# Run the generator and choose 'Worklist Page' at Template Selection
yo @sap/generator-fiori
```

**STEP**: 2 — Enable table-level variant management (manifest.json)

**DESCRIPTION**: To provide variant management at the table level only (default: hidden), set variantManagementHidden to false in the Worklist page component settings in manifest.json. Place this in the Worklist page entry inside "sap.ui.generic.app" -> "pages" -> corresponding page -> "component" -> "settings". This enables the table's variant UI without enabling smartVariantManagement at page level.

**LANGUAGE**: JSON

**CODE**:
```json
{
  "sap.ui.generic.app": {
    "pages": [
      {
        "entitySet": "YourEntitySet",
        "component": {
          "name": "sap.suite.ui.generic.template.ListReport.view.ListReport",
          "settings": {
            "variantManagementHidden": false
          }
        }
      }
    ]
  }
}
```

**STEP**: 3 — Enable page-level variant management (manifest.json)

**DESCRIPTION**: To enable page-level variant management (shared variants across the page), set smartVariantManagement to true and ensure variantManagementHidden is false in the Worklist page component settings in manifest.json.

**LANGUAGE**: JSON

**CODE**:
```json
{
  "sap.ui.generic.app": {
    "pages": [
      {
        "entitySet": "YourEntitySet",
        "component": {
          "name": "sap.suite.ui.generic.template.ListReport.view.ListReport",
          "settings": {
            "smartVariantManagement": true,
            "variantManagementHidden": false
          }
        }
      }
    ]
  }
}
```

**STEP**: 4 — Understand Worklist floorplan behavior (no manifest change required)

**DESCRIPTION**: Use these behavior notes as constraints when implementing UI or customizing the app:
- Worklist is a simplified List Report without a Smart Filter Bar; search field is in the table toolbar.
- Execute on Select action is not available.
- Multiselect is enabled by default for tables. If a table only has line item actions, the table can be configured as a no-selection table.
- Export to Microsoft Excel is not available in Worklist.
- Default table type is responsive; table title shows the row count. Table content defaults to fixed layout and scroll-to-load behavior.
- To implement category worklists, define multiple views within a single table (multiple views / single table mode).

No additional manifest snippet is required for these behaviors unless specific custom settings are added for your implementation.

**STEP**: 5 — Notes for OData V4 and further configuration

**DESCRIPTION**: For OData V4 the Worklist is still a simplified List Report without a filter bar. Use the generator to create a V4-compatible Worklist. For advanced table, filtering, navigation, and extension options, consult the corresponding Fiori Elements configuration and extension documentation (Configuring Filter Bars, Configuring Tables, Configuring Navigation, App Extensions). No code snippet is provided here; adjust manifest and component settings as needed for your OData version and required extensions.

fiori fiori-elements worklist odata manifest.json variants smart-table generator


# Commands in SAP Fiori Tools

# Commands in SAP Fiori Tools

## Commands in Application Info page
|Feature|Group|SAP Fiori elements|SAPUI5 freestyle|Fiori Reuse|v2|v4|EDMX Backend|CAP Node.js|CAP Java|Fiori Adaptation|Component|Description|Command|
|--|:--:|:--:|:--:|:--:|:--:|:--:|:--:|:--:|:--:|:--:|:--:|--|--|
|Deploy|Common Tasks|✓|✓|✓|✓|✓|✓|✓||✓|✓|Deploy the application using the configuration which is by default stored in the `ui5-deploy.yaml` file.|`sap.ux.appGenerator.launchDeploy`|
|Manage Service Models|Common Tasks|✓|✓||✓|✓|✓||||✓|Sync the local copy of the metadata.xml file with the back end.|`sap.ux.serviceManager.openServiceMgr`|
|Open Adaptation Editor|Common Tasks|||||||||✓||Open the Adaptation Editor to create adaptations.|`sap.ux.adp.openAdaptationEditor`|
|Open Guided Development|Common Tasks|✓|||✓|✓|✓|✓|✓|||Open Guided Development to access guides that explain how to implement certain functionality.|`sap.ux.help.openGuidedDevelopmentFromExplorer`|
|Open Page Map|Common Tasks|✓|✓||✓|✓|✓|✓|✓|||Open the Page Map to see application pages and navigation paths.|`sap.ux.pageMap.showMap`|
|Preview Application|Common Tasks|✓|✓||✓|✓|✓|✓||✓|✓|Select a start script to preview the application.|`sap.ux.pageEditor.previewExternal`|
|Add Card Editor Config|Configuration|✓|||✓|✓|✓|||||Add the configuration for the card generator and tooling.|`npx --yes @sap-ux/create@latest add cards-editor`|
|Add Deploy Config|Configuration|✓|✓|✓|✓|✓|✓|✓||✓|✓|Add deploy configuration.|`sap.ux.appGenerator.launchDeployConfig`|
|Add Mockserver Config|Configuration|✓|✓||✓|✓|✓|||||Add configuration for mockserver middleware.|`npx --yes @sap-ux/create@latest add mockserver-config`|
|Add SAP Fiori Launchpad Config|Configuration|✓|✓||✓|✓|✓|✓|✓|||Add the SAP Fiori launchpad configuration to the application.|`sap.ux.appGenerator.launchFlpConfig`|
|Add Variants Config|Configuration|✓|✓||✓|✓|✓|||||Add the configuration for variants creation.|`sap.ux.applicationModeler.addVariantsConfig`|
|Test deployment|Deploy|✓|✓|✓|✓|✓|✓|✓|✓|✓|✓|Start deployment in test mode.|`npm run deploy-test`|
|Undeploy|Deploy|✓|✓|✓|✓|✓|✓|✓||✓|✓|Remove a deployed artifact from the back end or cloud.|`npm run undeploy`|
|Add Local Annotation File|Manage|||||||||✓||Add a local annotation file to the adaptation project.|`sap.ux.adp.addAnnotationFile`|
|Add OData Service|Manage|||||||||✓||Add an OData service and SAPUI5 model to the adaptation project.|`sap.ux.adp.addODataServiceAndModel`|
|Add SAP Fiori Launchpad Config|Manage|||||||||✓||Add the SAP Fiori launchpad configuration to the application.|`sap.ux.adp.addFlpConfig`|
|Add SAPUI5 Components|Manage|||||||||✓||Add SAPUI5 component usages to the adaptation project.|`sap.ux.adp.addSAPUI5ComponentUsages`|
|Build Application|Manage|✓|✓||✓|✓||||||Build the application. The results are stored in the `dist` folder.|`npm run build`|
|Change minUI5Version|Manage|✓|✓||✓|✓|✓|✓|✓|||Change the minimum version of SAPUI5 that this application requires.|`sap.ux.applicationModeler.changeMinUI5Version`|
|Check Node Modules|Manage|✓|✓||✓|✓|✓|✓|✓|✓||Check node module dependencies for newer versions.|`npm outdated`|
|Check Service|Manage|✓|||✓|✓|✓|||||View service entities and their annotations. Copy annotations to a local annotation file.|`sap.ux.serviceModeler.openFile`|
|Convert Preview Config|Manage|✓|✓||✓|✓|✓|||||Convert the configuration to preview the application with virtual endpoints.|`sap.ux.applicationModeler.convertPreview`|
|Create Archive|Manage|✓|✓|✓|✓|✓|✓|✓|✓|✓|✓|Export the project, excluding the node_modules folder, to a `.zip` file.|`sap.ux.environmentcheck.archiveProject`|
|Manage XML Annotations|Manage|✓|✓||✓|✓|✓||||✓|Create and maintain local XML annotation files.|`sap.ux.serviceManager.openAnnotationFileMgr`|
|Open Card Editor|Manage|✓|||✓|✓|✓|||||Open the card generator for editing.|`npm run start-cards-generator`|
|Open Data Editor|Manage|✓|✓||✓|✓|✓|||||Open the Data Editor to maintain mock data.|`sap.ux.dataEditor.open`|
|Open Documentation|Manage|✓|||✓|✓|✓|✓|✓|||Open the documentation of available manifest and SAPUI5 flexibility properties.|`sap.ux.applicationModeler.showDocu`|
|Replace OData Service|Manage|||||||||✓||Replace the OData service of the adaptation project.|`sap.ux.adp.replaceODataService`|
|Run UI5 Linter|Manage|✓|✓|✓|✓|✓|✓|✓|✓|✓|✓|Check compatibility of your project with SAPUI5 version 2.|`sap.ux.applicationModeler.runUI5Linter`|
|Run Variants Management|Manage|✓|✓||✓|✓|✓|||||Run the configuration for variants creation.|`npm run start-variants-management`|
|Validate Project|Manage|✓|||✓|✓|✓|||||Validate the project and generate a report.|`sap.ux.applicationModeler.validate`|

## Commands in Command Palette
|Category|Title|Command|when|Source|
|--|--|--|--|--|
|Fiori|Restart XML Annotation Language Server|`sap.ux.annoataionModeler.startXmlServer `||packages/annotation-modeler/ide-extension/package.json|
|Fiori|Add Configuration for Variants Creation|`sap.ux.applicationModeler.addVariantsConfig `||packages/application-modeler/ide-extension/package.json|
|Fiori|Add Deployment Configuration|`sap.ux.appGenerator.launchDeployConfig `||packages/application-modeler/ide-extension/package.json|
|Fiori|Add Embedded Configuration for SAP Fiori Launchpad|`sap.ux.applicationModeler.flpEmbeddedMode `||packages/application-modeler/ide-extension/package.json|
|Fiori|Add Reference to SAP Fiori Reusable Libraries|`sap.ux.appGenerator.launchReferenceLib `||packages/application-modeler/ide-extension/package.json|
|Fiori|Add SAP Fiori Launchpad Configuration|`sap.ux.appGenerator.launchFlpConfig `||packages/application-modeler/ide-extension/package.json|
|Fiori|Add SAP Fiori Launchpad Configuration for Adaptation Project|`sap.ux.adp.addFlpConfig `||packages/application-modeler/ide-extension/package.json|
|Fiori|Add SAP System|`sap.ux.applicationModeler.sapSystems.add `|VSCode only|packages/application-modeler/ide-extension/package.json|
|Fiori|Archive Project|`sap.ux.environmentcheck.archiveProject `||packages/application-modeler/ide-extension/package.json|
|Fiori|Change Telemetry Settings|`sap.ux.applicationModeler.changeTelemetrySettings `||packages/application-modeler/ide-extension/package.json|
|Fiori|Change the Minimum SAPUI5 Version|`sap.ux.applicationModeler.changeMinUI5Version `||packages/application-modeler/ide-extension/package.json|
|Fiori|Convert Preview Configuration|`sap.ux.applicationModeler.convertPreview `||packages/application-modeler/ide-extension/package.json|
|Fiori|Delete Application from CAP Project|`sap.ux.applicationModeler.deleteCapApp `||packages/application-modeler/ide-extension/package.json|
|Fiori|Deploy Application|`sap.ux.appGenerator.launchDeploy `||packages/application-modeler/ide-extension/package.json|
|Fiori|Download ADT Deployed App from SAPUI5 ABAP Repository|`sap.ux.appGenerator.appDownloadFromRepo `||packages/application-modeler/ide-extension/package.json|
|Fiori|Enable App-to-App Navigation Preview|`sap.ux.applicationModeler.appToAppNavigation `||packages/application-modeler/ide-extension/package.json|
|Fiori|Generate UI Service|`sap.ux.appGenerator.launchUiServiceGen `||packages/application-modeler/ide-extension/package.json|
|Fiori|Import SAP System|`sap.ux.applicationModeler.sapSystems.import `|VSCode only|packages/application-modeler/ide-extension/package.json|
|Fiori|Migrate Project for Use in SAP Fiori Tools|`sap.ux.applicationModeler.migrateProject `||packages/application-modeler/ide-extension/package.json|
|Fiori|Open Adaptation Editor|`sap.ux.adp.openAdaptationEditor `||packages/application-modeler/ide-extension/package.json|
|Fiori|Open Adaptation Project Generator|`sap.ux.adp.openAdaptationProjectGenerator `||packages/application-modeler/ide-extension/package.json|
|Fiori|Open Application Generator|`sap.ux.appGenerator.launch `||packages/application-modeler/ide-extension/package.json|
|Fiori|Open Application Info|`sap.ux.application.info `||packages/application-modeler/ide-extension/package.json|
|Fiori|Open CF Application Router Generator|`sap.ux.appGenerator.launchDeployment `||packages/application-modeler/ide-extension/package.json|
|Fiori|Open Data Editor|`sap.ux.dataEditor.open `||packages/application-modeler/ide-extension/package.json|
|Fiori|Open Environment Check|`sap.ux.environmentcheck.open `||packages/application-modeler/ide-extension/package.json|
|Fiori|Open Reusable Library Generator|`sap.ux.appGenerator.launchReuseLibGen `||packages/application-modeler/ide-extension/package.json|
|Fiori|Open Run Configurations|`sap.ux.applicationModler.launchConfig `||packages/application-modeler/ide-extension/package.json|
|Fiori|Preview Application|`sap.ux.pageEditor.previewExternal `||packages/application-modeler/ide-extension/package.json|
|Fiori|Refresh Application Modeler View|`sap.ux.applicationModeler.configExplorer.refresh `||packages/application-modeler/ide-extension/package.json|
|Fiori|Run UI5 Linter|`sap.ux.applicationModeler.runUI5Linter `||packages/application-modeler/ide-extension/package.json|
|Fiori|Show Output Channel|`sap.ux.applicationModeler.showOutputChannel `||packages/application-modeler/ide-extension/package.json|
|Fiori|Show Page Editor|`sap.ux.pageMap.showPageEditor `||packages/application-modeler/ide-extension/package.json|
|Fiori|Show Page Map|`sap.ux.pageMap.showMap `||packages/application-modeler/ide-extension/package.json|
|Fiori|Show Release Notes|`sap.ux.fioriTools.showReleaseNotes `||packages/application-modeler/ide-extension/package.json|
|Fiori|Show SAP System Details|`sap.ux.applicationModeler.sapSystems.show `|VSCode only|packages/application-modeler/ide-extension/package.json|
|Fiori|Validate Project|`sap.ux.applicationModeler.validate `||packages/application-modeler/ide-extension/package.json|
|SAP Fiori AI|Clear Chat History|`sap.ux.fiori.tools.ai.chatView.clearChatMessages `||packages/fiori-ai/extensions/chat/ide-extension/package.json|
|SAP Fiori AI|Export Chat History|`sap.ux.fiori.tools.ai.chatView.exportChatMessages `||packages/fiori-ai/extensions/chat/ide-extension/package.json|
|SAP Fiori AI|Open ReadMe|`sap.ux.fiori.tools.ai.chatView.openReadMe `||packages/fiori-ai/extensions/chat/ide-extension/package.json|
|Fiori Tools AI|Launch the Project Accelerator|`sap.ux.help.fiori.ai.launchProjectAccelerator `|showBetaFeatures && isEnabledFioriAI|packages/help/ide-extension/package.json|
|Fiori|Open Guided Development|`sap.ux.help.openGuidedDevelopment `||packages/help/ide-extension/package.json|
|Fiori|Open Guided Development to the Side|`sap.ux.help.openGuidedDevelopmentToTheSide `||packages/help/ide-extension/package.json|
|Fiori|Request New Guide|`sap.ux.help.openGuidedDevelopmentRequestNewGuide `||packages/help/ide-extension/package.json|
|Fiori|Open Annotation File Manager|`sap.ux.serviceManager.openAnnotationFileMgr `||packages/service-modeler/ide-extension/package.json|
|Fiori|Open Service Manager|`sap.ux.serviceManager.openServiceMgr `||packages/service-modeler/ide-extension/package.json|
|Fiori|Open Service Modeler|`sap.ux.serviceModeler.openFileCmdPalatte `||packages/service-modeler/ide-extension/package.json|
|Fiori|Open Service Modeler to the Side|`sap.ux.serviceModeler.openFileToTheSide `||packages/service-modeler/ide-extension/package.json|
|Fiori|Open Walkthrough|`sap.ux.applicationModeler.walkthrough.launch `||packages/application-modeler/ide-extension/package.json|

tools-suite.md - Chunk 1

# Commands in SAP Fiori Tools

# Commands in SAP Fiori Tools

<br>

## Commands in Application Info page
|Feature|Group|SAP Fiori elements|SAPUI5 freestyle|Fiori Reuse|v2|v4|EDMX Backend|CAP Node.js|


# @sap/ux-ui5-tooling

The SAP Fiori Tools - UI5 Tooling contains a selection of custom [middlewares](https://sap.github.io/ui5-tooling/pages/extensibility/CustomServerMiddleware/) that can be used with the command `ui5 serve` as well as custom [tasks](https://sap.github.io/ui5-tooling/pages/extensibility/CustomTasks/) that can be used with the command `ui5 build`.
Furthermore, the module expose the cli `fiori` offering e.g. the [`fiori run`](#run) command is a wrapper of the `ui5 serve` commands and provides some additional parameters as well as `fiori add deploy-config` and `fiori add flp-config` to extend an existing project.

**IMPORTANT**:
- For more information about migration to the latest `@ui5/cli`, see [here](https://sap.github.io/ui5-tooling/stable/).
- Starting with version `1.17.6`, the minimum required Node.js version is 20.19.2 or higher!

ux-ui5-tooling-README.md - Chunk 1


# [**Middlewares**](#middlewares)

SAP Fiori tools use the capabilities of custom middlewares to start and preview SAP Fiori elements or SAPUI5 freestyle applications, e.g. to enable auto refresh, to switch the version of SAPUI5 sources or to serve static resources. Starting with version `1.3.0` the behaviour of the preview of the SAP Fiori applications has changed. Now the persistent iAppState is ignored in order to have the source code changes always apply when application is refreshed. If you want to enable the iAppState then you need to add the URL parameter `fiori-tools-iapp-state=true` to the browser URL, e.g. `http://localhost:8080/test/flpSandbox.html?fiori-tools-iapp-state=true#masterDetail-display`.

ux-ui5-tooling-README.md - Chunk 2


## [**1. Application Reload**](#1-application-reload)

The application reload middleware allows developers to preview SAP Fiori applications while developing/configuring them. Whenever a file relevant for the SAP Fiori application is changed, the reload middleware will refresh the application preview.

#### Example Configuration

Executing `npx fiori run` in your project with the configuration below in a `ui5.yaml` would start the application reload middleware with its default settings.

```
server:
  customMiddleware:
  - name: fiori-tools-appreload
    afterMiddleware: compression
```

#### Configuration options

The application reload middleware does not require any configuration parameters. However, there are optional parameters that can be used if the project structure differs from standard SAP Fiori projects.

#### path

- `<string>` (default: `webapp`)
Path that is to be watched. By default, the standard SAPUI5 `webapp` folder is used

#### ext

- `<string>` (default: `html,js,ts,json,xml,properties,change,variant,appdescr_variant,ctrl_variant,ctrl_variant_change,ctrl_variant_management_change`)
Change this parameter to select a custom set of file extensions that are to be watched

#### port

- `<int>` (default: `35729`)
Port to be used to communicate file system changes

#### debug

- `<boolean>` (default: `false`)
Set this parameter to get more log information.

ux-ui5-tooling-README.md - Chunk 3


## [**2. Proxy**](#2-proxy)

The proxy middleware provides you with the capabilities to connect to different back-end systems or to switch the SAPUI5 version of the application. The proxy is based on the [@sap-ux/ui5-proxy-middleware](https://www.npmjs.com/package/@sap-ux/ui5-proxy-middleware) for proxying the UI5 sources (starting with version `1.6.0`) and the [@sap-ux/backend-proxy-middleware](https://www.npmjs.com/package/@sap-ux/backend-proxy-middleware) for connecting to different back-end systems (starting with version `1.6.7`). Both `@sap-ux/ui5-proxy-middleware` and `@sap-ux/backend-proxy-middleware` are based on the [http-proxy-middleware](https://www.npmjs.com/package/http-proxy-middleware).

### Configuration Examples

#### [Connecting to a back-end system](#connecting-to-a-back-end-system)

Executing `npx fiori run` in your project with the configuration below in the `ui5.yaml` file would forward any request starting with the `path` parameter to the provided back-end `url`.

```
- name: fiori-tools-proxy
  afterMiddleware: compression
  configuration:
    backend:
    - path: /sap
      url: https://my.backend.com:1234
```

#### [Using connectPath for credential retrieval](#using-connectpath-for-credential-retrieval)

When credentials are saved against a full service URL (for example, `https://my.backend.com:1234/sap/opu/odata/example/service`) rather than just the base URL, you need to specify the `connectPath` parameter to ensure the correct credentials are retrieved. The `connectPath` should match the path portion of the URL against which the credentials were saved.

```yaml
- name: fiori-tools-proxy
  afterMiddleware: compression
  configuration:
    backend:
    - path: /sap
      url: https://my.backend.com:1234
      connectPath: /sap/opu/odata/UI5/ABAP_REPOSITORY_SRV
```

**When to use `connectPath`:**
- Your credentials are stored in the SAP System configuration with a full service URL including the path
- You need to connect to a specific service endpoint for authentication
- The stored system URL differs from the base server URL

**Note:** If credentials are saved against the base URL only (e.g., `https://my.backend.com:1234`), the `connectPath` parameter is not needed.

#### [Connecting to a back-end system with destination](#connecting-to-a-back-end-system-with-destination)

If the back-end is hidden behind a destination then you can also provide the `destination` in the configuration.

```
- name: fiori-tools-proxy
  afterMiddleware: compression
  configuration:
    backend:
    - path: /sap
      url: https://my.backend.com:1234
      destination: my_backend
```
#### [Connecting to a back-end system with destination and principal propagation](#connecting-to-a-back-end-system-with-destination-and-principal-propagation)

If the back-end destination is configured to use principal propagation, then in some cases the requests might fail. If this occurs then you will need to set the optional property `xfwd` to `true`. This will add the x-forwared headers to the proxy requests.

```
- name: fiori-tools-proxy
  afterMiddleware: compression
  configuration:
    backend:
    - path: /sap
      url: https://my.backend.com:1234
      destination: my_backend
      xfwd: true
```
#### [Connecting to multiple back-end systems](#connecting-to-multiple-back-end-systems)
You can also connect to multiple back-end systems like this.

```
- name: fiori-tools-proxy
  afterMiddleware: compression
  configuration:
    backend:
    - path: /northwind
      url: https://my.backend_2.com:1234
    - path: /sap
      url: https://my.backend.com:1234
```
#### [Connecting to the SAP Business Technology Platform](#connecting-to-the-sap-business-technology-platform)
If you want to connect to an ABAP Environment on SAP Business Technology Platform then you will need to set the optional property `scp` to `true`. For any other target, remove this property or set it to `false`.

```
- name: fiori-tools-proxy
  afterMiddleware: compression
  configuration:
    backend:
    - path: /sap
      url: https://my.steampunk.com:1234
      scp: true
```

#### [Connecting to the SAP Business Accelerator Hub](#connecting-to-the-sap-business-accelerator-hub)
If you want to connect to the SAP Business Accelerator Hub then you will need to set the optional property `apiHub` to `true`, and set the corresponding `path` and `url`, e.g.

```
- name: fiori-tools-proxy
  afterMiddleware: compression
  configuration:
    backend:
    - path: /s4hanacloud
      url: https://api.sap.com
      apiHub: true
```
#### [Proxying WebSockets](#proxying-websockets)
If you want the proxy to handle also WebSockets, then you need to set the optional property `ws` to `true`, e.g.

```
- name: fiori-tools-proxy
  afterMiddleware: compression
  configuration:
    backend:
    - path: /sap
      url: https://my.backend.com:1234
      ws: true
```
**Note: proxying WebSockets is currently not supported in SAP Business Application Studio.**

#### [Changing the path to which a request is proxied](#changing-the-path-to-which-a-request-is-proxied)
Let's that you want to configure the proxy to send requests from a certain path `/services/odata` to a destination with a specified entry path `/my/entry/path`. Then you need to do the following:

```
- name: fiori-tools-proxy
  afterMiddleware: compression
  configuration:
    backend:
    - path: /services/odata
      pathReplace: /my/entry/path
      url: https://my.backend.com:1234
      destination: my_backend
```

#### [Add Query Parameters](#add-query-parameters)
Add query parameters to the proxied request by using the `params` configuration option, e.g.

```
- name: fiori-tools-proxy
  afterMiddleware: compression
  configuration:
    backend:
    - path: /sap
      url: https://my.backend.com:1234
      params:
        saml2: 'disabled'
```

#### [Providing Proxy Configuration](#providing-proxy-configuration)
By the default the `fiori-tools-proxy` will read the proxy configuration from the Node.js environment variables `proxy`, `https-proxy` and `noproxy`. If those variables are not set, then you can also provide the proxy configuration in the `ui5.yaml` file. **Please note: if you want to exclude any domains from the proxy then you will need to set the `noproxy` variable, e.g. `npm config set noproxy "sap.com"`**.

```
- name: fiori-tools-proxy
  afterMiddleware: compression
  configuration:
    proxy: https://myproxy.com:8443
    backend:
    - path: /sap
      url: https://my.backend.com:1234

```
#### [Ignoring Certificate Errors](#ignoring-certificate-errors)
By default, the `fiori-tools-proxy` will verify the SSL certificates and will throw an error if the validation fails. One can set the parameter `ignoreCertErrors: true` to ignore the certificate errors. Setting this parameter to `true` also allows the usage of self-signed certificates.

```
- name: fiori-tools-proxy
  afterMiddleware: compression
  configuration:
    ignoreCertErrors: true
    backend:
    - path: /sap
      url: https://my.backend.com:1234

```

**Note**: The singular form `ignoreCertError` is also supported for backward compatibility but is deprecated. When using the singular form, a deprecation warning will be displayed encouraging migration to `ignoreCertErrors` (plural).
#### [Providing Credentials](#providing-credentials)
##### Local Testing
For local testing the logon credentials to a backend system need to be provided using the secure storage of the operating system.

Configure the needed connections here: `SAP Fiori -> SAP SYSTEMS`

##### CI Scenario
In the CI scenario the logon credentials to a backend system need to be provided by the two environment variables

`FIORI_TOOLS_USER` and `FIORI_TOOLS_PASSWORD`

#### [Backend configuration options](#backend-configuration-options)

Here is the full list of the available configuration options for the backend proxy.
- `forward` (available with version 1.8.5): url string to be parsed with the url module
- `ws` (available with version 1.1.5): true/false: if you want to proxy websockets
- `xfwd` (available with version 1.1.9): true/false, adds x-forward headers
- `toProxy` (available with version 1.8.5): true/false, passes the absolute URL as the path (useful for proxying to proxies)
- `prependPath` (available with version 1.8.5): true/false, Default: true - specify whether you want to prepend the target's path to the proxy path
- `ignorePath` (available with version 1.8.5): true/false, Default: false - specify whether you want to ignore the proxy path of the incoming request (note: you will have to append / manually if required)
- `localAddress` (available with version 1.8.5): Local interface string to bind for outgoing connections
- `changeOrigin` (available with version 1.8.5): true/false, Default: true - changes the origin of the host header to the target URL
- `params` (available with version 1.23.0): object, adds query parameters to the proxied request
- `preserveHeaderKeyCase` (available with version 1.8.5): true/false, Default: false - specify whether you want to keep letter case of response header key
- `auth` (available with version 1.8.5): Basic authentication i.e. 'user:password' to compute an Authorization header
- `hostRewrite` (available with version 1.8.5): rewrites the location hostname on (301/302/307/308) redirects
- `autoRewrite` (available with version 1.8.5): rewrites the location host/port on (301/302/307/308) redirects based on requested host/port. Default: false
- `protocolRewrite` (available with version 1.8.5): rewrites the location protocol on (301/302/307/308) redirects to 'http' or 'https'. Default: null
- `cookieDomainRewrite` (available with version 1.8.5): rewrites domain of set-cookie headers. Possible values:
  - false (default): disables cookie rewriting
  - String: new domain, for example cookieDomainRewrite: "new.domain". To   remove the domain, use cookieDomainRewrite: ""
  - Object: mapping of domains to new domains, use "*" to match all domains
- `cookiePathRewrite` (available with version 1.8.5): rewrites path of set-cookie headers. Possible values:
  - false (default): disable cookie rewriting
  - String: new path, for example cookiePathRewrite: "/newPath/". To remove the path, use cookiePathRewrite: "". To set path to root use cookiePathRewrite: "/"
  - Object: mapping of paths to new paths, use "*" to match all paths.
- `headers` (available with version 1.8.5): object, adds request headers
- `proxyTimeout` (available with version 1.8.5): timeout (in millis) when proxy receives no response from target
- `timeout` (available with version 1.8.5): timeout (in millis) for incoming requests
- `followRedirects` (available with version 1.8.5): true/false, Default: false - specify whether you want to follow redirects

#### [UI5](#ui5)

The proxy configuration contains also the configuration for loading the SAPUI5 resources when previewing the application, e.g.

```
- name: fiori-tools-proxy
  afterMiddleware: compression
  configuration:
    ui5:
      path:
      - /resources
      - /test-resources
      url: https://ui5.sap.com
```

By using the proxy configuration one can also change the SAPUI5 version, which is used to preview the application. You can use the `version` parameter to change the SAPUI5 version as follows:

```
- name: fiori-tools-proxy
  afterMiddleware: compression
  configuration:
    ui5:
      path:
      - /resources
      - /test-resources
      url: https://ui5.sap.com
      version: 1.102.7
```

Starting with `ux-ui5-tooling` version `1.4.7`, if the `version` property is not set in the `ui5.yaml`, then the `minUI5Version` from `manifest.json` will be used for the application preview. If the `version` property is set, but it is empty, then the `latest` SAPUI5 version from https://ui5.sap.com will be used for the application preview. For any other case the value of the `version` property will be used for the application preview.

Starting with `ux-ui5-tooling` version `1.7.1` a check for the SAPUI5 version of the application was added, which checks if the version is availble on the SAPUI5 SDK. If not, then the nearest, highest patch, version is used instead.

**Note:** all UI5 requests are routed through the proxy. Sometimes this can cause performance issues. If you don't want route the UI5 requests through the proxy, then you can set parameter `directLoad: true`. This will inject the UI5 url in the HTML file of the application and thus the UI5 libs will be loaded directly. This feature is only available for files served from the local file system (not for virtual endpoints). The filename must adhere to the default filenames: `/index.html`, `/test/flpSandbox.html`, `/test/flpSandboxMockServer.html` or `/test/flp.html`.

```
- name: fiori-tools-proxy
  afterMiddleware: compression
  configuration:
    ui5:
      path:
      - /resources
      - /test-resources
      url: https://ui5.sap.com
      directLoad: true
```

Starting with version `1.6.0` one can use the following syntax for proxying different UI5 requests to different URLs, e.g.

```
- name: fiori-tools-proxy
  afterMiddleware: compression
  configuration:
    ui5:
      paths:
        - path: /resources
          url: https://ui5.sap.com
        - path: /test-resources
          url: https://ui5.sap.com
      version: '1.100.1'
```

Starting with version `1.20.0` one can use the following syntax to load UI5 sources from a different host, e.g.

**NOTE: using `pathReplace` will not consider a specified UI5 version. If a specific UI5 version is needed, then it needs to be part of the `pathReplace`.**

```Yaml
server:
  customMiddleware:
  - name: ui5-proxy-middleware
    afterMiddleware: compression
    configuration:
      ui5:
      - path: /resources
        url: https://my.backend.example:1234
        pathReplace: /sap/public/ui5/resources
```
```Yaml
server:
  customMiddleware:
  - name: fiori-tools-proxy
    afterMiddleware: compression
    configuration:
      ui5:
        paths:
          - path: /resources
            url: https://ui5.sap.com
          - path: /test-resources
            url: https://my.backend.example:1234
            pathReplace: /sap/public/ui5/resources
```

ux-ui5-tooling-README.md - Chunk 4


## [**3. Serve Static**](#3-serve-static)

The serve static middleware provides the capability to serve any static resources locally from your machine. E.g. you can serve SAPUI5 locally or any other resources.

### [Example Configuration for serving locally SAPUI5](#example-configuration-for-serving-locally-ui5)

**Pre-requisites:**
SAPUI5 SDK version is downloaded and extracted locally on the machine. One can download UI5 resources from <https://tools.hana.ondemand.com/#sapui5>

Executing `npx fiori run` in your project with the configuration below in a `ui5.yaml` file would serve the UI5 sources from your machine. Any request starting with the `path` parameter will be forwarded to the local path provided in the `src` parameter.

```
server:
  customMiddleware:
  - name: fiori-tools-servestatic
    afterMiddleware: compression
    configuration:
      paths:
        - path: /resources
          src: "Path/To/SAPUI5-SDK"
        - path: /test-resources
          src: "Path/To/SAPUI5-SDK"
```

### [Example Configuration for serving any resources locally](#example-configuration-for-serving-any-resources-locally)
Executing `npx fiori run` in your project with the configuration below in a `ui5.yaml` file would serve resources from your machine. Any request starting with the `path` parameter will be forwarded to the local path provided in the `src` parameter.

```
server:
  customMiddleware:
  - name: fiori-tools-servestatic
    afterMiddleware: compression
    configuration:
      paths:
        - path: /images
          src: "Path/To/images"
        - path: /libs
          src: "Path/To/libs"
```

### [Example configuration for mocking the User API Service from @sap/approuter](#example-configuration-for-mocking-the-user-api-service-from-sapapprouter)
If you are using the [User API Service](https://www.npmjs.com/package/@sap/approuter#user-api-service) from `@sap/approuter` in your application, then you can mock by providing the following configuration.

```
server:
  customMiddleware:
  - name: fiori-tools-servestatic
    afterMiddleware: compression
    configuration:
      paths:
        - path: /userapi/currentUser
          src: "Path/To/UserJson/user.json"
          index: false
          fallthrough: false
          redirect: false
```
whereas the `user.json` can look like this e.g.

```
{
   "firstname": "John",
   "lastname": "Doe",
   "email": "john.doe@example.com",
   "name": "john.doe@example.com",
   "displayName": "John Doe (john.doe@example.com)",
   "scopes": "openid,user_attributes,uaa.user"
}
```

### [Configuration options](#configuration-options-1)
Additionaly you can specify any of the configuration options (excluding `setHeaders`!) of the [serve-static](https://www.npmjs.com/package/serve-static) middleware.

E.g. you can set `fallthrough: false`, which will cause the middleware to return 404 error, when it can't find a file on the local system:

```
server:
  customMiddleware:
  - name: fiori-tools-servestatic
    afterMiddleware: compression
    configuration:
      paths:
        - path: /resources
          src: "Path/To/SAPUI5-SDK"
        - path: /test-resources
          src: "Path/To/SAPUI5-SDK"
      fallthrough: false
```

Alternatively you can set e.g. `fallthrough: false` only for specific requests:

```
server:
  customMiddleware:
  - name: fiori-tools-servestatic
    afterMiddleware: compression
    configuration:
      paths:
        - path: /resources
          src: "Path/To/SAPUI5-SDK"
          fallthrough: false
        - path: /test-resources
          src: "Path/To/SAPUI5-SDK"
```

ux-ui5-tooling-README.md - Chunk 5