- 
                Notifications
    
You must be signed in to change notification settings  - Fork 1
 
UI Annotations
        Ankit Kumar Singh edited this page Sep 9, 2025 
        ·
        3 revisions
      
    The UI Annotations Layer defines how CDS projection views are rendered in SAP Fiori Elements applications.
Instead of writing custom UI code, you configure the UI behavior directly from CDS using metadata extensions. This approach enables rapid, consistent, and maintainable Fiori UIs.
In this project, metadata extensions are provided for:
- 
Vehicle Projection (
ZAKS_P_ROOT_VEHICLE) - 
Trip Projection (
ZAKS_P_CDS_TRIP) - 
Maintenance Projection (
ZAKS_P_CDS_MAINTENANCE) 
@Metadata.layer: #CORE
@UI: {
    headerInfo : {
        typeName: 'Vehicle',
        typeNamePlural: 'Vehicles',
        title: { type: #STANDARD, label: 'Vehicle', value: 'VehicleId' }
    },
    presentationVariant: [
        { sortOrder: [{ by: 'VehicleId', direction: #DESC }] }
    ]
}
annotate view ZAKS_P_ROOT_VEHICLE with
{
    @UI.facet: [
        { id: 'Vehicle', purpose: #STANDARD, type: #IDENTIFICATION_REFERENCE, label: 'Vehicle', position: 10 },
        { id: 'Trip', purpose: #STANDARD, type: #LINEITEM_REFERENCE, label: 'Trip', position: 20, targetElement: '_Trip' },
        { id: 'Maintenance', purpose: #STANDARD, type: #LINEITEM_REFERENCE, label: 'Maintenance', position: 30, targetElement: '_Maintenance' }
    ]
    @UI.hidden: true
    VehicleUUID;
    @UI: { lineItem: [{ position: 10, label: 'Vehicle ID' }],
           identification: [{ position: 10, label: 'Vehicle ID' }],
           selectionField: [{ position: 10 }] }
    VehicleId;
    @UI: { lineItem: [{ position: 20, label: 'Registration No' }],
           identification: [{ position: 20, label: 'Registration No' }],
           selectionField: [{ position: 20 }] }
    RegdNo;
    @UI: { lineItem: [{ position: 30, label: 'Vehicle Type' }],
           identification: [{ position: 30, label: 'Vehicle Type' }],
           selectionField: [{ position: 30 }] }
    VehicleType;
    @UI: { lineItem: [{ position: 40, label: 'Brand' }],
           identification: [{ position: 40, label: 'Brand' }] }
    Brand;
    @UI: { lineItem: [{ position: 50, label: 'Model' }],
           identification: [{ position: 50, label: 'Model' }] }
    Model;
    @UI: { identification: [{ position: 60, label: 'Date of Purchase' }] }
    PurchaseDate;
    @UI: { lineItem: [{ position: 60, label: 'Price' }],
           identification: [{ position: 70, label: 'Price' }] }
    CostPrice;
    @UI: { lineItem: [{ position: 70, label: 'Currency' }],
           identification: [{ position: 80, label: 'Currency' }] }
    Currency;
    @UI: { identification: [{ position: 90, label: 'Fuel Type' }] }
    FuelType;
    @UI: { lineItem: [{ position: 80, label: 'Capacity' }],
           identification: [{ position: 100, label: 'Capacity' }] }
    Capacity;
    @UI: { lineItem: [{ position: 90, label: 'Unit' }],
           identification: [{ position: 110, label: 'Unit' }] }
    CapacityUnit;
    @UI: { identification: [{ position: 120, label: 'Status' }] }
    Status;
    @UI: { lineItem: [{ position: 100, label: 'Plant ID' }],
           identification: [{ position: 130, label: 'Plant ID' }] }
    Plant;
    @UI: { identification: [{ position: 140, label: 'Created By' }] }
    CreatedBy;
    @UI: { identification: [{ position: 150, label: 'Created On' }] }
    CreatedOn;
}- 
@UI.headerInfo: Controls the object page header (singular/plural entity names, title field) - 
@UI.facet: Groups UI sections (Identification, Trip, Maintenance)- Vehicle: Identification fields
 - Trip: Line item reference to child trips
 - Maintenance: Line item reference to child maintenance records
 
 - 
@UI.lineItem: Fields shown in table (list report) - 
@UI.identification: Fields on the object page details section - 
@UI.selectionField: Fields available for filtering/search - 
@UI.hidden: Hides technical fields (e.g.,VehicleUUID) from the UI 
@Metadata.layer: #CORE
@UI: {
    headerInfo : {
        typeName: 'Trip',
        typeNamePlural: 'Trips',
        title: { type: #STANDARD, label: 'Trip', value: 'TripId' }
    },
    presentationVariant: [
        { sortOrder: [{ by: 'TripId', direction: #DESC }] }
    ]
}
annotate view ZAKS_P_CDS_TRIP with
{
    @UI.facet: [
        { id: 'Trip', purpose: #STANDARD, type: #IDENTIFICATION_REFERENCE, label: 'Trip', position: 10 }
    ]
    @UI.hidden: true
    TripUUID;
    @UI: { lineItem: [{ position: 10, label: 'Trip ID' }],
           identification: [{ position: 10, label: 'Trip ID' }],
           selectionField: [{ position: 10 }] }
    TripId;
    @UI.hidden: true
    VehicleId;
    @UI.hidden: true
    VehicleUUID;
    @UI: { lineItem: [{ position: 20, label: 'Driver ID' }],
           identification: [{ position: 20, label: 'Driver ID' }] }
    DriverId;
    @UI: { lineItem: [{ position: 30, label: 'Origin' }],
           identification: [{ position: 30, label: 'Origin' }] }
    Origin;
    @UI: { lineItem: [{ position: 40, label: 'Destination' }],
           identification: [{ position: 40, label: 'Destination' }] }
    Destination;
    @UI: { identification: [{ position: 50, label: 'Journey Start Date' }] }
    StartDate;
    @UI: { identification: [{ position: 60, label: 'Journey End Date' }] }
    EndDate;
    @UI: { lineItem: [{ position: 50, label: 'Distance in KM' }],
           identification: [{ position: 70, label: 'Distance in KM' }] }
    DistanceKm;
    @UI: { lineItem: [{ position: 60, label: 'Trip Cost' }],
           identification: [{ position: 80, label: 'Trip Cost' }] }
    total_trip_cost;
    @UI: { lineItem: [{ position: 70, label: 'Currency' }],
           identification: [{ position: 90, label: 'Currency' }] }
    Currency;
    @UI: { lineItem: [{ position: 80, label: 'Cargo Type' }],
           identification: [{ position: 100, label: 'Cargo Type' }] }
    CargoType;
    @UI: { identification: [{ position: 110, label: 'Created By' }] }
    CreatedBy;
    @UI: { identification: [{ position: 120, label: 'Created On' }] }
    CreatedOn;
}- 
@UI.headerInfo: Defines how trips appear in the object page header - 
@UI.facet: Creates a dedicated "Trip" identification section - 
@UI.lineItem: Trip details shown in table/list report - 
@UI.identification: Trip details shown on the object page - 
@UI.selectionField: Enables filtering byTripId - 
@UI.hidden: Hides technical keys (TripUUID,VehicleId,VehicleUUID) from UI 
@Metadata.layer: #CORE
@UI: {
    headerInfo : {
        typeName: 'Maintenance',
        typeNamePlural: 'Maintenance',
        title: { type: #STANDARD, label: 'Maintenance', value: 'MaintId' }
    },
    presentationVariant: [
        { sortOrder: [{ by: 'MaintId', direction: #DESC }] }
    ]
}
annotate view ZAKS_P_CDS_MAINTENANCE with
{
    @UI.facet: [
        { id: 'Maintenance', purpose: #STANDARD, type: #IDENTIFICATION_REFERENCE, label: 'Maintenance', position: 10 }
    ]
    @UI.hidden: true
    MaintUUID;
    @UI: { lineItem: [{ position: 10, label: 'Maintenance ID' }],
           identification: [{ position: 10, label: 'Maintenance ID' }],
           selectionField: [{ position: 10 }] }
    MaintId;
    @UI.hidden: true
    VehicleId;
    @UI.hidden: true
    VehicleUUID;
    @UI: { lineItem: [{ position: 20, label: 'Service Date' }],
           identification: [{ position: 20, label: 'Service Date' }] }
    ServiceDate;
    @UI: { lineItem: [{ position: 30, label: 'Service Type' }],
           identification: [{ position: 30, label: 'Service Type' }] }
    ServiceType;
    @UI: { lineItem: [{ position: 40, label: 'Workshop Name' }],
           identification: [{ position: 40, label: 'Workshop Name' }] }
    WorkshopName;
    @UI: { lineItem: [{ position: 50, label: 'Servicing Cost' }],
           identification: [{ position: 50, label: 'Servicing Cost' }] }
    ServiceCost;
    @UI: { lineItem: [{ position: 60, label: 'Currency' }],
           identification: [{ position: 60, label: 'Currency' }] }
    Currency;
    @UI: { lineItem: [{ position: 70, label: 'Odometer Reading in KM' }],
           identification: [{ position: 70, label: 'Odometer Reading in KM' }] }
    OdometerReading;
    @UI: { lineItem: [{ position: 80, label: 'Parts Changed/Repaired' }],
           identification: [{ position: 80, label: 'Parts Changed/Repaired' }] }
    PartsChanged;
    @UI: { lineItem: [{ position: 90, label: 'Warranty Claimed' }],
           identification: [{ position: 90, label: 'Warranty Claimed' }] }
    WarrantyClaim;
    @UI: { lineItem: [{ position: 100, label: 'Next Servicing Date' }],
           identification: [{ position: 100, label: 'Next Servicing Date' }] }
    NextServiceDate;
    @UI: { lineItem: [{ position: 110, label: 'Material Number' }],
           identification: [{ position: 110, label: 'Material Number' }] }
    MaterialNumber;
    @UI: { lineItem: [{ position: 120, label: 'Vendor ID' }],
           identification: [{ position: 120, label: 'Vendor ID' }] }
    VendorNumber;
    @UI: { identification: [{ position: 130, label: 'Created By' }] }
    CreatedBy;
    @UI: { identification: [{ position: 140, label: 'Created On' }] }
    CreatedOn;
}- 
@UI.headerInfo: Defines object header for Maintenance records - 
@UI.facet: Groups all maintenance fields under a section - 
@UI.lineItem: Fields shown in maintenance list report - 
@UI.identification: Fields shown on the maintenance object page - 
@UI.selectionField: Enables filtering/search byMaintId - 
@UI.hidden: Excludes technical keys (MaintUUID,VehicleUUID,VehicleId) from UI 
- Facets define logical sections on object pages.
 - Header Info controls how the entity is displayed in Fiori apps.
 - Line Items: fields visible in list reports.
 - Identification: fields visible in the object page details.
 - Selection Fields: fields available for filters/search.
 - Hidden: keeps technical keys out of the UI.
 
With these metadata extensions, your RAP Business Objects are fully prepared for automatic, best-practice SAP Fiori Elements UI generation.
---
π Next: [βοΈ Behavior Definitions](https://github.com/iankitsinghk/fleet-management-system-abap-rap-v1/wiki/Behavior-Definitions)