Serving Fiori UIs

    CAP provides out-of-the-box support for SAP Fiori Elements frontends.

    This guide explains how to add one or more SAP Fiori Elements apps to a CAP project, how to add SAP Fiori Elements annotations to respective service definitions, etc. In the following sections, we are always referring to SAP Fiori Elements when mentioning Fiori.

    Learn more about developing SAP Fiori Elements and OData V4 (since 1.84.)


    SAP Fiori Preview

    When starting your application, for example, using cds watch, there is an SAP Fiori preview for development purposes. You can use this to see the effect of annotations in a quick roundtrip. Be aware, that this is just a preview. Differences between the preview and an implemented SAP Fiori application can occur.

    This is only active using the development profile.

    To enable this preview also for the production profile add the following configuration to your project’s package.json: cds.features.fiori_preview:true If you add this to your cdsrc.json omit the cds section.

    Adding SAP Fiori Apps to CAP Projects

    As showcased in cap/samples, SAP Fiori apps should be added as sub folders to the app/ of a CAP project. Each sub folder constitutes an individual SAP Fiori application, with local annotations, manifest.json, etc. So, a typical folder layout would look like this:

    Folder / Sub Folder Description
    app/ all SAP Fiori apps should go in here
        browse/ SAP Fiori app for end users
        orders/ SAP Fiori app for order management
        admin/ SAP Fiori app for admins
        index.html For sandbox tests
    srv/ all services
    db/ domain models, and db stuff

    Using SAP Fiori Tools

    The SAP Fiori tools provide advanced support for adding SAP Fiori apps to existing CAP projects as well as a wealth of productivity tools, for example to add SAP Fiori annotations or graphical modeling and editing. They can be used locally in Visual Studio Code (VS Code) or in SAP Business Application Studio.

    Learn more about how to install SAP Fiori tools.

    By Copying from cap/samples

    For example, you can copy the SAP Fiori apps from cap/samples as a template and modify the content as appropriate.

    By Copying SAP Fiori Elements Sample Service

    This is a sample to create an incident management app with SAP Fiori Elements for OData V4.

    Adding SAP Fiori Annotations

    The main content to be added is service definitions annotated with information how to render respective data.

    What Are SAP Fiori Annotations?

    SAP Fiori elements apps are generic frontends, which construct and render the pages and controls based on annotated metadata documents. The annotations provide semantic annotations used to render such content, for example:

    annotate CatalogService.Books with @(
      UI: {
        SelectionFields: [ ID, price, currency_code ],
        LineItem: [
          {Value: title},
          {Value: author, Label:'{i18n>Author}'},
          {Value: price},
          {Value: currency.symbol, Label:' '},

    Find this source and many more in cap/samples. Learn more on OData Annotations in CDS.

    Where to Put Them?

    While CDS in principle allows to add such annotations everywhere in your models, we recommend putting them in separate .cds files placed in your ./app/* folders, for example, as follows.

    ./app  #> all your fiori annotations should go here, for example:
          fiori-service.cds #> annotating ../srv/admin-service.cds
          fiori-service.cds #> annotating ../srv/cat-service.cds
    ./srv  #> all service definitions should stay clean in here:

    See this also in cap/samples/fiori.

    Reasoning: This recommendation essentially follows best practices and guiding principles of Conceptual Modeling and Separation of Concerns.

    Maintaining Annotations

    Maintaining OData annotations in .cds files is accelerated by the SAP Fiori tools - CDS OData Language Server @sap/ux-cds-odata-language-server-extension comprised in SAP CDS language support plugin. It assists you with adding and editing OData annotations in CDS syntax with:

    • Code Completion
    • Validation against the OData vocabularies and project metadata
    • Navigation to the referenced annotations
    • Quick view of vocabulary information
    • Internationalization support

    These assisting features are provided for OData annotations in CDS syntax and can’t be used yet for the core data services common annotations.

    @sap/ux-cds-odata-language-server-extension module doesn’t require any manual installation. The latest version is fetched by default from as indicated in the user preference setting CDS > Contributions: Registry.

    Learn more about the CDS extension for VS Code.

    Code Completion

    CDS OData Language Server provides a list of context-sensitive suggestions based on the service metadata and OData vocabularies. You can use it to choose OData annotation terms, their properties, and values from the list of suggestions in annotate directives applied to service entities and entity elements. See annotate directives for more details.

    Using Code Completion

    To trigger the code completion, press Ctrl (Windows), space (Mac). The list of suggested values is displayed.

    You can filter the list of suggested values by typing more characters.

    Navigate to the desired value using up or down arrows or your mouse. Accept the highlighted value using Enter key or a mouse click. Use code completion to add and change individual values (word-based completion) and to add small code blocks containing annotation structures along with mandatory properties (micro-snippets). In an active code snippet, you can use Tab to quickly move to the next tab stop.

    Example: Annotating Service Entities

    (cursor position indicated by |)

    1. Place cursor in the annotate directive for a service entity, for example annotate Foo.Bar with ; and trigger the code completion.

    2. Type u to filter the suggestions and choose {} UI. Micro-snippet @UI : {|} is inserted: annotate Foo.Bar with @UI : {|};

    3. Use the code completion again to add an annotation term from UI vocabulary, in this example SelectionFields. Micro snippet for this annotation is added and the cursor is placed right after the term name letting you define a qualifier: annotate Foo.Bar with @UI : {SelectionFields | : []};

    4. Press the Tab key to move the cursor to the next tab stop and use the code completion again to add values. As UI.SelectionFields annotation is a collection of entity elements (entity properties), all elements of the annotated entity are suggested.

      To choose an element of an associated entity, first select the corresponding association from the list and type . (period). Elements of associated entity are suggested.

      You can add multiple values separated by comma.

          annotate Foo.Bar with @UI : { SelectionFields : [
              description, assignedIndividual.lastName|
    5. Add a new line after , (comma) and use the code completion again to add another annotation from UI vocabulary, such as LineItem. Line item is a collection of DataField records. To add a record, select the record type you need from the completion list.

           annotate Foo.Bar with @UI : { SelectionFields : [
               description, assignedIndividual.lastName
               LineItem : [
                       Value : |,

      For each record type, two kinds of micro-snippets are provided: one containing only mandatory properties and one containing all properties defined for this record (full record). Usually you need just a subset of properties. So, you either select a full record and then remove the properties you don’t need, or add the record containing only required properties and then add the remaining properties.

    6. Use code completion to add values for the annotation properties.

          annotate Foo.Bar with @UI : { SelectionFields : [
              description, assignedIndividual.lastName
              LineItem : [
                      Value : description,
                      Target :  'assignedIndividual/@Communication.Contact',

      To add values pointing to annotations defined in another CDS source, you must reference this source with using directive. See The using Directive for more details.

    Example: Annotating Entity Elements

    (cursor position indicated by |)

    1. Place the cursor in the annotate directive, for example annotate Foo.Bar with {|};, add a new line and trigger the code completion. You get the list of entity elements. Choose the one you want to annotate.

          annotate Foo.Bar with {
    2. Press Space and use the code completion again and choose {} UI. Micro-snippet @UI : {|} is inserted:

          annotate Foo.Bar with {
              code @UI : { | }
    3. Trigger completion again and choose an annotation term from UI vocabulary, in this example: Hidden.

          annotate Foo.Bar with {
              code @UI : {Hidden : |}
    4. Press the Tab key to move the cursor to the next tab stop and use the code completion again to add the value. As UI.Hidden annotation is of Boolean type, the values true and false is suggested:

          annotate Foo.Bar with {
              code @UI : {Hidden : false }


    CDS OData Language Server server validates OData annotations in .cds files against the service metadata and OData vocabularies. It also checks provided string content for language-dependent annotation values and warns you if the format doesn’t match the internationalization (i18n) key reference. It makes you aware that this string is hard-coded and won’t change based on the language setting in your application. See Internationalization support for more details.

    Validation is performed when you open a .cds file and then is retriggered with each change to the relevant files.

    You can view the diagnostic messages by hovering over the highlighted part in the annotation file or by opening the problems panel. Click on the message in problems panel to navigate to the related place in the annotation file.

    If an annotation value points to the annotation defined in another CDS source, you must reference this source with using directive to avoid warnings. See The using Directive for more details.

    CDS OData Language Server enables quick navigation to the definition of referenced annotations. For example, if your annotation file contains a DataFieldForAnnotation record referencing an Identification annotation defined in the service file, you can view which file it’s defined in and what fields or labels this annotation contains. You can even update the Identification annotation or add comments.

    You can navigate to the referenced annotation using Peek Definition and Go To Definition features.

    If the referenced annotation is defined in another CDS source, you must reference this source with using directive to enable the navigation. See The using Directive for more details.

    Peek Definition

    Peek Definition lets you preview and update the referenced annotation without switching away from the code that you’re writing. It’s triggered when your cursor is inside the referenced annotation value.

    • Using keyboard: press Alt + F12 (Windows), Option F12 (Mac)
    • Using mouse: right-click and select Peek Definition If an annotation is defined in multiple sources, all these sources are listed. You can select which one you would like to view or update. Annotation layering isn’t considered.

    Go to Definition

    Go To Definition lets you navigate to the source of the referenced annotation and opens the source file scrolled to the respective place in a new tab. It’s triggered when your cursor is inside the referenced annotation value.

    Place your text cursor inside the path referencing the annotation term segment or translatable string value and trigger Go to Definition:

    • Using keyboard: press F12 in VS Code, Ctrl + F11 in SAP Business Application Studio
    • Using mouse: right-click and select Go To Definition
    • Using keyboard and mouse: Ctrl + mouse click (Windows), CMD + mouse click (Mac)

    If an annotation is defined in multiple sources, Peek definition listing these sources will be shown instead. Annotation layering isn’t considered.

    Documentation (Quick Info)

    Annotation language server provides a quick information for annotation terms, record types, and properties used in the annotation file or provided as suggestions in code completion lists. This information is retrieved from the respective OData vocabularies and can provide answers to the following questions:

    • What is the type and purpose of the annotation term / record type / property?
    • What targets can the annotation term apply to?
    • Is the annotation term / record type / property experimental? Is it deprecated?
    • Is this annotation property mandatory or optional?

    The exact content depends on the availability in OData vocabularies.

    To view the quick info for an annotation term, record type or property used in the annotation file, hover your mouse over it. The accompanying documentation is displayed in a hover window, if provided in the respective OData vocabularies.

    To view the quick info for each suggestion in the code completion list, either press Ctrl + Space (Windows), CMD + Space (Mac) or click the info icon. The accompanying documentation for the suggestion expands to the side. The expanded documentation stays so and updates as you navigate the list. You can close this by pressing Ctrl + Space / CMD + Space again or by clicking on the close icon.

    Internationalization Support

    When you open an annotation file, all language-dependent string values are checked against the file. Each value that doesn’t represent a valid reference to the existing text key in the file, is indicated with a warning. A Quick Fix action is suggested to generate a text key in i18n file and substitute your string value with the reference to that entry.

    Prefer @title and @description

    Influenced by JSON Schema, CDS supports the common annotations @title and @description, which are mapped to corresponding OData annotations as follows:

    CDS JSON Schema OData
    @title title @Common.Label
    @description description @Core.Description

    It’s recommended to prefer these annotations over the OData ones in protocol-agnostic data models and service models, for example:

    annotate my.Books with { //...
       title @title: 'Book Title';
       author @title: 'Author ID';

    Prefer @readonly, @mandatory, …

    CDS supports @readonly as a [common annotation, which translates to respective OData annotations from the @Capabilities vocabulary. We recommend using the former for reasons of conciseness and comprehensibility as shown in this example:

    @readonly entity Foo {   // entity-level
      @readonly foo : String // element-level

    is equivalent to:

    entity Foo @(Capabilities:{
      // entity-level
      InsertRestrictions.Insertable: false,
      UpdateRestrictions.Updatable: false,
      DeleteRestrictions.Deletable: false
    }) {
      // element-level
      @Core.Computed foo : String

    Similar recommendations apply to @mandatory and others → see Common Annotations.

    Draft-Based Editing

    SAP Fiori supports edit sessions with draft states stored on the server, so users can interrupt and continue later on, possibly from different places and devices. CAP as well as SAP Fiori Elements provide out-of-the-box support for Drafts as outlined in the following sections. It’s recommended to always use Draft when your application needs data input by end users.

    For details and guidelines about that, see SAP Fiori Design Guidelines for Draft.

    Find a working end-to-end version in cap/samples/fiori.

    Enabling Draft with @odata.draft.enabled

    To enable draft for an entity exposed by a service, simply annotate it with @odata.draft.enabled as in this example:

    annotate AdminService.Books with @odata.draft.enabled;

    See that live in cap/samples.

    You can’t project from draft-enabled entities, as annotations are propagated. Either enable the draft for the projection and not the original entity or disable the draft on the projection using @odata.draft.enabled: null.

    Enabling Draft for Localized Data

    Additionally annotate the underlying base entity in the base model with @fiori.draft.enabled to also support drafts for localized data:

    annotate sap.capire.bookshop.Books with @fiori.draft.enabled;

    Background: SAP Fiori Drafts requires single keys of type UUID, which isn’t the case by default for the automatically generated _texts entities (→ see the Localized Data guide for details). The annotation @fiori.draft.enabled tells the compiler to add such a technical primary key element named ID_texts.

    See that live in cap/samples.

    Validating Drafts

    You can add custom handlers to add specific validations as usual. In addition, in case of draft, you can register handlers to the PATCH events to validate input per field, during the edit session, as follows.

    … in Java

    You can add your validation logic in before operation event handlers. Specific events for draft operations exist, see Java > Fiori Drafts > Editing Drafts for more details.

    … in Node.js

    You can add your validation logic in the before operation handler for the CREATE or UPDATE event (as in the case of nondraft implementations) or on the SAVE event (specific to drafts only):

    srv.before ('CREATE','Books', (req)=>{ ... }) // run before create
    srv.before ('UPDATE','Books', (req)=>{ ... }) // run before create
    srv.before ('SAVE','Books', (req)=>{...})     // run at final save only

    In addition, you can add field-level validations on the individual PATCH events:

    srv.before ('PATCH','Books', (req)=>{...}) // run during editing

    These get triggered during the draft edit session whenever the user tabs from one field to the next, and can be used to provide early feedback.

    Value Help Support

    In addition to supporting the standard @Common.ValueList annotations as defined in the OData Vocabularies, CAP provides advanced convenient support for Value Help as understood and supported by SAP Fiori.

    Convenience option @cds.odata.valuelist

    Simply add annotation @cds.odata.valuelist to an entity, and all Associations targeting this entity will automatically receive Value Lists in SAP Fiori clients. For example:

    entity Currencies {}
    service BookshopService {
       entity Books { //...
          currency : Association to Currencies; 

    Pre-Defined Types in @sap/cds/common

    The reuse types in @sap/cds/common already have this added to base types and entities, so all uses automatically benefit from this. This is an effective excerpt of respective definitions in @sap/cds/common:

    type Currencies : Association to sap.common.Currencies;
    context sap.common {
      entity Currencies : CodeList {...};
      entity CodeList { name : localized String; ... }
    annotate sap.common.CodeList with @(
       UI.Identification: [name],

    Usages of @sap/cds/common

    In effect, usages of @sap/cds/common stay clean of any pollution, for example:

    using { Currency } from '@sap/cds/common';
    entity Books { //...
      currency : Currency;

    Find that also in our cap/samples.

    Still, all SAP Fiori UIs on all services exposing Books will automatically receive Value Help for currencies. You can also benefit from that when deriving your project-specific code list entities from sap.common.CodeList.

    Resulting Annotations in EDMX

    Here is an example how this ends up as OData Common.ValueList annotations:

    <Annotations Target="AdminService.Books/currency_code">
       <Annotation Term="Common.ValueList">
          <Record Type="Common.ValueListType">
             <PropertyValue Property="CollectionPath" String="Currencies"/>
             <PropertyValue Property="Label" String="Currency"/>
             <PropertyValue Property="Parameters">
                   <Record Type="Common.ValueListParameterInOut">
                      <PropertyValue Property="ValueListProperty" String="code"/>
                      <PropertyValue Property="LocalDataProperty" PropertyPath="currency_code"/>
                   <Record Type="Common.ValueListParameterDisplayOnly">
                      <PropertyValue Property="ValueListProperty" String="name"/>
    Show/Hide Beta Features