How to create Smart Templates annotations within CDS views – part 3
Introduction
This is the continuation of the blog started here!
This blog has been split in 3 parts:
Link | Content |
---|---|
How to create Smart Templates annotations within CDS views – part 1 | Development tool installation and DDL Source creation |
How to create Smart Templates annotations within CDS views – part 2 | Service registration and Smart Template creation in the NW Gateway and consumed by Smart Templates |
This part | Enhancing the annotation |
Step 6 – Enhancing the annotation
In this last part of the blog we are going to see how to enrich and improve the CDS view with more annotation terms in order to complete our sample application.
If you have followed the two previous parts you should have come now to a point where the application starts, but it doesn’t show anything yet.
The first useful thing that we want to add to our CDS view is the UI.LineItem annotation term to show a list of all the products when the application starts. This can be done by specifying in the CDS view, before each field we want to see in the grid, the position where we want to see it and its importance.
1 – Open first SAP Web IDE and open the existing annotation file with the AM. In this way we can check step by step how the annotation changes
2 – Open Eclipse
3 – Open the CDS view Z_SAMPLE_DEMO_PRODUCTS and change the code to be the following
@AbapCatalog.sqlViewName: ‘Z_VW_PRODUCTS’
@AbapCatalog.compiler.compareFilter: true
@AccessControl.authorizationCheck: #CHECK
@EndUserText.label: ‘Products’
@OData.publish: true
@UI.headerInfo:{
typeName: ‘Product’,
typeNamePlural: ‘Products’,
imageUrl: {value: ‘PictureUrl’},
title: {value: ‘Name’},
description: {value: ‘Description’}
}
define view Z_Sample_Demo_Products
as select from sepm_iproduct as Products
association [1..*] to Z_Sample_Demo_Soli as _SOItems on $projection.productuuid = _SOItems.ProductID
association [1..1] to sepm_iproductt as _ProductT on $projection.productuuid = _ProductT.productuuid
and _ProductT.language = ‘E’
association [1..1] to sepm_ibupa as _Supplier on $projection.supplieruuid = _Supplier.businesspartneruuid
{
key Products.productuuid,
@UI: {
lineItem: {position: 10, importance: #HIGH}
}
Products.product as ProductID,
Products.producttype as TypeCode,
@UI: {
lineItem: {position: 30, importance: #HIGH}
}
Products.productcategory as Category,
@UI: {
lineItem: {position: 20, importance: #HIGH, label: ‘Product Name’}
}
_ProductT.productname as Name,
‘EN’ as NameLanguage,
@UI: {
lineItem: {position: 40, importance: #HIGH, label: ‘Prod.Descrip.’}
}
_ProductT.productdescription as Description,
‘EN’ as DescriptionLanguage,
_Supplier.businesspartner as SupplierID,
_Supplier.companyname as SupplierName,
Products.productvalueaddedtax as TaxTarifCode,
Products.productbaseunit as MeasureUnit,
Products.weight as WeightMeasure,
Products.weightunit as WeightUnit,
Products.currency as CurrencyCode,
@UI: {
lineItem: {position: 50, importance: #HIGH}
}
Products.price as Price,
Products.width as Width,
Products.depth as Depth,
Products.height as Height,
Products.dimensionunit as DimUnit,
Products.creationdatetime as CreatedAt,
Products.lastchangeddatetime as ChangedAt,
concat(concat(‘/webapp/images/’,Products.product),‘.jpg’) as PictureUrl,
Products.supplieruuid,
_SOItems
}
3 – Save and activate
4 – If you refresh the annotation file in SAP Web IDE you should see that a new UI.LineItem annotation term has been added to it in disabled mode, because it’s coming directly from the server
5 – Let’s add now some selection fields: we want to use them to filter records in the application. The annotation term we need to add is UI.SelectionField and since we want to filter by ProductID and Category, we need to add it just before these two fields in the view, like the following
6 – Save and activate. Refreshing the annotation, now you should see this
7 – We can make this view a little bit more complex by adding the UI.Identification term. This can be done at the same way we did for the the UI.LineItem. The view becomes:
@AbapCatalog.sqlViewName: ‘Z_VW_PRODUCTS’
@AbapCatalog.compiler.compareFilter: true
@AccessControl.authorizationCheck: #CHECK
@EndUserText.label: ‘Products’
@OData.publish: true
@UI.headerInfo:{
typeName: ‘Product’,
typeNamePlural: ‘Products’,
imageUrl: {value: ‘PictureUrl’},
title: {value: ‘Name’},
description: {value: ‘Description’}
}
define view Z_Sample_Demo_Products
as select from sepm_iproduct as Products
association [1..*] to Z_Sample_Demo_Soli as _SOItems on $projection.productuuid = _SOItems.ProductID
association [1..1] to sepm_iproductt as _ProductT on $projection.productuuid = _ProductT.productuuid
and _ProductT.language = ‘E’
association [1..1] to sepm_ibupa as _Supplier on $projection.supplieruuid = _Supplier.businesspartneruuid
{
key Products.productuuid,
@UI: {
identification: {position: 10, importance: #HIGH},
lineItem: {position: 10, importance: #HIGH},
selectionField: {position: 10}
}
Products.product as ProductID,
@UI: {
identification: {position: 40, importance: #HIGH}
}
Products.producttype as TypeCode,
@UI: {
identification: {position: 30, importance: #HIGH},
lineItem: {position: 30, importance: #HIGH},
selectionField: {position: 20}
}
Products.productcategory as Category,
@UI: {
identification: {position: 20, importance: #HIGH, label: ‘Product Name’},
lineItem: {position: 20, importance: #HIGH, label: ‘Product Name’}
}
_ProductT.productname as Name,
‘EN’ as NameLanguage,
@UI: {
identification: {position: 50, importance: #HIGH, label: ‘Prod.Descrip.’},
lineItem: {position: 40, importance: #HIGH, label: ‘Prod.Descrip.’}
}
_ProductT.productdescription as Description,
‘EN’ as DescriptionLanguage,
_Supplier.businesspartner as SupplierID,
_Supplier.companyname as SupplierName,
Products.productvalueaddedtax as TaxTarifCode,
Products.productbaseunit as MeasureUnit,
Products.weight as WeightMeasure,
Products.weightunit as WeightUnit,
Products.currency as CurrencyCode,
@UI: {
identification: {position: 60, importance: #HIGH},
lineItem: {position: 50, importance: #HIGH}
}
Products.price as Price,
Products.width as Width,
Products.depth as Depth,
Products.height as Height,
Products.dimensionunit as DimUnit,
Products.creationdatetime as CreatedAt,
Products.lastchangeddatetime as ChangedAt,
concat(concat(‘/webapp/images/’,Products.product),‘.jpg’) as PictureUrl,
Products.supplieruuid,
_SOItems
}
8 – Save and activate. The annotation in the AM should show now this new UI.Identification term
9 – We can do the same for the UI.StatusInfo to show the creation and the change dates at the end of the view
….
Products.dimensionunit as DimUnit,
@UI: {
statusInfo: {position: 10, importance: #MEDIUM}
}
Products.creationdatetime as CreatedAt,
@UI: {
statusInfo: {position: 20, importance: #MEDIUM}
}
Products.lastchangeddatetime as ChangedAt,
concat(concat(‘/webapp/images/’,Products.product),‘.jpg’) as PictureUrl,
Products.supplieruuid,
_SOItems
}
10 – Save and activate. The UI.StatusInfo has been successfully added:
11 – Let’s add a couple of UI.DataPoint terms in order to show the Price and the Tax Code
….
_Supplier.businesspartner as SupplierID,
_Supplier.companyname as SupplierName,
@UI: {
dataPoint: { title: ‘TaxCode’ }
}
Products.productvalueaddedtax as TaxTarifCode,
Products.productbaseunit as MeasureUnit,
Products.weight as WeightMeasure,
Products.weightunit as WeightUnit,
Products.currency as CurrencyCode,
@UI: {
identification: {position: 60, importance: #HIGH},
lineItem: {position: 50, importance: #HIGH},
dataPoint: { title: ‘Price’ }
}
Products.price as Price,
….
12 – Save and activate. Here it’s the new annotation file
13 – Some UI.FieldGroup terms will help us to show Technical Data information about the product in the ObjectPage, so let’s add these new terms in the view
@AbapCatalog.sqlViewName: ‘Z_VW_PRODUCTS’
@AbapCatalog.compiler.compareFilter: true
@AccessControl.authorizationCheck: #CHECK
@EndUserText.label: ‘Products’
@OData.publish: true
@UI.headerInfo:{
typeName: ‘Product’,
typeNamePlural: ‘Products’,
imageUrl: {value: ‘PictureUrl’},
title: {value: ‘Name’},
description: {value: ‘Description’}
}
define view Z_Sample_Demo_Products
as select from sepm_iproduct as Products
association [1..*] to Z_Sample_Demo_Soli as _SOItems on $projection.productuuid = _SOItems.ProductID
association [1..1] to sepm_iproductt as _ProductT on $projection.productuuid = _ProductT.productuuid
and _ProductT.language = ‘E’
association [1..1] to sepm_ibupa as _Supplier on $projection.supplieruuid = _Supplier.businesspartneruuid
{
key Products.productuuid,
@UI: {
identification: {position: 10, importance: #HIGH},
lineItem: {position: 10, importance: #HIGH},
selectionField: {position: 10}
}
Products.product as ProductID,
@UI: {
identification: {position: 40, importance: #HIGH}
}
Products.producttype as TypeCode,
@UI: {
identification: {position: 30, importance: #HIGH},
lineItem: {position: 30, importance: #HIGH},
selectionField: {position: 20}
}
Products.productcategory as Category,
@UI: {
identification: {position: 20, importance: #HIGH, label: ‘Product Name’},
lineItem: {position: 20, importance: #HIGH, label: ‘Product Name’}
}
_ProductT.productname as Name,
‘EN’ as NameLanguage,
@UI: {
identification: {position: 50, importance: #HIGH, label: ‘Prod.Descrip.’},
lineItem: {position: 40, importance: #HIGH, label: ‘Prod.Descrip.’}
}
_ProductT.productdescription as Description,
‘EN’ as DescriptionLanguage,
_Supplier.businesspartner as SupplierID,
_Supplier.companyname as SupplierName,
@UI: {
dataPoint: { title: ‘TaxCode’ }
}
Products.productvalueaddedtax as TaxTarifCode,
Products.productbaseunit as MeasureUnit,
@UI: {
fieldGroup: {qualifier: ‘FGTechData’, groupLabel: ‘Technical Data’, position: 10, importance: #MEDIUM}
}
Products.weight as WeightMeasure,
Products.weightunit as WeightUnit,
Products.currency as CurrencyCode,
@UI: {
identification: {position: 60, importance: #HIGH},
lineItem: {position: 50, importance: #HIGH},
dataPoint: { title: ‘Price’ }
}
Products.price as Price,
@UI: {
fieldGroup: {qualifier: ‘FGTechData’, groupLabel: ‘Technical Data’, position: 20, importance: #MEDIUM}
}
Products.width as Width,
@UI: {
fieldGroup: {qualifier: ‘FGTechData’, groupLabel: ‘Technical Data’, position: 40, importance: #MEDIUM}
}
Products.depth as Depth,
@UI: {
fieldGroup: {qualifier: ‘FGTechData’, groupLabel: ‘Technical Data’, position: 30, importance: #MEDIUM}
}
Products.height as Height,
Products.dimensionunit as DimUnit,
@UI: {
statusInfo: {position: 10, importance: #MEDIUM}
}
Products.creationdatetime as CreatedAt,
@UI: {
statusInfo: {position: 20, importance: #MEDIUM}
}
Products.lastchangeddatetime as ChangedAt,
concat(concat(‘/webapp/images/’,Products.product),‘.jpg’) as PictureUrl,
Products.supplieruuid,
_SOItems
}
14 – Save and activate. This is how the annotation appears now
15 – As the last thing, let’s add a UI.LineItem annotation even for Sales Order Line Items. Open in Eclipse the view Z_SAMPLE_DEMO_SOLI and add the annotation in this way:
@AbapCatalog.sqlViewName: ‘Z_VW_SOLITEMS’
@AbapCatalog.compiler.compareFilter: true
@AccessControl.authorizationCheck: #CHECK
@EndUserText.label: ‘Sales Order Line Items’
define view Z_Sample_Demo_Soli
as select from sepm_isoi as SOLItems
{
key SOLItems.salesorderitemuuid,
SOLItems.salesorderuuid as SalesOrderID,
@UI: {
lineItem: {position: 10, importance: #HIGH}
}
SOLItems.salesorderitem as ItemPosition,
SOLItems.productuuid as ProductID,
SOLItems.shorttextgroupuuid as NoteID,
SOLItems.transactioncurrency as CurrencyCode,
@UI: {
lineItem: {position: 40, importance: #HIGH}
}
SOLItems.grossamountintransaccurrency as GrossAmount,
@UI: {
lineItem: {position: 30, importance: #HIGH}
}
SOLItems.netamountintransactioncurrency as NetAmount,
@UI: {
lineItem: {position: 20, importance: #HIGH}
}
SOLItems.taxamountintransactioncurrency as TaxAmount,
SOLItems.productavailabilitystatus as StatusAvailability,
SOLItems.opportunityitem as OpportunityItem
}
16 – Save and activate. In the annotation file, if you refresh it and switch to the Z_SAMPLE_DEMO_SOLI entity, you should see this
17 – Let’s run the application now and check what we have done so far
18 – The application looks quite promising. We still cannot see the buttons for creating, updating and deleting records. This can be achieved by adding the following @ObjectModel annotation to the beginning of the Z_SAMPLE_DEMO_PRODUCTS view:
@AbapCatalog.sqlViewName: ‘Z_VW_PRODUCTS’
@AbapCatalog.compiler.compareFilter: true
@AccessControl.authorizationCheck: #CHECK
@EndUserText.label: ‘Products’
@OData.publish: true
@ObjectModel: {
createEnabled: true,
updateEnabled: true,
deleteEnabled: true
}
@UI.headerInfo:{
typeName: ‘Product’,
typeNamePlural: ‘Products’,
imageUrl: {value: ‘PictureUrl’},
title: {value: ‘Name’},
description: {value: ‘Description’}
}
define view Z_Sample_Demo_Products
….
19 – Save and activate. Now the application looks like this:
20 – For products pictures we need to add to the web app folder a subfolder named images containing all the images named as the products
21 – The application looks like this
22 – Unfortunately we cannot add Facets to our CDS view: this is not yet supported. In order to add them we need to do it directly in the annotation file with the AM.
The process is the same I showed in the blog here.
23 – For example we can add a UI.HeaderFacet term containing 3 UI.ReferenceFacets and a UI.Facet containing a UI.CollectionFacet with 2 UI.ReferenceFacets within and another UI.ReferenceFacet
24 – Running the application you should get something like this:
25 – We are done now with your Smart Template application based on CDS Views. You should have learnt now how to create a new CDS view, how to inject annotations terms in it, how to create a new application is SAP Web IDE and how to enhance the annotation coming from the service with other annotation terms.
Congratulations! You have successfully created your first Smart Template app based on CDS views!
Great blog. Would be nice to know
1. How to hook data from tables before going to UI?
2. How to handle editing/creating using BOPF framework (hook to handle creation/editing logic)?
Hello, I am trying to develop fiori apps by smarttemplate. but now I have the question that how to edit and create new record by the add button on the template?There is always occurring the error:"no data found" .
Have you found out the solution? I will be appreciated to know the answer.
Excellent blog buddy!!!!
Very good blog. One of the best explaining CDS/Odata Exposure. One open question: Is it possible to have language dependant labels in CDS? You hardcoded the labels in english but they are potentially needed in other languages? How can I achieve this?
Thank you for the blog. It had just the right info to build a ST from scratch. I built my first ST app. 🙂
If I may offer a suggestion, could you add more snapshots or explain in more detail what cds annotations like dataPoint, identification, statusInfo, etc do when touching on these topics inside the blog. It was evident once I added the annotations but i would have preferred more info on what I am doing before I did anything. For example, what does dataPoints do and where can I see them in the Fiori app. Its not an essential but nice to have item.
Thanks again.
P.S.If someone else had a similar issue you can view the descriptions of cds ui annotations here.
Superb Blog..very well explained ...Thanks a ton
Smriti
How can I create Facet then ReferenceFacets and CollectionFacet by CDS annotation like @ui.facet : [{...}] and what next?
Hi Mykola,
i wanted to ask you if you got an asnwer to your question becuase i have the exakt same problem and cant find anything...
thanks in advance (:
@UI.facet: [{ purpose: #HEADER}] as the top node is the key for anyone else searching <.<
Hi.
I've found solution and it looks like:
Hi Mykola Chekalov,
You can also check this blog for more information
https://blogs.sap.com/2019/02/08/myinbox-ui-generation-using-cds-views-and-ui.facet-annotation
Regards,
Mahesh
Hi SIMMACO FERRIERO,
Please saw this issue and give your input. https://answers.sap.com/questions/13874087/gl-account-line-items-gl-view-application-gl-accou.html?url_id=text-global-profile-inbox-mod
It has cds view.
Thank you.
Gayathri