Skip to Content
Technical Articles
Author's profile photo Shobhit Srivastava

Developing SAP Fiori Element application by using SAP Cloud Application Programming Model

Introduction:

SAP Fiori Elements is a framework comprising of templates for commonly used application patterns, for example List Report, Worklist, Object Page, Overview Page and Analytical list page. Predefined templates combined with OData service and annotations generates SAP Fiori application at startup.

Pre-requisites:

  1. Subscribe to SAP Business Application Studio.
  2. Create SAP Hana cloud instance.
  3. Create HDI Hana instance.
  4. Connect SAP BAS with SAP HANA Cloud by binding the HDI container.
  5. Run the Dev space and the SAP HANA cloud instance.

Benefits of creating application with SAP Fiori Element

  • No JavaScript UI coding
  • Apps are based on centrally provided templates (views and controllers), so no application-specific view instances are required.
  • Ensures consistent UI across similar apps.
  • The metadata-driven development model eliminates front in coding effort, so the developer can focus on the business logic.

Annotations Concept:

  • Descriptions added to OData metadata document is known as OData Annotation.
  • For SAP OData version 2.0, annotation is stored in XML tag of OData metadata. All SAP specified annotation are started with ‘sap:’.
  • In OData version 4.0, annotations are separated from the main part of the OData metadata document, either as a separate part in OData metadata document or stored in a separate file.
  • Annotations Vocabulary : The most commonly used vocabulary for Fiori Elements is UI vocabulary. Vocabulary defines how you can add annotations to an OData service.

Fiori Elements Templates

  • List Report– displays list of items equipped with functions for filtering and many other functions. It serves as an alternative of ALV in SAP GUI to display data in web applications.
  • Object Page– purpose of Object page is to display information of a single business entity.
  • Analytic List Page– An Analytical list page is designed to analyze data from different perspective.
  • Overview Page– is similar to a dashboard fulfilling the objective of displaying large amounts of information. Overview page is designed to provide quick access to vital business information at a glance, in the form of actionable cards.

Steps:

  • Create CAP Project from Template.

Cap%20project%20starting%20from%20template

Figure 1: CAP project starting from template

  • Enter a project name, select your runtime as Node.js. Add features to your project. Then click on finish button. Now CAP project is been generated. There will three main folders app, db, srv.

Figure%202%3A%20CAP%20Project%20Details

Figure 2: CAP Project Details

 

Figure%203%3A%20CAP%20project%20folder%20structure

Figure 3: CAP project folder structure

Folder structure is as follows:

  • Create data-Model folder in db. Now create a new file data-Model.cds under data-Model folder.
  • Create entity in this data-Model.cds file.

Figure%205%3A%20data-Model.cds%20file

Figure 4: data-Model.cds file

In data-Model.cds file define the entities with the column names as shown in the following code:

namespace db;
using db.types as types from '../data-Model/types';
entity PRODUCTS {
    key ID               : UUID;
        @title: 'Product Name'
        PROD_NAME        : String(256);
        @title: 'Product Price'
        PROD_PRICE       : Int64;
        @title: 'Currency'
        CURRENCY       : String(256);
        @title: 'Product Type'
        PROD_TYPE        : String(256);
        @title: 'Supplier Name'
        SUPPLIER_NAME    : String(256);
        @title: 'Customer Name'
        CUSTOMER_NAME    : String(256);
        @title: 'History'
        HISTORY          : types.HistoryT;
        @title: 'Agreement'
        AGREEMENT   : Boolean default false;
        @title:'Date of Manufacture'
        DOB: Date;
        LINK_TO_SUPPLIER : Association[1.. 1] to SUPPLIER
                               on LINK_TO_SUPPLIER.ID = SUPPLIER_NAME;
        LINK_TO_CUSTOMER : Association[1.. 1] to CUSTOMER
                               on LINK_TO_CUSTOMER.ID = CUSTOMER_NAME;

}
entity SUPPLIER {
    key ID          : String(256);
        DESCRIPTION : String(256);
}
entity CUSTOMER {
    key ID          : String(256);
        DESCRIPTION : String(256);
}

Also create types.cds file to define a user defined data type:

namespace db.types;

using {
    managed,
    sap
} from '@sap/cds/common';

type AppIdT : String(40);
type UserT  : String(256);

type HistoryT {

    @readonly
    @Common.Label : 'Created By'
    @cds.on.insert: $user
    CRTD_BY     : UserT;

    @readonly
    @Common.Label : 'Created On'
    @cds.on.insert: $now
    CRTD_DATE   : DateTime;

    @UI.Hidden
    CRTD_APP_ID : AppIdT;

    @readonly
    @Common.Label : 'Changed By'
    @cds.on.insert: $user
    @cds.on.update: $user
    CHNG_BY     : UserT;

    @readonly
    @Common.Label : 'Changed On'
    @cds.on.insert: $now
    @cds.on.update: $now
    CHNG_DATE   : DateTime;

    @UI.Hidden
    CHNG_APP_ID : AppIdT;
};
  • Now create cat-service.cds file in srv folder.

Figure%206%3A%20srv%20folder

Figure 5: srv folder

In cat-service.cds file expose the entity as a service named CatalogService. The annotation @(requires: ‘authenticated-user’) is used for authenticating the user. The annotation @odata.draft.enabled is used for enabling the preview mode.

using db as db from '../db/data-Model/data-Model';
using db.types as types from '../db/data-Model/types';

service CatalogService @(requires: 'authenticated-user') {
    @odata.draft.enabled
    entity Products as projection on db.PRODUCTS {
        *,
        LINK_TO_SUPPLIER : redirected to Suppliers, 
        LINK_TO_CUSTOMER : redirected to Customers,
    };

    entity Suppliers as projection on db.SUPPLIER;
    entity Customers as projection on db.CUSTOMER;
}

After writing the code in data-Model.cds and cat-service.cds file. Open Terminal and do cds build and cds deploy.

Figure 6: cds build and cds deploy

Now the table artifact will be generated in SAP HANA cloud Database as shown in below figure.

Figure%208%3A%20Table%20artifacts%20in%20SAP%20Hana%20Cloud%20Database

Figure 7: Table artifacts in SAP Hana Cloud Database

  • Now creating a SAP Fiori application from template.

Figure%207%3A%20Sap%20Fiori%20app%20from%20template

Figure 8: Sap Fiori app from template

Select Sap fiori application. Then press Next button.

Figure%208%3A%20Select%20List%20Report%20template

Figure 9: Select List Report template

Select the template type as SAP Fiori and then select List Report template.

Figure%209%3A%20Data%20source%20and%20Service%20selection

Figure 10: Data source and Service selection

Select data source as Local cap project and chose your project. Select odata service as CatalogService(Node.js).

Figure%2010%3A%20Entity%20Selection

Figure 11: Entity Selection

Chose main entity as Products. Navigation entity as none. And No radio button for automatically add table column to the list page and a section to the object page.

Figure%2011%3A%20Project%20Attributes

Figure 12: Project Attributes

Enter the Module name, Application title, no application namespace, select yes for add deployment configuration to MTA and add FLP configuration and click next button.

Figure%2012%3A%20Deployment%20configuration

Figure 13: Deployment configuration

Chose the target as Cloud Foundry and destination as none. Then press next.

Figure%2013%3A%20Fiori%20launchpad%20configuration

Figure 14: Fiori launchpad configuration

Enter semantic object, action and title. Then press Finish. Now the application will be generated.

Figure%2014%3A%20Application%20details

Figure 15: Application details

The productsapp is generated and saved for further use. The productsapp folder structure is as follows:

Figure%20%3A%20Sap%20Fiori%20app%20structure

Figure 16: Sap Fiori app structure

Code of manifest.json file is:

{
    "_version": "1.49.0",
    "sap.app": {
        "id": "productsapp",
        "type": "application",
        "i18n": "i18n/i18n.properties",
        "applicationVersion": {
            "version": "0.0.1"
        },
        "title": "{{appTitle}}",
        "description": "{{appDescription}}",
        "resources": "resources.json",
        "sourceTemplate": {
            "id": "@sap/generator-fiori:lrop",
            "version": "1.10.3",
            "toolsId": "ff8013c8-3b87-45a2-b24e-657be8404fec"
        },
        "dataSources": {
            "CatalogService": {
                "uri": "/odata/v4/catalog/",
                "type": "OData",
                "settings": {
                    "annotations": [],
                    "localUri": "localService/metadata.xml",
                    "odataVersion": "4.0"
                }
            }
        },
        "crossNavigation": {
            "inbounds": {
                "productsapp-inbound": {
                    "signature": {
                        "parameters": {},
                        "additionalParameters": "allowed"
                    },
                    "semanticObject": "products",
                    "action": "manage",
                    "title": "{{flpTitle}}",
                    "subTitle": "{{flpSubtitle}}",
                    "icon": ""
                }
            }
        }
    },
    "sap.ui": {
        "technology": "UI5",
        "icons": {
            "icon": "",
            "favIcon": "",
            "phone": "",
            "phone@2": "",
            "tablet": "",
            "tablet@2": ""
        },
        "deviceTypes": {
            "desktop": true,
            "tablet": true,
            "phone": true
        }
    },
    "sap.ui5": {
        "flexEnabled": true,
        "dependencies": {
            "minUI5Version": "1.116.0",
            "libs": {
                "sap.m": {},
                "sap.ui.core": {},
                "sap.ushell": {},
                "sap.fe.templates": {}
            }
        },
        "contentDensities": {
            "compact": true,
            "cozy": true
        },
        "models": {
            "i18n": {
                "type": "sap.ui.model.resource.ResourceModel",
                "settings": {
                    "bundleName": "productsapp.i18n.i18n"
                }
            },
            "": {
                "dataSource": "CatalogService",
                "preload": true,
                "settings": {
                    "synchronizationMode": "None",
                    "operationMode": "Server",
                    "autoExpandSelect": true,
                    "earlyRequests": true
                }
            },
            "@i18n": {
                "type": "sap.ui.model.resource.ResourceModel",
                "uri": "i18n/i18n.properties"
            }
        },
        "resources": {
            "css": []
        },
        "routing": {
            "config": {},
            "routes": [
                {
                    "pattern": ":?query:",
                    "name": "ProductsList",
                    "target": "ProductsList"
                },
                {
                    "pattern": "Products({key}):?query:",
                    "name": "ProductsObjectPage",
                    "target": "ProductsObjectPage"
                }
            ],
            "targets": {
                "ProductsList": {
                    "type": "Component",
                    "id": "ProductsList",
                    "name": "sap.fe.templates.ListReport",
                    "options": {
                        "settings": {
                            "entitySet": "Products",
                            "initialLoad": "Enabled",
                            "variantManagement": "Page",
                            "navigation": {
                                "Products": {
                                    "detail": {
                                        "route": "ProductsObjectPage"
                                    }
                                }
                            }
                        }
                    }
                },
                "ProductsObjectPage": {
                    "type": "Component",
                    "id": "ProductsObjectPage",
                    "name": "sap.fe.templates.ObjectPage",
                    "options": {
                        "settings": {
                            "editableHeaderContent": false,
                            "entitySet": "Products"
                        }
                    }
                }
            }
        }
    },
    "sap.fiori": {
        "registrationIds": [],
        "archeType": "transactional"
    }
}
  • Now create cat-service-annotations.cds file in srv and write the following code in this file.
using CatalogService as service from './cat-service';
/**
 * Annotations for Products
 */
annotate service.Products with {
    ID        @title: 'ID';
    AGREEMENT @title: 'Agreement';
}
// UI code for object ProductsList
annotate service.Products with @(
    UI.HeaderInfo     : {
        TypeName      : 'Products',
        TypeNamePlural: 'Products',
        Title         : {
            $Type: 'UI.DataField',
            Value: PROD_NAME
        },
        Description   : {
            $Type: 'UI.DataField',
            Value: PROD_TYPE
        }

    },
    UI.SelectionFields: [
        PROD_NAME,
        PROD_TYPE,
        SUPPLIER_NAME,
        CUSTOMER_NAME
    ],

    UI.LineItem       : [
        {
            $Type        : 'UI.DataField',
            Label        : 'ID',
            Value        : ID,
            ![@UI.Hidden]: true,
        },
        {
            $Type: 'UI.DataField',
            Label: 'Product Name',
            Value: PROD_NAME,
        },
        {
            $Type: 'UI.DataField',
            Label: 'Product Type',
            Value: PROD_TYPE,
        },
        {
            $Type: 'UI.DataField',
            Label: 'Customer Name',
            Value: CUSTOMER_NAME,
        },
        {
            $Type: 'UI.DataField',
            Label: 'Supplier Name',
            Value: SUPPLIER_NAME,
        },
        {
            $Type: 'UI.DataField',
            Label: 'Product Price',
            Value: PROD_PRICE,
        },
        {
            $Type: 'UI.DataField',
            Label: 'Product Price',
            Value: CURRENCY
        },
        {
            $Type: 'UI.DataField',
            Label: 'Agreement',
            Value: AGREEMENT,
        }
    ]
);
// UI code for object ProductsObjectPage
annotate service.Products with @(
    UI.FieldGroup #GeneratedGroup1: {
        $Type: 'UI.FieldGroupType',
        Data : [
            {
                $Type: 'UI.DataField',
                Label: 'ID',
                Value: ID
            // ![@UI.Hidden] : true,
            },
            {
                $Type: 'UI.DataField',
                Label: 'Product Name',
                Value: PROD_NAME
            },
            {
                $Type: 'UI.DataField',
                Label: 'Product Type',
                Value: PROD_TYPE
            }
        ],
    },
    UI.FieldGroup #GeneratedGroup2: {
        $Type: 'UI.FieldGroupType',
        Data : [
            {
                $Type: 'UI.DataField',
                Label: 'Customer Name',
                Value: CUSTOMER_NAME
            },
            {
                $Type: 'UI.DataField',
                Label: 'Supplier Name',
                Value: SUPPLIER_NAME
            },
            {
                $Type: 'UI.DataField',
                Label: 'Product Price',
                Value: PROD_PRICE
            },
            {
                $Type: 'UI.DataField',
                Label: 'Agreement',
                Value: AGREEMENT
            },
            {
                $Type: 'UI.DataField',
                Label: 'Currency',
                Value: CURRENCY
            },
            {
                $Type: 'UI.DataField',
                Label: 'Date of Manufacture',
                Value: DOB
            }
        ]
    },
    UI.FieldGroup #GeneratedGroup3: {
        $Type: 'UI.FieldGroupType',
        Data : [
            {
                $Type: 'UI.DataField',
                Label: 'Created By',
                Value: HISTORY_CRTD_BY
            },
            {
                $Type: 'UI.DataField',
                Label: 'Created On',
                Value: HISTORY_CRTD_DATE
            },
            {
                $Type: 'UI.DataField',
                Label: 'Changed By',
                Value: HISTORY_CHNG_BY
            },
            {
                $Type: 'UI.DataField',
                Label: 'Changed On',
                Value: HISTORY_CHNG_DATE
            }
        ]
    },
    UI.Facets                     : [
        {
            $Type : 'UI.ReferenceFacet',
            ID    : 'GeneratedFacet1',
            Label : 'General Information',
            Target: '@UI.FieldGroup#GeneratedGroup1',
        },
        {
            $Type : 'UI.ReferenceFacet',
            ID    : 'GeneratedFacet2',
            Label : 'Additional Information',
            Target: '@UI.FieldGroup#GeneratedGroup2',
        },
        {
            $Type : 'UI.ReferenceFacet',
            ID    : 'GeneratedFacet3',
            Label : 'History',
            Target: '@UI.FieldGroup#GeneratedGroup3',
        }
    ]
);

// Making Mandatory fields
annotate service.Products with {
    PROD_NAME
    @(Common: {FieldControl: #Mandatory});
    SUPPLIER_NAME
    @(Common: {FieldControl: #Mandatory})
};

// Creating Drop down and value help
annotate service.Products with {
    SUPPLIER_NAME @(Common: {
        Text           : LINK_TO_SUPPLIER.DESCRIPTION,
        TextArrangement: #TextOnly,        
        ValueList      : {
            CollectionPath: 'Suppliers',
            Label         : 'Supplier Name',
            Parameters    : [
                {
                    $Type            : 'Common.ValueListParameterDisplayOnly',
                    ValueListProperty: 'DESCRIPTION',

                },
                {
                    $Type            : 'Common.ValueListParameterInOut',
                    LocalDataProperty: SUPPLIER_NAME,
                    ValueListProperty: 'ID',

                }
            ],

        }
    });
    CUSTOMER_NAME @(Common: {
        Text           : LINK_TO_CUSTOMER.DESCRIPTION,
        TextArrangement: #TextOnly,
        ValueListWithFixedValues,
        ValueList      : {
            CollectionPath: 'Customers',
            Label         : 'Customers',
            Parameters    : [
                {
                    $Type            : 'Common.ValueListParameterDisplayOnly',
                    ValueListProperty: 'DESCRIPTION',

                },
                {
                    $Type            : 'Common.ValueListParameterInOut',
                    LocalDataProperty: CUSTOMER_NAME,
                    ValueListProperty: 'ID',

                }
            ],

        }
    });
};

annotate service.Products with @(Capabilities.FilterRestrictions: {FilterExpressionRestrictions: [{
    Property          : SUPPLIER_NAME,
    AllowedExpressions: 'SingleValue'
}]});

After adding annotations in cat-service-annotations.cds  open new terminal and do cds build, cds deploy and then cds run.

Figure%2017%3A%20cds%20build%20and%20cds%20deploy

Figure 17: cds build and cds deploy

Figure%2017%3A%20cds%20run

Figure 18: cds run

  • Open a new terminal the web application and service endpoints are listed.

Figure%2019%3A%20Output

Figure 19: Output

  • Open web application:

Figure%2020%3A%20Products%20app%20List%20page

Figure 20: Products app List page

The selection fields is the smart filters and the line item is the smart table. Code is added in cat-service-annotations.cds file in srv folder.

  • Now open any product in the line item. The page will navigate to object page.

Figure%2021%3A%20Products%20app%20Object%20page

Figure 21: Products app Object page

The header info, facets and Field Groups are displayed on object page. Code is added in cat-service-annotations.cds file in srv folder.

Demonstration of Products application:

See vedio for demo.

Refer to github repository: https://github.com/Shobhit3197/https-shobhit0504-dev.azure.com-shobhit0504-Foxcom-_git-newCustomerProject

 

Assigned Tags

      2 Comments
      You must be Logged on to comment or reply to a post.
      Author's profile photo ANURAG SINGH
      ANURAG SINGH

      Nicely documented steps..

      Author's profile photo Dixit Miglani
      Dixit Miglani

      Hi Shobhit,

       

      Nice explanation with clear steps. Happy learning!!