Skip to Content

In Fiori Elements – Develop a List Report Basic Approach we looked at the simplest way to create a List Report using an OData service based on a purpose built CDS view with all of the annotations pre-set.  In this blog we look at alternate approach when you have an OData service without any pre-set annotations.  You can also use this approach to override or supplement pre-set annotations.

Find other Fiori Elements blogs on the Fiori Elements wiki

What are annotations?

In my first blog I described them as … “comments on the OData service that provides the data”.

The official OData site gives them a formal definition as:

Metadata annotations can be used to define additional characteristics or capabilities of a metadata element, such as a service, entity type, property, function, action or parameter.”

I find it more helpful to think of them as adding formalised semantic meaning to OData entities. In other words the annotations describe the purpose and intent of the OData entity and its attributes in a way that can be used directly by programs (and, happily, humans).

As mentioned in previous blogs, annotations are an optional part of OData.  The available annotations are described using an OData vocabulary.  For example, SAP has a vocabulary of all annotations that can be used in ABAP CDS views.  Some of these annotations are UI annotations that we can use to build our List Report.  Other annotations have other purposes such as @OData.Publish:true which exposes a CDS view as an OData Service. When it comes to UI Annotations, there are quite a lot of them… so we’ll start with a focus on the essentials for List Reports.

Creating a Fiori Element List Report with Annotations XML

Before we start, it’s worth noting that while its UI annotations let us control most of the List Report, not everything can be controlled by UI annotations. Certain features depend on what the OData Service itself provides, e.g. we can only provide a keyword search in the List Report Filter bar if the OData Service EntitySet contains the semantic marker sap:searchable=”true”. Features such as create, update, delete are provided in a similar way.

So how does using an annotations XML file change our process for creating a List Report which in Fiori  Elements – How to develop a List Report – Basic Approach as:

  1. Prepare the OData service
  2. Prepare the UI Annotations
  3. Create the Fiori App using the Fiori Elements List Report template

The pre-requisites are still the same, and the process itself is essentially the same, it’s just a slight change in the order of the steps:

  1. Prepare the OData service
  2. Create the Fiori App using the Fiori Elements List Report template
  3. Prepare the UI Annotations

So to show how this works, we’ll start with an OData Service without any UI annotations.  To demonstrate that this is really the only difference we will again use an OData Service based on a CDS view, although as mentioned in my previous blog, CDS views are not a pre-requisites – just very easy to use.

This time our OData Service is similar to our previous example but without any UI annotations and looks like this:

Creating the Fiori App in the HCP Web IDE using the Fiori Elements List Report wizard works exactly the same way. The only difference is which service and entity we select for the report. Now if you are using a SAP system that supports annotations it will still show you an annotation file, it’s just that the file will be generated with a  very basic XML structure.

Because there are no annotations yet, if you run the Component.js file of your app it will look something like this:

Working with the Annotations XML file

To work with our local annotations file we first need to check we have one. If you have used the wizard then it should exist already, but not everyone has access to HCP Web IDE or Personal Web IDE, so let’s review again where this lives in the recommended SAPUI5 app structure.

In our app we should see a folder called “annotations”. This should be a sub-folder of “webapp”.  If not we can always create one, e.g. using the context menu of folder “webapp” and selecting New > Folder.

Next we check there is a file called annotations.xml in our project’s annotations folder. If not we can create one using the context menu of folder “annotations” and selecting New > Annotation File.

Tip: It’s important to use the New > Annotation file wizard, and not just create the file using New > File.  The Annotation file wizard will not only create an annotations xml file, it will fill it with the basic edmx tags needed to start annotating. This is an example of an annotations.xml file generated this way:

The annotation file wizard will also update the manifest.json file to make sure our app:

  1. Knows where the annotation file sits in the project hierarchy and exactly what the file is called
  2. Knows where to find text resources (i18n.properties) related to your annotations file
  3. Links the OData Service to the related annotation xml file

As a reminder, we looked at the manifest.json file and its contents in the Fiori  Elements – How to develop a List Report – Basic Approach blog.

Tip: The annotations file doesn’t need to be called annotations.xml – although it does need to be a XML file.  If we use a different file name then we need to adjust the manifest.json file to match.

We can edit the annotations file directly using the Code Editor or, in the HCP Web IDE, we can use the Annotation Modeler tool. The Annotation Modeler uses a HCP Web IDE plugin so it is only available in the HCP Web IDE, so it’s always worth knowing the XML format itself.  In this blog for simplicity we will show the annotation modeler and related XML snippets.

You’ll find XML snippets for the different annotations in the SAPUI5 SDK in the section Developing Apps with SAP Fiori Elements > Annotations Relevant for List Reports and Object Pages, and Annotations Relevant for List Reports.

Annotations of the Fiori Element List Report

We can see in the SAPUI5 SDK that there are several UI annotations relevant to the List Report, but fortunately there are only 3 we need to create a basic List Report and these are:

  • UI.HeaderInfo – for the list table header
  • UI.LineItem – for the list table contents
  • UI.SelectionFields – for the filter bar fields

They relate to the List Report as follows:

Before we add any annotations our annotations.xml file looks like this in the annotation modeler.

In the Code Editor, if we’ve used the Fiori Elements List Report wizard, the relationship to our OData Service will already be added to the  tag of our annotations.xml file and will look like this:

All of our following annotations will need to be placed within a <Schema> tag for our OData Entity Set within the <edmx:DataServices> tag like this:

We use the + icon in the action columns to add extra annotations.

Adjusting the UI.HeaderInfo Annotations

The easiest annotation to add is the UI.HeaderInfo that adds the description and count to the table header of our List Report.  All we need to do is to enter the mandatory fields TypeName and TypeName Plural.  We can see in the Key Information column that these are immediately added to i18n property files.

It’s also mandatory to enter a value for the Title annotation which is a child of UI.HeaderInfo. This annotation will actually be used for the related Object Page which will we cover in a future blog.

In the code editor these annotations will look like this:

Adjusting the UI.LineItem Annotations

The UI.LineItem annotations denote which fields should be columns in our list report table.  There are different types of columns we can use – text, numbers, date/time, amount with currency, quantity with unit, urls, buttons, rating stars, progress bars, etc.  Once again we start with the simplest approach which is to use simple typed data fields, such as text and number fields.  For this we select the + action next in the UI.LineItem and choose the child annotation DataField.

In the DataField annotation we use the Value dropdown select the matching entity attribute and add a Label for the column header. The annotation modeler automatically adds the Labels to the @i18n properties file, or we can select an existing text from the file for our Label. We repeat this for as many columns as we want to add.

In the code editor these annotations will look like this:

Adjusting the UI.SelectionFields Annotations

We add the fields we want in our filter bar in the UI.SelectionFields annotations.  We use the SelectionFields dropdown to select attributes of our EntitySet. We use the Add Path option to add more filter fields.

In the code editor these annotations will look like this:

Running the app

Having saved all the UI annotations we have added, we can now run our App from the Component.js file. It should look like this:

Once again it’s a fully functioning production quality List Report app, complete with personalization settings (check out the gear wheel icon at the top right of the table) so users can adjust the filters, sort order, and groupings.

Basic vs. Alternate Approach

So which approach is preferred – basic approach or local annotations? Certainly if you have an environment capable of producing annotated CDS views and you are creating views explicitly for a given list report it makes sense to keep the annotations aligned against the CDS view. Otherwise local annotations work just fine.

In the next blog we’ll look at how we can make the list report even more useful.  We can control features such as the table type, single or multi-selection of rows, filter variant management, and default sort order.

We can also add some graphical visualizations to make the information in our report easier to understand such as thumbnail images, status icons, rating stars and progress bars.   These are techniques we’ll be able to reuse when we look at the Object Page in a future blog.

To report this post you need to login first.

49 Comments

You must be Logged on to comment or reply to a post.

    1. Jocelyn Dart Post author

      Yes! That’s Object Page… only holding off a little as that gets us into deeper architecture discussions which will make more sense once we’ve discussed codeless navigation options

      (0) 
  1. Helmut Tammen

    Really a great tutorial. Thank you for that. I already waited for something like this.

    When I implemented an application with my own OData service everything worked fine except displaying the texts from ResourceModel (i18n.properties). The texts are simply not available even though ResourceModel is defined in manifest.json, texts are available in i18n.properties and annotation definition looks ok (see here for screenshots).
    Any ideas?

    Thanks Helmut

    (0) 
    1. Jocelyn Dart Post author

      Hi Helmut
      ok so I’m guessing you created you project structure & manifest.json by hand? Brave!
      When we generate using the wizard the i18n model itself is referenced with thd model name @i18n in the manifest.json as well.  Do that & your references to @i18n properties should come through
      Let us know how you go
      Jocelyn

      (0) 
      1. Helmut Tammen

        Hi Jocelyn,
        I also used the wizard to create the app.
        It created the i18n model like this (without the @):

        “i18n”: {
        “type”: “sap.ui.model.resource.ResourceModel”,
        “uri”: “i18n/i18n.properties”
        },

        When I changed the model name to “@i18n” the texts were displayed. Already wondered about the strange i18n model name :-D.

        Thanks a lot
        Helmut

        (1) 
          1. Former Member

            Thanks for the information.

            I added the model @i18n to the manifest.json file and it worked correctly.

            “models”: {
            “i18n”: {
            “type”: “sap.ui.model.resource.ResourceModel”,
            “uri”: “i18n/i18n.properties”
            },
            “@i18n”: {
            “type”: “sap.ui.model.resource.ResourceModel”,
            “uri”: “i18n/i18n.properties”
            },

             

            Best Regards,

            Emanuel

            (0) 
  2. Former Member

    Hi Jocelyn,

    This is an awesome post and really helpful.

    I want to ask is there something different to be done when creating the application using a local mock service(Mock service created using edmx file).

    I created the List Report application using template and my mock service. I then tried to create the local annotation by following your blog but was unable to do so using the Annotation Modeller wizard as it was not detecting my local service.I then manually added the schema of the service in code editor of the Annotation modeler and was able to create annotations.

    The manifest.json  file was also updated accordingly to pick the annotation file.

    But when I test the application using Mock data the annotation file is not picked up. I had to manually add the column in the application.

    Can you please suggest if there is something different to be done when creating application using local Mock service?

    This would be really helpful as many folks are working on Demo apps,using the local mock service,to approach the respective clients.

    Cheers!!

    (1) 
  3. Former Member

    Excellent article Jocelyn.
    It was very useful for me to decide which approach to take between “Local UI Annotations” and “Service UI Annotations”.

    Thanks!
    Best Regards,

    Emanuel

    (1) 
  4. Holger Schäfer

    Thank you for the great intro Jocelyn,

    i am currently working on some CDS on S/4HANA 1610 SP0 and run into issues with aggreations and the List Report Viewer.

    After some investigation the List Report Template seems to always use an OData merge select of the used columns and also the columns defined as UI.LineItem.

    If i later change visible columns to aggregate only on one column and get the @Agregation SUM for netvalue, i will get a lot of rows, because the odata request selects always all ListItem columns even if they are not shown on UI Table?!?

    Is this by design or mayber a bug?

    My current solution is skip using ListItems and later on add them manually, but from my point of view this is a bug and should be handled in the fiori list report viewer app, because you will get the wrong results using default ListItem.

    For me the ListItem should only define the initial set of shown columns, but when i change them and store the new set as variant in the LREP, i would expect the correct results.

    Maybe you are also familar with this topic and knows if this is a bug or behaves by design (for a reason that i do not know 😉

    Regards Holger

    (0) 
    1. Jocelyn Dart Post author

      Hi Holger,

      Hmmm… I am not sure if I have understood you?

      Can you give some code examples or screenshots?

      Have you tried setting the annotations in the CDS view or metadata extension of a CDS view to see if that resolves  your concern?

       

       

      (0) 
  5. Former Member

    Thanks for the post Jocelvn.

    I am trying to implement UI annotation for smart table – the requirement is to restrict the columns appearing in the table personalization button. This I am trying to do by setting sap:visible to true. But where I need to do this is not clear.

    In backend oData entity I could not find any property like sap:visible (unlike for updatable, creatable, etc.). Also in UI annotations, I could not find any option like visible (unlike headerInfo, LineItem, etc.).

    Could you please help me in the same please.

     

    Thanks,

    Bhoomika

    (0) 
    1. Jocelyn Dart Post author

      Hmmm… ok Bhoomika.

      I would suggest that most CDS experts would say the best way to do that would be NOT to include it in your ABAP CDS Consumption View in the first place.  After all that is kind of why we have the layers of Dictionary table refined by Interface view refined by Consumption view.

      However if you really need it in your Consumption View for technical reasons you could try @UI.Hidden as per Field Hiding https://help.sap.com/viewer/cc0c305d2fab47bd808adcad3ca7ee9d/7.51.2/en-US/1104003411cf44c79f07baf963742ede.html

      (0) 
    1. Jocelyn Dart Post author

      Hi Neil,

      That is something I am currently working on.  As a hint… table types are handled in a few ways:

      1. In the CDS view the view may be marked as an aggregation – this flips the table type to “grid”
      2. You can override the table type in the manifest.json file… with restrictions
      3. Tree hierarchy tables are a special kind of grid table when you set a GroupBy presentationvariant. This lets you display totals and subtotals for instance

      More info in the SAPUI5 SDK https://sapui5.hana.ondemand.com/#docs/guide/7f844f1021cd4791b8f7408eac7c1cec.html

      Rgds

      Jocelyn

      (0) 
  6. Former Member

    Hi Jocelyn,

    I am working on List Report template and I have to add progress bars in the table columns.

    Can you tell how that can be implemented?

     

    Thanks

    Manpreet

    (0) 
    1. Jocelyn Dart Post author

      Hi Lars,

      There actually is – you can specify that the data is loaded immediately on entry to the transaction rather than pressing go.

      You can do this by using the UI Adaptation editor in the Web IDE as I explain in Fiori elements – export to MS Excel via the UI Adaptation Editor and using it to select the smart table and change Enable Auto Binding to true.

      HOWEVER be careful before setting this that you have considered the performance implications as the size of your data grows.  If the user may need to filter the data anyway you could have them waiting a while for nothing.

      Rgds

      Jocelyn

       

      (0) 
  7. Former Member

    Hi Jocelyn,

     

    I have applied Intent based navigation to open another Fiori App to one of my fields in the CDS view . But I need to open the new app with multiple selection already applied . Eg: The new app is opened by clicking on document number but the document which should open in FB03 should be selected by doc no + fiscal Year + company code and then open up . Can you provide an update how this can be achieved as i am not able to provide more than 1 key during navigation from cds view.

     

    Regards,

    Rishabh

    (0) 
  8. Arunava Mukherjee

    Hi Jocelyn,

    Thank you very much for the detailed and nice description.

    In one of my project I am using the List Report template where I do need to format the time in Hour:Minute:Second format. Say for example we are getting data from odata only in minutes. So how to and where to plugin the formatter function for this.

    Thank you in advance.

    (0) 
      1. Arunava Mukherjee

        Hi Jocelyn,

        Thank you very much for the reply. But what we want is just to specify or use our own custom formatter function in ListReport template. The time example which I mentioned is definitely one use case but that is not the only thing we want to do.

        So this is very much helpful for  us to have a way to plugin our custom formatter function in UI5 library template projects.

        Our Expectation is to have something like this. Specifying custom formatter, but in annotation.xml

         <Text text="{
                        path: '/this_Is_the_binding',
                        type: 'sap.ui.model.type.DateTime',
                        formatOptions: {
                            pattern: 'yyyyMMdd HHmmss'
                        }
                    }" />
        (0) 
  9. Tanveer Shaikh

    Hi Jocelyn,

    I am trying to build a navigation from List report line item document number to some other app – i.e have document number as link

    Snippet from local annotations  in UI.LineItem-

    <Annotation Term="UI.LineItem">
      <Collection>
         <Record Type="UI.DataField">
           .
           .
           .
    <Record Type="UI.DataFieldForIntentBasedNavigation">
         <PropertyValue Property="SemanticObject" String="MySalesOrder"/>
         <PropertyValue Property="Inline" Bool="true"/>
         <PropertyValue Property="Label" String="Manage"/>
         <PropertyValue Property="Action"  String="display"/>
    </Record>
       </Collection>
    </Annotation>

    Doesn’t work. ofcourse I am missing something, but didn’t find any blog/reference/KBA  – Can you please help ?

    I am using all local annotations in annotation modeler with xsodata, No ABAP CDS.

    Thanks,

    Tanveer

    (0) 
    1. Jocelyn Dart Post author

      Hi Tanveer

      One for another day…  short version… all of the properties of that row are passed as parameters, plus the header content and some other stuff.

      In the Launchpad Designer, you configure a tile catalog with a tile to your app, and a target mapping to the app *and* to the intent you used for your inline button.  When you configure the target mapping to the inline button, the parameter names are whatever the target app uses, and the parameter values reference the properties of your list.

      Try comparing it to some of the delivered tile catalogs – any of the Manage apps should do – and you’ll get the idea

      Good luck!

      Jocelyn

      (0) 
      1. Tanveer Shaikh

         

        HI Jocelyn,

        Thanks for reply –  I understand the part of launchpad designer but I think I am missing something from List Report annotations side.

        I used UI.DataFieldForIntentBasedNavigation under UI.LineItem, is that correct ? any other annotations I need to add ? Can this be done without extension ? What All configs will be required in maifest.json ? Also, how to make document number field the ‘hyperlink’  type look ?

        Thanks for your help !

        Thanks,

        Tanveer

         

        (0) 
        1. Jocelyn Dart Post author

          Hi Tanveer,

          You can use DataFieldForIntentBasedNavigation or DataFieldWithIntentBasedNavigation – “for” shows it as a button, the “with” variation turns the field into a hyperlink.

          No you do not need extensions.

          Use the outbounds section within sap.app in the manifest.json to define your navigation parameters for the Semantic Object.  Find out more here Configuring Navigation

          I’ll try and get a blog out explaining more soon.

          Rgds,

          Jocelyn

          (0) 
  10. Pradeep V

     

    Hi Jocelyn,

    Great Blog, Thank you so much for sharing the knowledge, I have created a report with the list report template and i have a requirement to display a text message on the report , and keep it forever on the report just like a note or something like that, Is there any way to do so?

     

    Regards,

    Pradeep

    (1) 
    1. Jocelyn Dart Post author

      Hi Pradeep, That sounds like you need to write some data back to the database so it is kept? Then you want to look at changing your read only List Report to a read/write transactional app using BOPF as per the ABAP Programming model for SAP Fiori. Take a look at the tutorial Developing New Transactional Apps 

      Good luck!

      Jocelyn

      (0) 
      1. Jocelyn Dart Post author

        Just another thought – technically you could also use an inline action in the table and a breakout extension to do that.   However that requires more knowledge and skill to pass the field to an OData Service function to store it.

        (0) 
      2. Pradeep V

        HI Jocelyn,

        Thank you for the reply and i do not have to write back to the database, i just want display a  message on top of the report, i mean a text on UI from the controller like “The date expires on this month end” something like that on somewhere on the report, since it is a smart list report template i have extended the controller to write custom functions, so i am fetching validity from the odata service and i just want to put the validity date somewhere on the report.

         

        Thanks in advance,

        Pradeep

        (1) 
          1. Pradeep V

             

            Hi Jocelyn,

             

            Extending a controller and Action to a list report is worked for me, I have done changes as follows:

            		"extends": {
            			"extensions": {
            				"sap.ui.controllerExtensions": {
            					"sap.suite.ui.generic.template.ListReport.view.ListReport": {
            						"controllerName": "MyReport.ext.controller.ListReportExt",
            						"sap.ui.generic.app": {
            							"EntitySetName": {
            								"EntitySet": "EntitySetName",
            								"Actions": {
            									"ReportDate": {
            										"id": "ReportDate",
            										"text": "",
            										"press": "onPressReportDate"
            									},
            									"ActionEntitySetName1": {
            										"id": "Actionbutton",
            										"text": "{@i18n>Action1}",
            										"press": "onDownload",
            										"requiresSelection": false
            									}
            								}
            							}
            						}
            					}
            				}
            			}
            		}
            
            
            In controller extension onInint method:
            
            this.getView().byId("ReportDate").setText("My Text");

             

            I am just adding a text to action button ReportDate which will display on the table and on press i am routing to corresponding App.

             

            Thanks for the help Jocelyn 🙂

             

            Best Regards,

            Pradeep

            (0) 
            1. Jocelyn Dart Post author

              Great – please write a blog on what you did !  And let me know … I’ll add it into our Fiori elements wiki so you will be recognized there as well!

              (1) 
      1. Akshaya Parthasarathy

        Hi Jocelyn

         

        I read the document. I have added another pages array in manifest and the navigation carousel appears but in the next navigated page, though I have configured to display a table, nothing comes up. Do you have any examples to help?

        (0) 
  11. Akshaya Parthasarathy

    Hi Jocelyn,

    I have created a list report and bound to an oData entity set. But in my table the data group is repeating on scroll. The batch is called again on scroll. Can you help?

    (0) 
    1. Jocelyn Dart Post author

      Hi Akshaya

      Please use blog comments only for comments on the blog itself. If you have related issues raise them in answers.sap.com with the appropriate tags such as Fiori or SAP Fiori for SAP S/4HANA.

      And always give us the context of your query – such as what SAPUI5 version are you on, what release system is your OData Service running on, is it a SAP or non-SAP OData Service,  if it’s a SAP OData Service did you create it in transaction SEGW or using a CDS View.

      One big tip – always test your OData Service independently of your UI – if the OData Service does not behave correctly, then of course the Fiori app that is running on top of that won’t work correctly either.  So test and fix the OData Service first.

      Hope that helps

      Jocelyn

      (0) 
  12. Divi Srilaxmi

    Hi Jocelyn,

     

    Thank you for the information, It was really helpful.

     

    I am facing one issue with selection fields description,  In my case the selection field name is “BELNR” (The same name is coming from odata service) But I wanted to add a field description for BELNR. I have tried with Label

    The generated code is :

    <Annotation Term=”UI.SelectionFields”>
    <Collection>
    <PropertyPath>BELNR<Annotation Term=”Common.Label” String=”{@i18n&gt;ACCOUNTING_DOCUMENT_NUMBER}”/>
    </PropertyPath>

     

    But it is not working, I am unable to see the selection field on the screen after adding the label. Could you please help me in this?

     

    Thanks,

    Srilaxmi

    (0) 

Leave a Reply