Skip to Content
Technical Articles

SAP Cloud Application Programming Model – Demo3

Hey All

This site is extension of my earlier posts on SAP Cloud Application Programming Model (SAP CAPM):

https://blogs.sap.com/2020/05/01/sap-cloud-application-programming-model-demo1/

https://blogs.sap.com/2020/05/03/sap-cloud-application-programming-model-demo2/

Let’s get started with Demo 3 on SAP Cloud Application Programming Model.

SAP Cloud Application Programming Model provides support to SAP Fiori using SAP Fiori Elements. As well known, Fiori Elements are created using the semantic annotations from OData.

What are OData Annotations?

Semantic information can be added to OData using annotations which enables SAP Fiori Elements in exposing the required elements on screen as part of UI. Also, OData annotations can provide information on the capabilities of OData service. 

In this blog, I have explained the List Report of SAP Fiori Elements using OData Annotations.

Open SAP Business Application Studio from SAP Cloud Platform account as explained in before blogs.

create a project in the workspace. Run the command: cds init employeeinfo in the terminal.

user: projects $ cds init employeeinfo

Follow the directory of the project created.

user: projects $ cd employeeinfo    

Place a data model in db folder: schema.cds

namespace sap.com.employeeinfo;

entity Employees{
    key ID: Integer;
    firstname: String(50);
    lastname: String(50);
    company: String(50);
    experience: Integer;
}

Add the service file in SRV folder: cat-service.cds

using sap.com.employeeinfo from '../db/schema';

service CatalogService {
    entity Employees as projection on employeeinfo.Employees;
};

annotate CatalogService.Employees with @(
  UI: {
       HeaderInfo: {
        TypeName: '{i18n>Cat.TypeName}',
        TypeNamePlural: '{i18n>Cat.TypeNamePlural}',
        Title: { $Type: 'UI.DataField', Value: ID }
      },
        SelectionFields: [ ID, firstname, lastname, company, experience],      
      LineItem: [
        {$Type: 'UI.DataField', Value: ID},
        {$Type: 'UI.DataField', Value: firstname},
        {$Type: 'UI.DataField', Value: lastname},
        {$Type: 'UI.DataField', Value: company},
        {$Type: 'UI.DataField', Value: experience}
      ],  
  }
);

annotate CatalogService.Employees with {
  ID @( Common: { Label: '{i18n>Cat.ID}'} );
  firstname @( Common.Label: '{i18n>Cat.firstname}' );
  lastname @( Common.Label: '{i18n>Cat.lastname}' );
  company @( Common.Label: '{i18n>Cat.company}' );
  experience @( Common.Label: '{i18n>Cat.experience}');
}

Create a subfolder csv in db folder. Add a file to csv naming sap.com.employeeinfo.Employees.csv and keep the below data.

ID,firstname,lastname,company,experience
1,Dhanasupriya,Sidagam,com1,4
2,Sainath,Sidagam,com2,3
3,Bhuvana,Sidagam,com3,1

Now lets place our UI code in the app folder.

Create the below project structure in app and add the following code into respective files.

i18n.properties

Run the command cds watch and check for the metadata in browser.

metadata.xml:

<?xml version="1.0" encoding="utf-8"?>
<edmx:Edmx xmlns:edmx="http://docs.oasis-open.org/odata/ns/edmx" Version="4.0">
<edmx:Reference Uri="https://sap.github.io/odata-vocabularies/vocabularies/Common.xml">
<edmx:Include Alias="Common" Namespace="com.sap.vocabularies.Common.v1"/>
</edmx:Reference>
<edmx:Reference Uri="https://sap.github.io/odata-vocabularies/vocabularies/UI.xml">
<edmx:Include Alias="UI" Namespace="com.sap.vocabularies.UI.v1"/>
</edmx:Reference>
<edmx:DataServices>
<Schema xmlns="http://docs.oasis-open.org/odata/ns/edm" Namespace="CatalogService">
<EntityContainer Name="EntityContainer">
<EntitySet Name="Employees" EntityType="CatalogService.Employees"/>
</EntityContainer>
<EntityType Name="Employees">
<Key>
<PropertyRef Name="ID"/>
</Key>
<Property Name="ID" Type="Edm.Int32" Nullable="false"/>
<Property Name="firstname" Type="Edm.String" MaxLength="50"/>
<Property Name="lastname" Type="Edm.String" MaxLength="50"/>
<Property Name="company" Type="Edm.String" MaxLength="50"/>
<Property Name="experience" Type="Edm.Int32"/>
</EntityType>
<Annotations Target="CatalogService.Employees">
<Annotation Term="UI.HeaderInfo">
<Record Type="UI.HeaderInfoType">
<PropertyValue Property="Title">
<Record Type="UI.DataField">
<PropertyValue Property="Value" Path="ID"/>
</Record>
</PropertyValue>
<PropertyValue Property="TypeName" String="Employee"/>
<PropertyValue Property="TypeNamePlural" String="Employees"/>
</Record>
</Annotation>
<Annotation Term="UI.LineItem">
<Collection>
<Record Type="UI.DataField">
<PropertyValue Property="Value" Path="ID"/>
</Record>
<Record Type="UI.DataField">
<PropertyValue Property="Value" Path="firstname"/>
</Record>
<Record Type="UI.DataField">
<PropertyValue Property="Value" Path="lastname"/>
</Record>
<Record Type="UI.DataField">
<PropertyValue Property="Value" Path="company"/>
</Record>
<Record Type="UI.DataField">
<PropertyValue Property="Value" Path="experience"/>
</Record>
</Collection>
</Annotation>
<Annotation Term="UI.SelectionFields">
<Collection>
<PropertyPath>ID</PropertyPath>
<PropertyPath>firstname</PropertyPath>
<PropertyPath>lastname</PropertyPath>
<PropertyPath>company</PropertyPath>
<PropertyPath>experience</PropertyPath>
</Collection>
</Annotation>
</Annotations>
<Annotations Target="CatalogService.Employees/ID">
<Annotation Term="Common.Label" String="Employee ID"/>
</Annotations>
<Annotations Target="CatalogService.Employees/firstname">
<Annotation Term="Common.Label" String="First Name"/>
</Annotations>
<Annotations Target="CatalogService.Employees/lastname">
<Annotation Term="Common.Label" String="Last Name"/>
</Annotations>
<Annotations Target="CatalogService.Employees/company">
<Annotation Term="Common.Label" String="Company"/>
</Annotations>
<Annotations Target="CatalogService.Employees/experience">
<Annotation Term="Common.Label" String="Experience"/>
</Annotations>
</Schema>
</edmx:DataServices>
</edmx:Edmx>

Component.js

sap.ui.define(['sap/fe/AppComponent'], function(AppComponent) {
    'use strict';

    return AppComponent.extend('sap.demo.employees.Component', {
        metadata: {
            manifest: 'json'
        }
    });
});

index.html

<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="X-UA-Compatible" content="IE=edge" />
        <meta http-equiv="Content-Type" content="text/html;charset=UTF-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>{{appTitle}}</title>

        <script>
            window['sap-ushell-config'] = {
                defaultRenderer: 'fiori2',
                applications: {
                    "fe-lrop-v4": {
                        title: 'Employees',
                        description: 'Fiori elements app',
                        additionalInformation: 'SAPUI5.Component=sap.demo.employees',
                        applicationType: 'URL',
                        url: './',
                        navigationMode: 'embedded'
                    }
                }
            };
        </script>

        <script src="https://sapui5.hana.ondemand.com/1.71.0/test-resources/sap/ushell/bootstrap/sandbox.js"></script>
        <script
            src="https://sapui5.hana.ondemand.com/1.71.0/resources/sap-ui-core.js"
            data-sap-ui-libs="sap.m, sap.ushell, sap.collaboration, sap.ui.layout"
            data-sap-ui-compatVersion="edge"
            data-sap-ui-theme="sap_fiori_3"
            data-sap-ui-frameOptions="allow"
        ></script>
        <script>
            sap.ui.getCore().attachInit(() => sap.ushell.Container.createRenderer().placeAt('content'));
        </script>
    </head>
    <body class="sapUiBody" id="content"></body>
</html>

manifest.json:

{
    "_version": "1.15.0",
    "sap.app": {
        "id": "sap.uxfe.demo.products",
        "type": "application",
        "i18n": "i18n/i18n.properties",
        "applicationVersion": {
            "version": "1.0"
        },
        "title": "{{appTitle}}",
        "description": "{{appDescription}}",
        "ach": "CA-UI5-FE",
        "dataSources": {
            "mainService": {
                "uri": "/catalog/",
                "type": "OData",
                "settings": {
                    "odataVersion": "4.0"
                }
            }
        },
        "offline": false,
        "resources": "resources.json",
        "sourceTemplate": {
            "id": "ui5template.fiorielements.v4.lrop",
            "version": "1.0.0"
        }
    },
    "sap.ui": {
        "technology": "UI5",
        "icons": {
            "icon": "",
            "favIcon": "",
            "phone": "",
            "phone@2": "",
            "tablet": "",
            "tablet@2": ""
        },
        "deviceTypes": {
            "desktop": true,
            "tablet": true,
            "phone": true
        }
    },
    "sap.ui5": {
        "resources": {
            "js": [],
            "css": []
        },
        "dependencies": {
            "minUI5Version": "1.71.0",
            "libs": {
                "sap.fe": {}
            }
        },
        "models": {
            "i18n": {
                "type": "sap.ui.model.resource.ResourceModel",
                "uri": "i18n/i18n.properties"
            },
            "": {
                "dataSource": "mainService",
                "settings": {
                    "synchronizationMode": "None",
                    "operationMode": "Server",
                    "autoExpandSelect": true,
                    "earlyRequests": true
                }
            }
        },
        "routing": {
            "routes": [
                {
                    "pattern": "",
                    "name": "ProductsList",
                    "target": "EmployeeList"
                }
              
            ],
            "targets": {
                "EmployeeList": {
                    "type": "Component",
                    "id": "EmployeeList",
                    "name": "sap.fe.templates.ListReport",
                    "options": {
                        "settings": {
                            "entitySet": "Employees",
                            "variantManagement": "Page"
                           
                        }
                    }
                }
            }
        },
        "contentDensities": {
            "compact": true,
            "cozy": true
        }
    },
    "sap.platform.abap": {
        "_version": "1.1.0",
        "uri": ""
    },
    "sap.platform.hcp": {
        "_version": "1.1.0",
        "uri": ""
    },
    "sap.fiori": {
        "_version": "1.1.0",
        "registrationIds": [],
        "archeType": "transactional"
    }
}

Once our UI code is also ready, run the command cds watch again. Click on Open in New Tab button which will open at the right bottom of page.

Output: Open the highlighted path.

Click on Employees tile.

Finally our List Report SAP Fiori Element shows up.

Please comment down below for any suggestions & queries.

Thank you Community!! 🙂

#EnhanceLearning

BR//Dhanasupriya Sidagam

7 Comments
You must be Logged on to comment or reply to a post.
  • Hi,

    Great Blog! Can you please let me know what library needs to be included for Analytical List Page and Overview pages in manifest.json file?

    Tried adding 'sap.suite.ui.generic:{}' along with sap.fe:{}; that didnt help.
    
    “sap.ui5”: {
            “resources”: {
                “js”: [],
                “css”: []
            },
            “dependencies”: {
                “minUI5Version”: “1.71.0”,
                “libs”: {
                    “sap.fe”: {},
                    “sap.suite.ui.generic”: {}
                }
            },
    Thanks
    
                                
  • Hello Dhanasupriya,

    I am trying to consume cds odata by normal UII5 controls like table. I am trying to achieve in similar way as V2. But I am not able to show all records of serviice. Only 1 record is showing multiple times. It means I am not able to add aggregation binding with v4 odata. Could you please look into below code and please help me here.

    Manifest.json

    “dataSources”: {
    “CatalogService”: {
    “uri”: “/browse/”,
    “type”: “OData”,
    “settings”: {
    “odataVersion”: “4.0”
    }
    }

    View

    <Table items=”{path: ‘/PRIVILEGES’}” noDataText=”No Data” id=”table0″>
    <items>
    <ColumnListItem type=”Active” >
    <cells>
    <Text text=”{USER_NAME}” />
    <Text text=”{GRANTEE_SCHEMA_NAME}” />

    In network, I could see all records for the entity.

    Thanks

    Ansuman