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
Good One . CAP is the Next big thing in SAP ..
Really Good one 🙂
Can we use Smart filterbar with Smart Table Instead of Fiori elements?
yes.. we can
Hi Sidagam,
Can you please share example on using Smart FilterBar and SmartTable through CAP ?
Thanks,
Mahesh Z.
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.
Thanks
Hello Vishnupriya
Can you try checking with “sap.suite.ui.generic.template”: {} and "sap.ovp": {}
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
Good. Thanks for your sharing
Nice Blog.How did you get create button on Fiori page?
Thanks for the helpful blog.
Hi Dhanasupriya ,
Thanks for sharing All CAPM series , when try to do the same, getting bellow error after click of tile -
#Failed to load UI5 component for navigation intent "#fe-lrop-v4"
Could you please help me on this and find Screenshot also attached here.
It would be great helpfull , if any hint on this.
Regards,
Arjun