**TITLE**: Page

**INTRODUCTION**: The Page building block enables you to create a custom page with a pre-defined layout.

**TAGS**: page, layout, structure, container, navigation

**STEP**: Using the Page Building Block

**DESCRIPTION**: You can use the Page building block to create a new page. You can configure the content of the building block as per your requirements.

**LANGUAGE**: XML

**CODE**:
```xml
<mvc:View
	id="application-product"
	height="100%"
	controllerName="sap.fe.core.PageController"
	xmlns="sap.m"
	xmlns:mvc="sap.ui.core.mvc"
	xmlns:macros="sap.fe.macros"
	xmlns:l="sap.ui.layout"
>
	<macros:Page title="Page title" description="Page description" avatarSrc="sap-icon://page">
		<Panel headerText="First content" id="firstContent">
			<l:HorizontalLayout
				id="TileContainerExpanded"
				allowWrapping="true"
				content="{
        			path : '/Travel',
        			filters : [
            			{ path : 'TravelStatus_code', operator : 'EQ', value1 : 'O'}
        			]
    			}"
			>
				<GenericTile
					header="{Description}"
					subheader="{BeginDate}"
					press="onPressed"
					class="sapUiTinyMarginEnd sapUiTinyMarginTop tileLayout"
				>
					<TileContent unit="{CurrencyCode_code}">
						<NumericContent withMargin="false" value="{TotalPrice}" truncateValueTo="6" />
					</TileContent>
				</GenericTile>
			</l:HorizontalLayout>
		</Panel>
		<Panel headerText="Second content" id="secondContent">
			<macros:Table metaPath="/Travel/@com.sap.vocabularies.UI.v1.LineItem" />
		</Panel>
	</macros:Page>
</mvc:View>
```

**STEP**: Using Building Blocks

**DESCRIPTION**: You can use the building blocks in your page as shown in the following example.

**LANGUAGE**: XML

**CODE**:
```xml
<mvc:View
	id="application-product"
	height="100%"
	controllerName="sap.fe.core.PageController"
	xmlns="sap.m"
	xmlns:mvc="sap.ui.core.mvc"
	xmlns:macros="sap.fe.macros"
	xmlns:l="sap.ui.layout"
>
	<macros:Page title="Page title" description="Page description" avatarSrc="sap-icon://page">
		<Panel headerText="First content" id="firstContent">
			<l:HorizontalLayout
				id="TileContainerExpanded"
				allowWrapping="true"
				content="{
        			path : '/Travel',
        			filters : [
            			{ path : 'TravelStatus_code', operator : 'EQ', value1 : 'O'}
        			]
    			}"
			>
				<GenericTile
					header="{Description}"
					subheader="{BeginDate}"
					press="onPressed"
					class="sapUiTinyMarginEnd sapUiTinyMarginTop tileLayout"
				>
					<TileContent unit="{CurrencyCode_code}">
						<NumericContent withMargin="false" value="{TotalPrice}" truncateValueTo="6" />
					</TileContent>
				</GenericTile>
			</l:HorizontalLayout>
		</Panel>
		<Panel headerText="Second content" id="secondContent">
			<macros:Table metaPath="/Travel/@com.sap.vocabularies.UI.v1.LineItem" />
		</Panel>
	</macros:Page>
</mvc:View>
```

Page

page layout structure container navigation


**TITLE**: Paginator

**INTRODUCTION**: The Paginator building block enables you to render paginator buttons in scenarios where users have to navigate through a list of items.

**TAGS**: paginator, pagination, paging, navigation, results

**STEP**: Using the Paginator Building Block

**DESCRIPTION**: To use the Paginator building block, you can include it in your view.

**LANGUAGE**: XML

**CODE**:
```xml
<mvc:View
	id="application-product"
	height="100%"
	controllerName="sap.fe.core.fpmExplorer.paginatorDefault.Paginator"
	xmlns="sap.m"
	xmlns:mvc="sap.ui.core.mvc"
	xmlns:macros="sap.fe.macros"
>
	<Page id="PaginatorPage">
		<customHeader>
			<Toolbar>
				<Title text="Paginator Sample" level="H2" />
				<ToolbarSpacer />
				<macros:Paginator id="paginator" />
			</Toolbar>
		</customHeader>
		<macros:Form metaPath="/Travel/@com.sap.vocabularies.UI.v1.FieldGroup#ApprovalData" id="myForm" title="Travel Data" />
	</Page>
</mvc:View>
```

**STEP**: Initialize the Paginator Building Block

**DESCRIPTION**: To use the paginator building block, you need to initialize it in your controller coding and need to define a list binding and current context.

**LANGUAGE**: TypeScript

**CODE**:
```typescript
import PageController from "sap/fe/core/PageController";
import Paginator from "sap/fe/core/controllerextensions/Paginator";
import type UI5Event from "sap/ui/base/Event";
import type Control from "sap/ui/core/Control";
import JSONModel from "sap/ui/model/json/JSONModel";
import type Context from "sap/ui/model/odata/v4/Context";

/**
 * @namespace sap.fe.core.fpmExplorer.paginator
 */

export default PageController.extend("sap.fe.core.fpmExplorer.paginator.PaginatorController", {
	onBeforeRendering: function (this: PageController): void {
		const list = this.getView()?.byId("travelList");
		if (list) {
			if (!this.getModel("paginatorModel")) {
				// we create a JSON model to hold the list binding and selected row
				const jsonModel = new JSONModel();
				const ownerComponent = this.getOwnerComponent();
				const appComponent = ownerComponent.getAppComponent();
				appComponent?.setModel(jsonModel, "paginatorModel");
			}
		} else {
			// we are in the detail page, so we initialize the paginator with the list binding and selected row
			const paginatorModel = this.getModel("paginatorModel");
			const listBinding = paginatorModel?.getProperty("/listBinding");
			const selectedRow = paginatorModel?.getProperty("/selectedRow");
			this.paginator.initialize(listBinding, selectedRow);
		}
	},

	rowPress: function (this: PageController, event: UI5Event): void {
		const source = event.getSource() as Control;
		const context = source.getBindingContext() as Context;
		// we navigate to the detail page with the context of the selected row
		this.routing.navigate(context);

		// we update the paginator model with the list binding and selected row
		const listBinding = this.getView()?.byId("travelList")?.getBinding("items");
		const paginatorModel = this.getModel("paginatorModel") as JSONModel;
		paginatorModel.setProperty("/listBinding", listBinding);
		paginatorModel.setProperty("/selectedRow", context);
	},

	paginator: Paginator.override({
		onContextUpdate: function (this: PageController, context: Context): void {
			this.getView()?.setBindingContext(context);
		}
	})
});
```

**STEP**: Update the Page Context

**DESCRIPTION**: Once the user navigates to a new page through the paginator, you need to update the view context to reflect the new page's data.

**LANGUAGE**: TypeScript

**CODE**:
```typescript
import PageController from "sap/fe/core/PageController";
import Paginator from "sap/fe/core/controllerextensions/Paginator";
import type UI5Event from "sap/ui/base/Event";
import type Control from "sap/ui/core/Control";
import JSONModel from "sap/ui/model/json/JSONModel";
import type Context from "sap/ui/model/odata/v4/Context";

/**
 * @namespace sap.fe.core.fpmExplorer.paginator
 */

export default PageController.extend("sap.fe.core.fpmExplorer.paginator.PaginatorController", {
	onBeforeRendering: function (this: PageController): void {
		const list = this.getView()?.byId("travelList");
		if (list) {
			if (!this.getModel("paginatorModel")) {
				// we create a JSON model to hold the list binding and selected row
				const jsonModel = new JSONModel();
				const ownerComponent = this.getOwnerComponent();
				const appComponent = ownerComponent.getAppComponent();
				appComponent?.setModel(jsonModel, "paginatorModel");
			}
		} else {
			// we are in the detail page, so we initialize the paginator with the list binding and selected row
			const paginatorModel = this.getModel("paginatorModel");
			const listBinding = paginatorModel?.getProperty("/listBinding");
			const selectedRow = paginatorModel?.getProperty("/selectedRow");
			this.paginator.initialize(listBinding, selectedRow);
		}
	},

	rowPress: function (this: PageController, event: UI5Event): void {
		const source = event.getSource() as Control;
		const context = source.getBindingContext() as Context;
		// we navigate to the detail page with the context of the selected row
		this.routing.navigate(context);

		// we update the paginator model with the list binding and selected row
		const listBinding = this.getView()?.byId("travelList")?.getBinding("items");
		const paginatorModel = this.getModel("paginatorModel") as JSONModel;
		paginatorModel.setProperty("/listBinding", listBinding);
		paginatorModel.setProperty("/selectedRow", context);
	},

	paginator: Paginator.override({
		onContextUpdate: function (this: PageController, context: Context): void {
			this.getView()?.setBindingContext(context);
		}
	})
});
```

**ADDITIONAL RELATED CODE BLOCKS**:

**FILE**: service.cds

**LANGUAGE**: CDS

**CODE**:
```cds
using {
  sap,
  managed,
  Currency,
  Country
} from '@sap/cds/common';

using from '../service/annotations';

@cds.autoexpose  @readonly
aspect MasterData {}

service TravelService {
  @odata.draft.enabled
  @Common.SemanticKey: [TravelID]

  entity Travel : managed {
    key TravelUUID    : UUID;

        @Common.Label          : 'ID'
        @Common.Text           : Description
        TravelID      : Integer default 0                         @readonly;

        @Common.Label          : 'Begin Date'
        BeginDate     : Date;

        @Common.Label          : 'End Date'
        EndDate       : Date;

        @Common.Label          : 'Booking Fee'
        BookingFee    : Decimal(10, 2) default 0                  @Measures.ISOCurrency: CurrencyCode_code;

        @Common.Label          : 'Total Price'
        TotalPrice    : Decimal(10, 2)                            @readonly  @Measures.ISOCurrency: CurrencyCode_code;

        @Common.Label          : 'Currency'
        CurrencyCode  : Association to CurrencyCode default 'EUR' @mandatory;

        @Common.Label          : 'Description'
        Description   : String(1024);

        @Common.Label          : 'Travel Details'
        @UI.MultiLineText
        TravelDetails : String(1024);

        @title                 : 'Status'
        @Common.Text           : TravelStatus.name
        @Common.TextArrangement: #TextOnly
        TravelStatus  : Association to TravelStatus default 'O'   @readonly;

        @title                 : 'Agency'
        @Common.Text           : to_Agency.Name
        @Common.TextArrangement: #TextFirst
        to_Agency     : Association to TravelAgency               @mandatory;

        to_Booking    : Composition of many Booking
                          on to_Booking.to_Travel = $self;
  };

  entity Booking : managed {
    key BookingUUID   : UUID;

        @Common.Label: 'Booking ID'
        BookingID     : Integer                                  @Core.Computed;

        @Common.Label: 'Booking Date'
        BookingDate   : Date;

        @Common.Label: 'Connection'
        ConnectionID  : String(4)                                @mandatory;

        @Common.Label: 'Flight Date'
        FlightDate    : Date                                     @mandatory;

        @Common.Label: 'Flight Price'
        FlightPrice   : Decimal(10, 2)                           @Measures.ISOCurrency: CurrencyCode_code;

        @Common.Label: 'Currency'
        CurrencyCode  : Currency default 'EUR'                   @mandatory;

        @Common.Label: 'Status'
        BookingStatus : Association to BookingStatus default 'N' @mandatory;
        to_Travel     : Association to Travel                    @mandatory;

        PaymentMethod : String(1) default 'B'                    @Common              : {
          Label                   : 'Payment Method',
          Text                    : _Payment.Method,
          TextArrangement         : #TextOnly,
          ValueListWithFixedValues: true,
          ValueList               : {
            Label         : 'Payment Method',
            CollectionPath: 'Payment',
            Parameters    : [{
              $Type            : 'Common.ValueListParameterInOut',
              LocalDataProperty: PaymentMethod,
              ValueListProperty: 'code'
            }]
          }
        };
        _Payment      : Association to one Payment
                          on _Payment.code = PaymentMethod;
  };

  entity Payment {
    key code   : String(1) @(Common: {
          Label          : 'Payment Code',
          Text           : Method,
          TextArrangement: #TextFirst
        });
        Method : String    @(
          Core.Immutable: true,
          Common.Label  : 'Payment Method'
        );
  }

  entity TravelStatus : sap.common.CodeList {
    key code        : String(1) @Common.Text: descr;
        name        : String(255);
        descr       : String(1000);
        criticality : Int16     @odata.Type : 'Edm.Byte' enum {
          Neutral  = 0;
          Negative = 1;
          Critical = 2;
          Positive = 3;
          NewItem  = 5
        };
  };

  entity CurrencyCode : sap.common.CodeList {
        @Common.Label: 'Currency Code'
    key code  : String(3);

        @Common.Label: 'Currency Description'
        descr : String(255);
  };

  entity BookingStatus : sap.common.CodeList {
    key code : BookingStatusCode
  };

  entity TravelAgency : MasterData {
        @Common.Label: 'Agency ID'
        @Common.Text : Name
    key AgencyID       : String(6);

        @Common.Label: 'Agency Name'
        Name           : String(80);
        Street         : String(60);

        @Common.Label: 'Postal Code'
        PostalCode     : String(10);

        @Common.Label: 'City'
        City           : String(40);

        @Common.Label: 'Country Code'
        CountryCode    : Country;

        @Common.Label: 'Phone Number'
        PhoneNumber    : String(30);

        @Common.Label: 'Email Address'
        EMailAddress   : String(256);

        @Common.Label: 'Web Address'
        WebAddress     : String(256);
        Rating         : Integer;
        Recommendation : Integer;
  };

  type TravelStatusCode  : String(1) enum {
    Open     = 'O';
    Accepted = 'A';
    Canceled = 'X';
  };

  type BookingStatusCode : String(1) enum {
    New      = 'N';
    Booked   = 'B';
    Canceled = 'X';
  };
}

```

**FILE**: annotations.cds

**LANGUAGE**: CDS

**CODE**:
```cds
using TravelService as service from '../service/service';

annotate service.Travel {
  TravelStatus @Common.ValueListWithFixedValues;
  CurrencyCode @Common.ValueList: {
    CollectionPath: 'Currencies',
    Parameters    : [
      {
        $Type            : 'Common.ValueListParameterInOut',
        LocalDataProperty: CurrencyCode_code,
        ValueListProperty: 'code'
      },
      {
        $Type            : 'Common.ValueListParameterDisplayOnly',
        ValueListProperty: 'name'
      },
      {
        $Type            : 'Common.ValueListParameterDisplayOnly',
        ValueListProperty: 'descr'
      }
    ]
  };
}

annotate service.Travel with @UI.LineItem: [
  {Value: TravelID},
  {
    $Type : 'UI.DataFieldForAnnotation',
    Target: '@UI.ConnectedFields#TripDates'
  },
  {Value: to_Agency_AgencyID},
  {
    Value             : TravelStatus_code,
    Criticality       : TravelStatus.criticality,
    @UI.Importance    : #High,
    @HTML5.CssDefaults: {width: '10em'}
  },
  {Value: BookingFee},
  {Value: TotalPrice}
];

annotate service.Travel with @(UI: {SelectionFields: [
  TravelID,
  to_Agency_AgencyID,
  TravelStatus_code,
  BeginDate,
  EndDate
]});

annotate service.Travel with @Capabilities.FilterRestrictions.FilterExpressionRestrictions: [
  {
    Property          : 'BeginDate',
    AllowedExpressions: 'SingleRange'
  },
  {
    Property          : 'EndDate',
    AllowedExpressions: 'SingleRange'
  }
];

annotate service.Travel with @(UI: {
  FieldGroup #TravelData    : {Data: [
    {Value: TravelID},
    {Value: to_Agency_AgencyID},
    {Value: BeginDate},
    {Value: EndDate}
  ]},
  FieldGroup #ApprovalData  : {Data: [
    {
      $Type      : 'UI.DataField',
      Value      : TravelStatus_code,
      Criticality: TravelStatus.criticality,
      Label      : 'Status'
    },
    {Value: BookingFee},
    {Value: TotalPrice}
  ]},
  FieldGroup #HeaderMain    : {Data: [
    {Value: BeginDate},
    {Value: EndDate},
    {Value: TotalPrice}
  ]},
  ConnectedFields #TripDates: {
    Label   : 'Business Trip Dates',
    Template: '{BeginDate} / {EndDate}',
    Data    : {
      BeginDate: {
        $Type: 'UI.DataField',
        Value: BeginDate
      },
      EndDate  : {
        $Type: 'UI.DataField',
        Value: EndDate
      }
    }
  },
  Facets                    : [
    {
      $Type : 'UI.ReferenceFacet',
      ID    : 'TravelData',
      Label : 'Travel Information',
      Target: '@UI.FieldGroup#TravelData',
    },
    {
      $Type : 'UI.ReferenceFacet',
      ID    : 'ApprovalData',
      Label : 'Approval Data',
      Target: '@UI.FieldGroup#ApprovalData'
    },
    {
      $Type : 'UI.ReferenceFacet',
      ID    : 'BookingList',
      Label : 'Bookings',
      Target: 'to_Booking/@UI.LineItem'
    }
  ],
  HeaderFacets              : [{
    $Type : 'UI.ReferenceFacet',
    Target: '@UI.FieldGroup#HeaderMain'
  }],
  HeaderInfo                : {
    TypeName      : 'Travel',
    TypeNamePlural: 'Travels',
    Title         : {
      $Type: 'UI.DataField',
      Value: Description
    },
    Description   : {
      $Type: 'UI.DataField',
      Value: TravelID
    },
    TypeImageUrl  : 'sap-icon://header',
  }
});

annotate service.Travel {
  to_Agency @Common.ValueList: {
    CollectionPath: 'TravelAgency',
    Label         : '',
    Parameters    : [
      {
        $Type            : 'Common.ValueListParameterInOut',
        LocalDataProperty: to_Agency_AgencyID,
        ValueListProperty: 'AgencyID'
      },
      {
        $Type            : 'Common.ValueListParameterDisplayOnly',
        ValueListProperty: 'Name'
      },
      {
        $Type            : 'Common.ValueListParameterDisplayOnly',
        ValueListProperty: 'Street'
      },
      {
        $Type            : 'Common.ValueListParameterDisplayOnly',
        ValueListProperty: 'PostalCode'
      },
      {
        $Type            : 'Common.ValueListParameterDisplayOnly',
        ValueListProperty: 'City'
      },
      {
        $Type            : 'Common.ValueListParameterDisplayOnly',
        ValueListProperty: 'CountryCode_code'
      },
      {
        $Type            : 'Common.ValueListParameterDisplayOnly',
        ValueListProperty: 'PhoneNumber'
      },
      {
        $Type            : 'Common.ValueListParameterDisplayOnly',
        ValueListProperty: 'EMailAddress'
      },
      {
        $Type            : 'Common.ValueListParameterDisplayOnly',
        ValueListProperty: 'WebAddress'
      }
    ]
  };
}

annotate service.TravelAgency with @(UI: {
  DataPoint #Recommendation: {
    Value        : Recommendation,
    TargetValue  : 100.0,
    Title        : 'Recommendation',
    Visualization: #Progress
  },
  DataPoint #Rating        : {
    Value        : Rating,
    TargetValue  : 5.0,
    Title        : 'Rating',
    Visualization: #Rating
  },
  FieldGroup #Contact      : {Data: [{
    $Type : 'UI.DataFieldForAnnotation',
    Target: '@Communication.Contact',
    Label : 'Travel Agency'
  }]}
});

annotate service.TravelAgency with @(
  Communication.Contact : {
    email: [{
      type   : #work,
      address: EMailAddress
    }],
    fn   : Name,
    adr  : [{
      type    : #work,
      code    : PostalCode,
      country : CountryCode_code,
      locality: City
    }]
  },
  Common.IsNaturalPerson: false
);

annotate service.Booking {
  CurrencyCode @Common.ValueList: {
    CollectionPath: 'Currencies',
    Parameters    : [
      {
        $Type            : 'Common.ValueListParameterInOut',
        LocalDataProperty: CurrencyCode_code,
        ValueListProperty: 'code'
      },
      {
        $Type            : 'Common.ValueListParameterDisplayOnly',
        ValueListProperty: 'name'
      },
      {
        $Type            : 'Common.ValueListParameterDisplayOnly',
        ValueListProperty: 'descr'
      }
    ]
  };
}

annotate service.Booking with @(UI: {
  HeaderInfo: {
    TypeName      : 'Booking',
    TypeNamePlural: 'Bookings',
    TypeImageUrl  : 'sap-icon://alert',
    Title         : {
      $Type: 'UI.DataField',
      Value: BookingID
    }
  },
  Facets    : [{
    $Type : 'UI.ReferenceFacet',
    ID    : 'FacetIdentifier1',
    Target: '@UI.FieldGroup'
  }],
  LineItem  : [
    {Value: BookingID},
    {Value: BookingDate},
    {Value: ConnectionID},
    {Value: FlightDate},
    {Value: FlightPrice}
  ],
  FieldGroup: {Data: [
    {
      $Type: 'UI.DataField',
      Value: BookingID
    },
    {
      $Type: 'UI.DataField',
      Value: BookingDate
    },
    {
      $Type: 'UI.DataField',
      Value: FlightDate
    },
    {
      $Type: 'UI.DataField',
      Value: FlightPrice
    }
  ]}
});

annotate service.TravelAgency with @(UI: {FieldGroup #Link: {Data: [{
  $Type: 'UI.DataFieldWithUrl',
  Value: Name,
  Url  : WebAddress
}]}});

```

**FILE**: Travel.json

**LANGUAGE**: JSON

**CODE**:
```json
[
	{
		"TravelUUID": "52657221A8E4645C17002DF03754AB66",
		"TravelID": "00000001",
		"BeginDate": "2025-11-04",
		"EndDate": "2025-11-06",
		"BookingFee": "20.00",
		"TotalPrice": "900.00",
		"CurrencyCode_code": "USD",
		"Description": "Business Trip for Christine, Pierre",
		"TravelDetails": "This business trip includes a two-day customer workshop at the airport. The goal is the evaluation of the customer's use cases and the alignment on the road map for the upcoming year.",
		"TravelStatus_code": "A",
		"to_Agency_AgencyID": "070001"
	},
	{
		"TravelUUID": "53657221A8E4645C17002DF03754AB66",
		"TravelID": "00000002",
		"BeginDate": "2025-12-04",
		"EndDate": "2025-12-16",
		"BookingFee": "80.00",
		"TotalPrice": "3164.00",
		"CurrencyCode_code": "USD",
		"Description": "Lars Jensen site visit for system rollout support",
		"TravelDetails": "Will be provided soon...",
		"TravelStatus_code": "O",
		"to_Agency_AgencyID": "070002"
	},
	{
		"TravelUUID": "54657221A8E4645C17002DF03754AB66",
		"TravelID": "00000003",
		"BeginDate": "2025-08-04",
		"EndDate": "2025-08-08",
		"BookingFee": "40.00",
		"TotalPrice": "1871.00",
		"CurrencyCode_code": "USD",
		"Description": "John Smith customer workshop at Acme Corp headquarters",
		"TravelDetails": "Will be provided soon...",
		"TravelStatus_code": "O",
		"to_Agency_AgencyID": "070003"
	},
	{
		"TravelUUID": "55657221A8E4645C17002DF03754AB66",
		"TravelID": "00000004",
		"BeginDate": "2025-09-04",
		"EndDate": "2025-09-05",
		"BookingFee": "40.00",
		"TotalPrice": "1240.00",
		"CurrencyCode_code": "USD",
		"Description": "Anna Müller onboarding with new project team in Berlin",
		"TravelDetails": "Will be provided soon...",
		"TravelStatus_code": "X",
		"to_Agency_AgencyID": "070003"
	}
]

```

Paginator

paginator pagination paging navigation results


**TITLE**: Rich Text Editor

**INTRODUCTION**: The RichTextEditor building block enables you to add a control that shows a formatted text in display mode and allows users to edit and format it directly in edit mode.

**TAGS**: rich text editor, rte, wysiwyg, text formatting, editor

**STEP**: Implementation

**DESCRIPTION**: To use the rich text editor, you need to define the metaPath pointing to a string property. The building block is based on the rich text editor used in SAPUI5, allowing you to define the button groups and plugins the same way as you would in that control.

**LANGUAGE**: XML

**CODE**:
```xml
<core:FragmentDefinition
	xmlns:core="sap.ui.core"
	xmlns="sap.m"
	xmlns:macros="sap.fe.macros"
	xmlns:richtexteditor="sap.fe.macros.richtexteditor"
>
	<macros:RichTextEditorWithMetadata metaPath="Description" id="myRichTextEditor">
		<macros:buttonGroups>
			<richtexteditor:ButtonGroup name="font-style" visible="true" priority="10" buttons="bold,italic,underline" />
		</macros:buttonGroups>
	</macros:RichTextEditorWithMetadata>
</core:FragmentDefinition>
```

Rich Text Editor

rich text editor
rte
wysiwyg
text formatting
editor


**TITLE**: Share

**INTRODUCTION**: The Share building block enables you to add a button that allows users to share content from your application with other users or applications.

**TAGS**: share, sharing, collaboration, link, export

**STEP**: Implementation

**DESCRIPTION**: To use the share building block, you need to define it in your view.

**LANGUAGE**: XML

**CODE**:
```xml
<core:FragmentDefinition xmlns:core="sap.ui.core" xmlns="sap.m" xmlns:macros="sap.fe.macros">
	<macros:Share id="share" />
</core:FragmentDefinition>
```

**ADDITIONAL RELATED CODE BLOCKS**:

**FILE**: service.cds

**LANGUAGE**: CDS

**CODE**:
```cds
using {
  sap,
  managed,
  Currency,
  Country
} from '@sap/cds/common';

using from '../service/annotations';

@cds.autoexpose  @readonly
aspect MasterData {}

service TravelService {
  @odata.draft.enabled
  @Common.SemanticKey: [TravelID]

  entity Travel : managed {
    key TravelUUID    : UUID;

        @Common.Label          : 'ID'
        @Common.Text           : Description
        TravelID      : Integer default 0                         @readonly;

        @Common.Label          : 'Begin Date'
        BeginDate     : Date;

        @Common.Label          : 'End Date'
        EndDate       : Date;

        @Common.Label          : 'Booking Fee'
        BookingFee    : Decimal(10, 2) default 0                  @Measures.ISOCurrency: CurrencyCode_code;

        @Common.Label          : 'Total Price'
        TotalPrice    : Decimal(10, 2)                            @readonly  @Measures.ISOCurrency: CurrencyCode_code;

        @Common.Label          : 'Currency'
        CurrencyCode  : Association to CurrencyCode default 'EUR' @mandatory;

        @Common.Label          : 'Description'
        Description   : String(1024);

        @Common.Label          : 'Travel Details'
        @UI.MultiLineText
        TravelDetails : String(1024);

        @title                 : 'Status'
        @Common.Text           : TravelStatus.name
        @Common.TextArrangement: #TextOnly
        TravelStatus  : Association to TravelStatus default 'O'   @readonly;

        @title                 : 'Agency'
        @Common.Text           : to_Agency.Name
        @Common.TextArrangement: #TextFirst
        to_Agency     : Association to TravelAgency               @mandatory;

        to_Booking    : Composition of many Booking
                          on to_Booking.to_Travel = $self;
  };

  entity Booking : managed {
    key BookingUUID   : UUID;

        @Common.Label: 'Booking ID'
        BookingID     : Integer                                  @Core.Computed;

        @Common.Label: 'Booking Date'
        BookingDate   : Date;

        @Common.Label: 'Connection'
        ConnectionID  : String(4)                                @mandatory;

        @Common.Label: 'Flight Date'
        FlightDate    : Date                                     @mandatory;

        @Common.Label: 'Flight Price'
        FlightPrice   : Decimal(10, 2)                           @Measures.ISOCurrency: CurrencyCode_code;

        @Common.Label: 'Currency'
        CurrencyCode  : Currency default 'EUR'                   @mandatory;

        @Common.Label: 'Status'
        BookingStatus : Association to BookingStatus default 'N' @mandatory;
        to_Travel     : Association to Travel                    @mandatory;

        PaymentMethod : String(1) default 'B'                    @Common              : {
          Label                   : 'Payment Method',
          Text                    : _Payment.Method,
          TextArrangement         : #TextOnly,
          ValueListWithFixedValues: true,
          ValueList               : {
            Label         : 'Payment Method',
            CollectionPath: 'Payment',
            Parameters    : [{
              $Type            : 'Common.ValueListParameterInOut',
              LocalDataProperty: PaymentMethod,
              ValueListProperty: 'code'
            }]
          }
        };
        _Payment      : Association to one Payment
                          on _Payment.code = PaymentMethod;
  };

  entity Payment {
    key code   : String(1) @(Common: {
          Label          : 'Payment Code',
          Text           : Method,
          TextArrangement: #TextFirst
        });
        Method : String    @(
          Core.Immutable: true,
          Common.Label  : 'Payment Method'
        );
  }

  entity TravelStatus : sap.common.CodeList {
    key code        : String(1) @Common.Text: descr;
        name        : String(255);
        descr       : String(1000);
        criticality : Int16     @odata.Type : 'Edm.Byte' enum {
          Neutral  = 0;
          Negative = 1;
          Critical = 2;
          Positive = 3;
          NewItem  = 5
        };
  };

  entity CurrencyCode : sap.common.CodeList {
        @Common.Label: 'Currency Code'
    key code  : String(3);

        @Common.Label: 'Currency Description'
        descr : String(255);
  };

  entity BookingStatus : sap.common.CodeList {
    key code : BookingStatusCode
  };

  entity TravelAgency : MasterData {
        @Common.Label: 'Agency ID'
        @Common.Text : Name
    key AgencyID       : String(6);

        @Common.Label: 'Agency Name'
        Name           : String(80);
        Street         : String(60);

        @Common.Label: 'Postal Code'
        PostalCode     : String(10);

        @Common.Label: 'City'
        City           : String(40);

        @Common.Label: 'Country Code'
        CountryCode    : Country;

        @Common.Label: 'Phone Number'
        PhoneNumber    : String(30);

        @Common.Label: 'Email Address'
        EMailAddress   : String(256);

        @Common.Label: 'Web Address'
        WebAddress     : String(256);
        Rating         : Integer;
        Recommendation : Integer;
  };

  type TravelStatusCode  : String(1) enum {
    Open     = 'O';
    Accepted = 'A';
    Canceled = 'X';
  };

  type BookingStatusCode : String(1) enum {
    New      = 'N';
    Booked   = 'B';
    Canceled = 'X';
  };
}

```

**FILE**: annotations.cds

**LANGUAGE**: CDS

**CODE**:
```cds
using TravelService as service from '../service/service';

annotate service.Travel {
  TravelStatus @Common.ValueListWithFixedValues;
  CurrencyCode @Common.ValueList: {
    CollectionPath: 'Currencies',
    Parameters    : [
      {
        $Type            : 'Common.ValueListParameterInOut',
        LocalDataProperty: CurrencyCode_code,
        ValueListProperty: 'code'
      },
      {
        $Type            : 'Common.ValueListParameterDisplayOnly',
        ValueListProperty: 'name'
      },
      {
        $Type            : 'Common.ValueListParameterDisplayOnly',
        ValueListProperty: 'descr'
      }
    ]
  };
}

annotate service.Travel with @UI.LineItem: [
  {Value: TravelID},
  {
    $Type : 'UI.DataFieldForAnnotation',
    Target: '@UI.ConnectedFields#TripDates'
  },
  {Value: to_Agency_AgencyID},
  {
    Value             : TravelStatus_code,
    Criticality       : TravelStatus.criticality,
    @UI.Importance    : #High,
    @HTML5.CssDefaults: {width: '10em'}
  },
  {Value: BookingFee},
  {Value: TotalPrice}
];

annotate service.Travel with @(UI: {SelectionFields: [
  TravelID,
  to_Agency_AgencyID,
  TravelStatus_code,
  BeginDate,
  EndDate
]});

annotate service.Travel with @Capabilities.FilterRestrictions.FilterExpressionRestrictions: [
  {
    Property          : 'BeginDate',
    AllowedExpressions: 'SingleRange'
  },
  {
    Property          : 'EndDate',
    AllowedExpressions: 'SingleRange'
  }
];

annotate service.Travel with @(UI: {
  FieldGroup #TravelData    : {Data: [
    {Value: TravelID},
    {Value: to_Agency_AgencyID},
    {Value: BeginDate},
    {Value: EndDate}
  ]},
  FieldGroup #ApprovalData  : {Data: [
    {
      $Type      : 'UI.DataField',
      Value      : TravelStatus_code,
      Criticality: TravelStatus.criticality,
      Label      : 'Status'
    },
    {Value: BookingFee},
    {Value: TotalPrice}
  ]},
  FieldGroup #HeaderMain    : {Data: [
    {Value: BeginDate},
    {Value: EndDate},
    {Value: TotalPrice}
  ]},
  ConnectedFields #TripDates: {
    Label   : 'Business Trip Dates',
    Template: '{BeginDate} / {EndDate}',
    Data    : {
      BeginDate: {
        $Type: 'UI.DataField',
        Value: BeginDate
      },
      EndDate  : {
        $Type: 'UI.DataField',
        Value: EndDate
      }
    }
  },
  Facets                    : [
    {
      $Type : 'UI.ReferenceFacet',
      ID    : 'TravelData',
      Label : 'Travel Information',
      Target: '@UI.FieldGroup#TravelData',
    },
    {
      $Type : 'UI.ReferenceFacet',
      ID    : 'ApprovalData',
      Label : 'Approval Data',
      Target: '@UI.FieldGroup#ApprovalData'
    },
    {
      $Type : 'UI.ReferenceFacet',
      ID    : 'BookingList',
      Label : 'Bookings',
      Target: 'to_Booking/@UI.LineItem'
    }
  ],
  HeaderFacets              : [{
    $Type : 'UI.ReferenceFacet',
    Target: '@UI.FieldGroup#HeaderMain'
  }],
  HeaderInfo                : {
    TypeName      : 'Travel',
    TypeNamePlural: 'Travels',
    Title         : {
      $Type: 'UI.DataField',
      Value: Description
    },
    Description   : {
      $Type: 'UI.DataField',
      Value: TravelID
    },
    TypeImageUrl  : 'sap-icon://header',
  }
});

annotate service.Travel {
  to_Agency @Common.ValueList: {
    CollectionPath: 'TravelAgency',
    Label         : '',
    Parameters    : [
      {
        $Type            : 'Common.ValueListParameterInOut',
        LocalDataProperty: to_Agency_AgencyID,
        ValueListProperty: 'AgencyID'
      },
      {
        $Type            : 'Common.ValueListParameterDisplayOnly',
        ValueListProperty: 'Name'
      },
      {
        $Type            : 'Common.ValueListParameterDisplayOnly',
        ValueListProperty: 'Street'
      },
      {
        $Type            : 'Common.ValueListParameterDisplayOnly',
        ValueListProperty: 'PostalCode'
      },
      {
        $Type            : 'Common.ValueListParameterDisplayOnly',
        ValueListProperty: 'City'
      },
      {
        $Type            : 'Common.ValueListParameterDisplayOnly',
        ValueListProperty: 'CountryCode_code'
      },
      {
        $Type            : 'Common.ValueListParameterDisplayOnly',
        ValueListProperty: 'PhoneNumber'
      },
      {
        $Type            : 'Common.ValueListParameterDisplayOnly',
        ValueListProperty: 'EMailAddress'
      },
      {
        $Type            : 'Common.ValueListParameterDisplayOnly',
        ValueListProperty: 'WebAddress'
      }
    ]
  };
}

annotate service.TravelAgency with @(UI: {
  DataPoint #Recommendation: {
    Value        : Recommendation,
    TargetValue  : 100.0,
    Title        : 'Recommendation',
    Visualization: #Progress
  },
  DataPoint #Rating        : {
    Value        : Rating,
    TargetValue  : 5.0,
    Title        : 'Rating',
    Visualization: #Rating
  },
  FieldGroup #Contact      : {Data: [{
    $Type : 'UI.DataFieldForAnnotation',
    Target: '@Communication.Contact',
    Label : 'Travel Agency'
  }]}
});

annotate service.TravelAgency with @(
  Communication.Contact : {
    email: [{
      type   : #work,
      address: EMailAddress
    }],
    fn   : Name,
    adr  : [{
      type    : #work,
      code    : PostalCode,
      country : CountryCode_code,
      locality: City
    }]
  },
  Common.IsNaturalPerson: false
);

annotate service.Booking {
  CurrencyCode @Common.ValueList: {
    CollectionPath: 'Currencies',
    Parameters    : [
      {
        $Type            : 'Common.ValueListParameterInOut',
        LocalDataProperty: CurrencyCode_code,
        ValueListProperty: 'code'
      },
      {
        $Type            : 'Common.ValueListParameterDisplayOnly',
        ValueListProperty: 'name'
      },
      {
        $Type            : 'Common.ValueListParameterDisplayOnly',
        ValueListProperty: 'descr'
      }
    ]
  };
}

annotate service.Booking with @(UI: {
  HeaderInfo: {
    TypeName      : 'Booking',
    TypeNamePlural: 'Bookings',
    TypeImageUrl  : 'sap-icon://alert',
    Title         : {
      $Type: 'UI.DataField',
      Value: BookingID
    }
  },
  Facets    : [{
    $Type : 'UI.ReferenceFacet',
    ID    : 'FacetIdentifier1',
    Target: '@UI.FieldGroup'
  }],
  LineItem  : [
    {Value: BookingID},
    {Value: BookingDate},
    {Value: ConnectionID},
    {Value: FlightDate},
    {Value: FlightPrice}
  ],
  FieldGroup: {Data: [
    {
      $Type: 'UI.DataField',
      Value: BookingID
    },
    {
      $Type: 'UI.DataField',
      Value: BookingDate
    },
    {
      $Type: 'UI.DataField',
      Value: FlightDate
    },
    {
      $Type: 'UI.DataField',
      Value: FlightPrice
    }
  ]}
});

annotate service.TravelAgency with @(UI: {FieldGroup #Link: {Data: [{
  $Type: 'UI.DataFieldWithUrl',
  Value: Name,
  Url  : WebAddress
}]}});

```

**FILE**: Travel.json

**LANGUAGE**: JSON

**CODE**:
```json
[
	{
		"TravelUUID": "52657221A8E4645C17002DF03754AB66",
		"TravelID": "00000001",
		"BeginDate": "2025-11-04",
		"EndDate": "2025-11-06",
		"BookingFee": "20.00",
		"TotalPrice": "900.00",
		"CurrencyCode_code": "USD",
		"Description": "Business Trip for Christine, Pierre",
		"TravelDetails": "This business trip includes a two-day customer workshop at the airport. The goal is the evaluation of the customer's use cases and the alignment on the road map for the upcoming year.",
		"TravelStatus_code": "A",
		"to_Agency_AgencyID": "070001"
	},
	{
		"TravelUUID": "53657221A8E4645C17002DF03754AB66",
		"TravelID": "00000002",
		"BeginDate": "2025-12-04",
		"EndDate": "2025-12-16",
		"BookingFee": "80.00",
		"TotalPrice": "3164.00",
		"CurrencyCode_code": "USD",
		"Description": "Lars Jensen site visit for system rollout support",
		"TravelDetails": "Will be provided soon...",
		"TravelStatus_code": "O",
		"to_Agency_AgencyID": "070002"
	},
	{
		"TravelUUID": "54657221A8E4645C17002DF03754AB66",
		"TravelID": "00000003",
		"BeginDate": "2025-08-04",
		"EndDate": "2025-08-08",
		"BookingFee": "40.00",
		"TotalPrice": "1871.00",
		"CurrencyCode_code": "USD",
		"Description": "John Smith customer workshop at Acme Corp headquarters",
		"TravelDetails": "Will be provided soon...",
		"TravelStatus_code": "O",
		"to_Agency_AgencyID": "070003"
	},
	{
		"TravelUUID": "55657221A8E4645C17002DF03754AB66",
		"TravelID": "00000004",
		"BeginDate": "2025-09-04",
		"EndDate": "2025-09-05",
		"BookingFee": "40.00",
		"TotalPrice": "1240.00",
		"CurrencyCode_code": "USD",
		"Description": "Anna Müller onboarding with new project team in Berlin",
		"TravelDetails": "Will be provided soon...",
		"TravelStatus_code": "X",
		"to_Agency_AgencyID": "070003"
	}
]

```

Share


**TITLE**: Status

**INTRODUCTION**: No introduction

**TAGS**: status, object status, status indicator

**STEP**: Usage of Status Building Block

**DESCRIPTION**: To use the Status building block, you must define the metaPath pointing to a DataField or a property. The criticality of the DataField (or its DataFieldDefault) determines its color. You can attach a press event to the Status to handle user interactions.

**LANGUAGE**: XML

**CODE**:
```xml
<core:FragmentDefinition xmlns:core="sap.ui.core" xmlns="sap.m" xmlns:macros="sap.fe.macros">
	<VBox>
		<macros:Status
			metaPath="@com.sap.vocabularies.UI.v1.FieldGroup#ApprovalData/Data/0"
			id="myStatus"
			largeDesign="true"
			press=".onStatusPressed"
		/>
		<macros:Status metaPath="@com.sap.vocabularies.UI.v1.FieldGroup#ApprovalData/Data/1" id="mySecondStatus" />
	</VBox>
</core:FragmentDefinition>
```

Status


**TITLE**: Custom Column

**INTRODUCTION**: The Table building block enables you to render custom columns in a table.

**TAGS**: table extensions, custom columns, custom actions, APIs

**STEP**: Add Custom Columns

**DESCRIPTION**: You can add custom columns to your table. In this example, a process flow is added as a custom column. By specifying property names in the 'properties' attribute of the column, users can sort, group, export, and paste data based on these properties.

**LANGUAGE**: XML

**CODE**:
```xml
<core:FragmentDefinition xmlns:core="sap.ui.core" xmlns="sap.m" xmlns:macros="sap.fe.macros" xmlns:macrosTable="sap.fe.macros.table">
	<macros:Table metaPath="/Travel/@com.sap.vocabularies.UI.v1.LineItem">
		<macros:columns>
			<macrosTable:Column
				header="My Column"
				importance="High"
				width="20em"
				key="myColumnKey"
				properties="ApprovalStatus,PaymentStatus,ConfirmationStatus"
			>
				<core:Fragment fragmentName="sap.fe.core.fpmExplorer.customColumn.CustomColumn" type="XML" />
			</macrosTable:Column>
		</macros:columns>
	</macros:Table>
</core:FragmentDefinition>
```

**STEP**: Add Columns through Manifest

**DESCRIPTION**: If you want to add custom columns to your object page table rendered through UI.Facet annotations, you can use the 'columns' property in the controlConfiguration section of the respective UI.LineItem.

**LANGUAGE**: JSON

**CODE**:
```json
{
	"sample": {
		"type": "Component",
		"id": "sample",
		"name": "sap.fe.templates.ObjectPage",
		"options": {
			"settings": {
				"contextPath": "/Travel",
				"controlConfiguration": {
					"to_Booking/@com.sap.vocabularies.UI.v1.LineItem": {
						"columns": {
							"CustomColumnOnObjectPage": {
								"header": "{i18n>bookingProcess}",
								"width": "15em",
								"importance": "High",
								"horizontalAlign": "Left",
								"position": {
									"placement": "After",
									"anchor": "DataField::ConnectionID"
								},
								"template": "sap.fe.core.fpmExplorer.CustomColumn",
								"availability": "Default"
							}
						}
					}
				}
			}
		}
	}
}
```

Custom Column

table extensions
custom columns
custom actions
APIs


**TITLE**: Custom Action

**INTRODUCTION**: The Table building block enables you to define custom actions in a table.

**TAGS**: custom actions, row press handler, selection change handler, extensions

**STEP**: Add Custom Actions

**DESCRIPTION**: You can add custom actions to your table.

**LANGUAGE**: XML

**CODE**:
```xml
<core:FragmentDefinition xmlns:core="sap.ui.core" xmlns="sap.m" xmlns:macros="sap.fe.macros" xmlns:macrosTable="sap.fe.macros.table">
	<macros:Table metaPath="/Travel/@com.sap.vocabularies.UI.v1.LineItem">
		<macros:actions>
			<macrosTable:Action
				key="customAction"
				text="My Custom Action"
				press=".onPressAction"
				placement="After"
				requiresSelection="true"
			/>
			<macrosTable:ActionGroup key="customActionGroup" text="My Action Group" placement="After" anchor="customAction">
				<macrosTable:Action text="Menu Action 1" press=".onPressMenuAction" key="menuAction1" />
				<macrosTable:Action text="Menu Action 2" press=".onPressMenuAction" enabled="false" key="menuAction2" />
			</macrosTable:ActionGroup>
		</macros:actions>
	</macros:Table>
</core:FragmentDefinition>
```

**STEP**: Add Custom Menu Actions

**DESCRIPTION**: You can also add custom menu actions to your table.

**LANGUAGE**: XML

**CODE**:
```xml
<core:FragmentDefinition xmlns:core="sap.ui.core" xmlns="sap.m" xmlns:macros="sap.fe.macros" xmlns:macrosTable="sap.fe.macros.table">
	<macros:Table metaPath="/Travel/@com.sap.vocabularies.UI.v1.LineItem">
		<macros:actions>
			<macrosTable:Action
				key="customAction"
				text="My Custom Action"
				press=".onPressAction"
				placement="After"
				requiresSelection="true"
			/>
			<macrosTable:ActionGroup key="customActionGroup" text="My Action Group" placement="After" anchor="customAction">
				<macrosTable:Action text="Menu Action 1" press=".onPressMenuAction" key="menuAction1" />
				<macrosTable:Action text="Menu Action 2" press=".onPressMenuAction" enabled="false" key="menuAction2" />
			</macrosTable:ActionGroup>
		</macros:actions>
	</macros:Table>
</core:FragmentDefinition>
```

**STEP**: Add Actions through Manifest

**DESCRIPTION**: If you want to add custom actions to your object page table rendered through UI.Facet annotations, you can use the 'actions' property in the controlConfiguration section of the respective UI.LineItem.

**LANGUAGE**: JSON

**CODE**:
```json
{
	"sample": {
		"type": "Component",
		"id": "sample",
		"name": "sap.fe.templates.ObjectPage",
		"options": {
			"settings": {
				"contextPath": "/Travel",
				"controlConfiguration": {
					"to_Booking/@com.sap.vocabularies.UI.v1.LineItem": {
						"actions": {
							"customAction": {
								"press": "sap.fe.core.fpmExplorer.customTableAction.CustomAction.onPressAction",
								"text": "My Custom Action"
							},
							"menuAction1": {
								"text": "Menu Action 1",
								"press": "sap.fe.core.fpmExplorer.customTableAction.CustomAction.onPressMenuAction"
							},
							"menuAction2": {
								"text": "Menu Action 2",
								"press": "sap.fe.core.fpmExplorer.customTableAction.CustomAction.onPressMenuAction"
							},
							"DataFieldForActionGroup::MyActionGroup": {
								"menu": ["menuAction1", "menuAction2"],
								"position": {
									"anchor": "customAction",
									"position": "After"
								}
							}
						}
					}
				}
			}
		}
	}
}
```

Custom Action

custom actions
row press handler
selection change handler
extensions


**TITLE**: Analytical Table

**INTRODUCTION**: Analytical tables enable you to display and manage your data efficiently. This table type provides powerful functionalities, including advanced grouping and aggregation.

**TAGS**: analytical table, analytics, aggregation, grouping, totals, ApplySupported, CustomAggregate

**STEP**: Annotating a Service as an Analytical Service

**DESCRIPTION**: To set the analytical capabilities of your service or entity, use the Aggregation.ApplySupported annotation at the entity set level. The analytical table offers the possibility to group rows based on groupable properties. You must define which properties are groupable so that the table allows grouping the relevant properties. To annotate a set of properties as groupable, add it to the GroupableProperties annotation.

**LANGUAGE**: CDS

**CODE**:
```cds
service Service {
  @Aggregation.CustomAggregate #NumberProperty: 'Edm.Decimal'
  @Aggregation.CustomAggregate #Criticality   : 'Edm.Int32'
  @Aggregation.ApplySupported                 : {
    GroupableProperties   : [StringProperty, ],
    AggregatableProperties: [{Property: NumberProperty}]
  }

  @odata.draft.enabled
  entity RootEntity {
    key ID              : Integer       @Common.Label: 'Agency ID';
        StringProperty  : String        @Common.Label: 'Agency';
        IntegerProperty : Integer       @Common.Label: 'Integer Property';
        NumberProperty  : Decimal(4, 2) @Common.Label: 'Amount';
        BooleanProperty : Boolean       @Common.Label: 'Boolean Property';
        DateProperty    : Date          @Common.Label: 'Date Property';
        TimeProperty    : Time          @Common.Label: 'Time Property';
        Criticality     : Integer;
        emailAddress    : String        @Communication.IsEmailAddress;
        phoneNumber     : String        @Communication.IsPhoneNumber;
        role            : String;
        PostalCode      : String;
        CityName        : String;
        Country         : String;
  }

  annotate RootEntity with @(UI: {
    LineItem           : {
      ![@UI.Criticality]: Criticality,
      $value            : [
        {Value: ID},
        {Value: StringProperty},
        {
          Value             : NumberProperty,
          @UI.Importance    : #High,
          @HTML5.CssDefaults: {width: '10em'}
        },

      ]
    },
    PresentationVariant: {
      $Type         : 'UI.PresentationVariantType',
      Visualizations: [@UI.LineItem],
      RequestAtLeast: [Criticality]
    },
  });
}
```

**LANGUAGE**: XML

**CODE**:
```xml
<Annotation Term="Aggregation.ApplySupported">
	<Record Type="Aggregation.ApplySupportedType">
		<PropertyValue Property="GroupableProperties">
			<Collection>
				<PropertyPath>StringProperty</PropertyPath>
			</Collection>
		</PropertyValue>
		<PropertyValue Property="AggregatableProperties">
			<Collection>
				<Record Type="Aggregation.AggregatablePropertyType">
					<PropertyValue Property="Property" PropertyPath="NumberProperty" />
				</Record>
			</Collection>
		</PropertyValue>
	</Record>
</Annotation>
```

**STEP**: Defining Aggregatable Properties

**DESCRIPTION**: The properties can also be annotated as aggregatable (measures). To do so, at the entity level, you must also define the Aggregation.CustomAggregate annotation, which has the property name as the qualifier.

**LANGUAGE**: CDS

**CODE**:
```cds
service Service {
  @Aggregation.CustomAggregate #NumberProperty: 'Edm.Decimal'
  @Aggregation.CustomAggregate #Criticality   : 'Edm.Int32'
  @Aggregation.ApplySupported                 : {
    GroupableProperties   : [StringProperty, ],
    AggregatableProperties: [{Property: NumberProperty}]
  }

  @odata.draft.enabled
  entity RootEntity {
    key ID              : Integer       @Common.Label: 'Agency ID';
        StringProperty  : String        @Common.Label: 'Agency';
        IntegerProperty : Integer       @Common.Label: 'Integer Property';
        NumberProperty  : Decimal(4, 2) @Common.Label: 'Amount';
        BooleanProperty : Boolean       @Common.Label: 'Boolean Property';
        DateProperty    : Date          @Common.Label: 'Date Property';
        TimeProperty    : Time          @Common.Label: 'Time Property';
        Criticality     : Integer;
        emailAddress    : String        @Communication.IsEmailAddress;
        phoneNumber     : String        @Communication.IsPhoneNumber;
        role            : String;
        PostalCode      : String;
        CityName        : String;
        Country         : String;
  }

  annotate RootEntity with @(UI: {
    LineItem           : {
      ![@UI.Criticality]: Criticality,
      $value            : [
        {Value: ID},
        {Value: StringProperty},
        {
          Value             : NumberProperty,
          @UI.Importance    : #High,
          @HTML5.CssDefaults: {width: '10em'}
        },

      ]
    },
    PresentationVariant: {
      $Type         : 'UI.PresentationVariantType',
      Visualizations: [@UI.LineItem],
      RequestAtLeast: [Criticality]
    },
  });
}
```

**LANGUAGE**: XML

**CODE**:
```xml
<Annotation Term="Aggregation.CustomAggregate" Qualifier="NumberProperty" String="Edm.Decimal" />
```

Analytical Table

analytical table
analytics
aggregation
grouping
totals
ApplySupported
CustomAggregate


**TITLE**: Table

**INTRODUCTION**: The Table building block enables you to render a table based on an entitySet or a specific navigation property.

**TAGS**: table, overview, grid, list, data, rows, columns, LineItems

**STEP**: Implementation

**DESCRIPTION**: The UI.LineItem annotation defines the columns of the table.

**LANGUAGE**: CDS

**CODE**:
```cds
using TravelService as service from '../service/service';

annotate service.Travel {
  TravelStatus @Common.ValueListWithFixedValues;
  CurrencyCode @Common.ValueList: {
    CollectionPath: 'Currencies',
    Parameters    : [
      {
        $Type            : 'Common.ValueListParameterInOut',
        LocalDataProperty: CurrencyCode_code,
        ValueListProperty: 'code'
      },
      {
        $Type            : 'Common.ValueListParameterDisplayOnly',
        ValueListProperty: 'name'
      },
      {
        $Type            : 'Common.ValueListParameterDisplayOnly',
        ValueListProperty: 'descr'
      }
    ]
  };
}

annotate service.Travel with @UI.LineItem: [
  {Value: TravelID},
  {
    $Type : 'UI.DataFieldForAnnotation',
    Target: '@UI.ConnectedFields#TripDates'
  },
  {Value: to_Agency_AgencyID},
  {
    Value             : TravelStatus_code,
    Criticality       : TravelStatus.criticality,
    @UI.Importance    : #High,
    @HTML5.CssDefaults: {width: '10em'}
  },
  {Value: BookingFee},
  {Value: TotalPrice}
];

annotate service.Travel with @(UI: {SelectionFields: [
  TravelID,
  to_Agency_AgencyID,
  TravelStatus_code,
  BeginDate,
  EndDate
]});

annotate service.Travel with @Capabilities.FilterRestrictions.FilterExpressionRestrictions: [
  {
    Property          : 'BeginDate',
    AllowedExpressions: 'SingleRange'
  },
  {
    Property          : 'EndDate',
    AllowedExpressions: 'SingleRange'
  }
];

annotate service.Travel with @(UI: {
  FieldGroup #TravelData    : {Data: [
    {Value: TravelID},
    {Value: to_Agency_AgencyID},
    {Value: BeginDate},
    {Value: EndDate}
  ]},
  FieldGroup #ApprovalData  : {Data: [
    {
      $Type      : 'UI.DataField',
      Value      : TravelStatus_code,
      Criticality: TravelStatus.criticality,
      Label      : 'Status'
    },
    {Value: BookingFee},
    {Value: TotalPrice}
  ]},
  FieldGroup #HeaderMain    : {Data: [
    {Value: BeginDate},
    {Value: EndDate},
    {Value: TotalPrice}
  ]},
  ConnectedFields #TripDates: {
    Label   : 'Business Trip Dates',
    Template: '{BeginDate} / {EndDate}',
    Data    : {
      BeginDate: {
        $Type: 'UI.DataField',
        Value: BeginDate
      },
      EndDate  : {
        $Type: 'UI.DataField',
        Value: EndDate
      }
    }
  },
  Facets                    : [
    {
      $Type : 'UI.ReferenceFacet',
      ID    : 'TravelData',
      Label : 'Travel Information',
      Target: '@UI.FieldGroup#TravelData',
    },
    {
      $Type : 'UI.ReferenceFacet',
      ID    : 'ApprovalData',
      Label : 'Approval Data',
      Target: '@UI.FieldGroup#ApprovalData'
    },
    {
      $Type : 'UI.ReferenceFacet',
      ID    : 'BookingList',
      Label : 'Bookings',
      Target: 'to_Booking/@UI.LineItem'
    }
  ],
  HeaderFacets              : [{
    $Type : 'UI.ReferenceFacet',
    Target: '@UI.FieldGroup#HeaderMain'
  }],
  HeaderInfo                : {
    TypeName      : 'Travel',
    TypeNamePlural: 'Travels',
    Title         : {
      $Type: 'UI.DataField',
      Value: Description
    },
    Description   : {
      $Type: 'UI.DataField',
      Value: TravelID
    },
    TypeImageUrl  : 'sap-icon://header',
  }
});

annotate service.Travel {
  to_Agency @Common.ValueList: {
    CollectionPath: 'TravelAgency',
    Label         : '',
    Parameters    : [
      {
        $Type            : 'Common.ValueListParameterInOut',
        LocalDataProperty: to_Agency_AgencyID,
        ValueListProperty: 'AgencyID'
      },
      {
        $Type            : 'Common.ValueListParameterDisplayOnly',
        ValueListProperty: 'Name'
      },
      {
        $Type            : 'Common.ValueListParameterDisplayOnly',
        ValueListProperty: 'Street'
      },
      {
        $Type            : 'Common.ValueListParameterDisplayOnly',
        ValueListProperty: 'PostalCode'
      },
      {
        $Type            : 'Common.ValueListParameterDisplayOnly',
        ValueListProperty: 'City'
      },
      {
        $Type            : 'Common.ValueListParameterDisplayOnly',
        ValueListProperty: 'CountryCode_code'
      },
      {
        $Type            : 'Common.ValueListParameterDisplayOnly',
        ValueListProperty: 'PhoneNumber'
      },
      {
        $Type            : 'Common.ValueListParameterDisplayOnly',
        ValueListProperty: 'EMailAddress'
      },
      {
        $Type            : 'Common.ValueListParameterDisplayOnly',
        ValueListProperty: 'WebAddress'
      }
    ]
  };
}

annotate service.TravelAgency with @(UI: {
  DataPoint #Recommendation: {
    Value        : Recommendation,
    TargetValue  : 100.0,
    Title        : 'Recommendation',
    Visualization: #Progress
  },
  DataPoint #Rating        : {
    Value        : Rating,
    TargetValue  : 5.0,
    Title        : 'Rating',
    Visualization: #Rating
  },
  FieldGroup #Contact      : {Data: [{
    $Type : 'UI.DataFieldForAnnotation',
    Target: '@Communication.Contact',
    Label : 'Travel Agency'
  }]}
});

annotate service.TravelAgency with @(
  Communication.Contact : {
    email: [{
      type   : #work,
      address: EMailAddress
    }],
    fn   : Name,
    adr  : [{
      type    : #work,
      code    : PostalCode,
      country : CountryCode_code,
      locality: City
    }]
  },
  Common.IsNaturalPerson: false
);

annotate service.Booking {
  CurrencyCode @Common.ValueList: {
    CollectionPath: 'Currencies',
    Parameters    : [
      {
        $Type            : 'Common.ValueListParameterInOut',
        LocalDataProperty: CurrencyCode_code,
        ValueListProperty: 'code'
      },
      {
        $Type            : 'Common.ValueListParameterDisplayOnly',
        ValueListProperty: 'name'
      },
      {
        $Type            : 'Common.ValueListParameterDisplayOnly',
        ValueListProperty: 'descr'
      }
    ]
  };
}

annotate service.Booking with @(UI: {
  HeaderInfo: {
    TypeName      : 'Booking',
    TypeNamePlural: 'Bookings',
    TypeImageUrl  : 'sap-icon://alert',
    Title         : {
      $Type: 'UI.DataField',
      Value: BookingID
    }
  },
  Facets    : [{
    $Type : 'UI.ReferenceFacet',
    ID    : 'FacetIdentifier1',
    Target: '@UI.FieldGroup'
  }],
  LineItem  : [
    {Value: BookingID},
    {Value: BookingDate},
    {Value: ConnectionID},
    {Value: FlightDate},
    {Value: FlightPrice}
  ],
  FieldGroup: {Data: [
    {
      $Type: 'UI.DataField',
      Value: BookingID
    },
    {
      $Type: 'UI.DataField',
      Value: BookingDate
    },
    {
      $Type: 'UI.DataField',
      Value: FlightDate
    },
    {
      $Type: 'UI.DataField',
      Value: FlightPrice
    }
  ]}
});

annotate service.TravelAgency with @(UI: {FieldGroup #Link: {Data: [{
  $Type: 'UI.DataFieldWithUrl',
  Value: Name,
  Url  : WebAddress
}]}});
```

**LANGUAGE**: XML

**CODE**:
```xml
<Annotation Term="UI.LineItem">
	<Collection>
		<Record Type="UI.DataField">
			<PropertyValue Property="Value" Path="TravelID" />
		</Record>
		<Record Type="UI.DataField">
			<PropertyValue Property="Value" Path="to_Agency_AgencyID" />
		</Record>
		<Record Type="UI.DataFieldForAnnotation">
			<PropertyValue Property="Target" AnnotationPath="@UI.ConnectedFields#TripDates" />
		</Record>
		<Record Type="UI.DataField">
			<PropertyValue Property="Value" Path="TravelStatus_code" />
			<PropertyValue Property="Criticality" Path="TravelStatus/criticality" />
			<Annotation Term="UI.Importance" EnumMember="UI.ImportanceType/High" />
			<Annotation Term="HTML5.CssDefaults">
				<Record Type="HTML5.CssDefaultsType">
					<PropertyValue Property="width" String="10em" />
				</Record>
			</Annotation>
		</Record>
		<Record Type="UI.DataField">
			<PropertyValue Property="Value" Path="BookingFee" />
		</Record>
		<Record Type="UI.DataField">
			<PropertyValue Property="Value" Path="TotalPrice" />
		</Record>
	</Collection>
</Annotation>
```

**LANGUAGE**: ABAP

**CODE**:
```abap
@UI.lineItem: [
    { position: 10, importance: #HIGH }
  ]
  TravelID;

  @UI.lineItem: [
    { position: 20, importance: #HIGH }
  ]
  BeginDate;

  @UI.lineItem: [
    { position: 30, importance: #HIGH }
  ]
  EndDate;

  @UI.lineItem: [
    { position: 40, importance: #HIGH }
  ]
  AgencyID;

  @UI.lineItem: [
    { position: 50, importance: #HIGH, criticality: 'TravelStatusCriticality' }
  ]
  TravelStatusCode;

  @UI.lineItem: [
    { position: 60 }
  ]
  BookingFee;

  @UI.lineItem: [
    { position: 70 }
  ]
  TotalPrice;

  @UI.hidden: true
  TravelStatusCriticality;
```

**ADDITIONAL RELATED CODE BLOCKS**:

**FILE**: Sample.fragment.xml

**LANGUAGE**: XML

**CODE**:
```xml
<core:FragmentDefinition xmlns:core="sap.ui.core" xmlns="sap.m" xmlns:macros="sap.fe.macros">
	<macros:Table metaPath="/Travel/@com.sap.vocabularies.UI.v1.LineItem" />
</core:FragmentDefinition>

```

**FILE**: service.cds

**LANGUAGE**: CDS

**CODE**:
```cds
using {
  sap,
  managed,
  Currency,
  Country
} from '@sap/cds/common';

using from '../service/annotations';

@cds.autoexpose  @readonly
aspect MasterData {}

service TravelService {
  @odata.draft.enabled
  @Common.SemanticKey: [TravelID]

  entity Travel : managed {
    key TravelUUID    : UUID;

        @Common.Label          : 'ID'
        @Common.Text           : Description
        TravelID      : Integer default 0                         @readonly;

        @Common.Label          : 'Begin Date'
        BeginDate     : Date;

        @Common.Label          : 'End Date'
        EndDate       : Date;

        @Common.Label          : 'Booking Fee'
        BookingFee    : Decimal(10, 2) default 0                  @Measures.ISOCurrency: CurrencyCode_code;

        @Common.Label          : 'Total Price'
        TotalPrice    : Decimal(10, 2)                            @readonly  @Measures.ISOCurrency: CurrencyCode_code;

        @Common.Label          : 'Currency'
        CurrencyCode  : Association to CurrencyCode default 'EUR' @mandatory;

        @Common.Label          : 'Description'
        Description   : String(1024);

        @Common.Label          : 'Travel Details'
        @UI.MultiLineText
        TravelDetails : String(1024);

        @title                 : 'Status'
        @Common.Text           : TravelStatus.name
        @Common.TextArrangement: #TextOnly
        TravelStatus  : Association to TravelStatus default 'O'   @readonly;

        @title                 : 'Agency'
        @Common.Text           : to_Agency.Name
        @Common.TextArrangement: #TextFirst
        to_Agency     : Association to TravelAgency               @mandatory;

        to_Booking    : Composition of many Booking
                          on to_Booking.to_Travel = $self;
  };

  entity Booking : managed {
    key BookingUUID   : UUID;

        @Common.Label: 'Booking ID'
        BookingID     : Integer                                  @Core.Computed;

        @Common.Label: 'Booking Date'
        BookingDate   : Date;

        @Common.Label: 'Connection'
        ConnectionID  : String(4)                                @mandatory;

        @Common.Label: 'Flight Date'
        FlightDate    : Date                                     @mandatory;

        @Common.Label: 'Flight Price'
        FlightPrice   : Decimal(10, 2)                           @Measures.ISOCurrency: CurrencyCode_code;

        @Common.Label: 'Currency'
        CurrencyCode  : Currency default 'EUR'                   @mandatory;

        @Common.Label: 'Status'
        BookingStatus : Association to BookingStatus default 'N' @mandatory;
        to_Travel     : Association to Travel                    @mandatory;

        PaymentMethod : String(1) default 'B'                    @Common              : {
          Label                   : 'Payment Method',
          Text                    : _Payment.Method,
          TextArrangement         : #TextOnly,
          ValueListWithFixedValues: true,
          ValueList               : {
            Label         : 'Payment Method',
            CollectionPath: 'Payment',
            Parameters    : [{
              $Type            : 'Common.ValueListParameterInOut',
              LocalDataProperty: PaymentMethod,
              ValueListProperty: 'code'
            }]
          }
        };
        _Payment      : Association to one Payment
                          on _Payment.code = PaymentMethod;
  };

  entity Payment {
    key code   : String(1) @(Common: {
          Label          : 'Payment Code',
          Text           : Method,
          TextArrangement: #TextFirst
        });
        Method : String    @(
          Core.Immutable: true,
          Common.Label  : 'Payment Method'
        );
  }

  entity TravelStatus : sap.common.CodeList {
    key code        : String(1) @Common.Text: descr;
        name        : String(255);
        descr       : String(1000);
        criticality : Int16     @odata.Type : 'Edm.Byte' enum {
          Neutral  = 0;
          Negative = 1;
          Critical = 2;
          Positive = 3;
          NewItem  = 5
        };
  };

  entity CurrencyCode : sap.common.CodeList {
        @Common.Label: 'Currency Code'
    key code  : String(3);

        @Common.Label: 'Currency Description'
        descr : String(255);
  };

  entity BookingStatus : sap.common.CodeList {
    key code : BookingStatusCode
  };

  entity TravelAgency : MasterData {
        @Common.Label: 'Agency ID'
        @Common.Text : Name
    key AgencyID       : String(6);

        @Common.Label: 'Agency Name'
        Name           : String(80);
        Street         : String(60);

        @Common.Label: 'Postal Code'
        PostalCode     : String(10);

        @Common.Label: 'City'
        City           : String(40);

        @Common.Label: 'Country Code'
        CountryCode    : Country;

        @Common.Label: 'Phone Number'
        PhoneNumber    : String(30);

        @Common.Label: 'Email Address'
        EMailAddress   : String(256);

        @Common.Label: 'Web Address'
        WebAddress     : String(256);
        Rating         : Integer;
        Recommendation : Integer;
  };

  type TravelStatusCode  : String(1) enum {
    Open     = 'O';
    Accepted = 'A';
    Canceled = 'X';
  };

  type BookingStatusCode : String(1) enum {
    New      = 'N';
    Booked   = 'B';
    Canceled = 'X';
  };
}

```

**FILE**: Travel.json

**LANGUAGE**: JSON

**CODE**:
```json
[
	{
		"TravelUUID": "52657221A8E4645C17002DF03754AB66",
		"TravelID": "00000001",
		"BeginDate": "2025-11-04",
		"EndDate": "2025-11-06",
		"BookingFee": "20.00",
		"TotalPrice": "900.00",
		"CurrencyCode_code": "USD",
		"Description": "Business Trip for Christine, Pierre",
		"TravelDetails": "This business trip includes a two-day customer workshop at the airport. The goal is the evaluation of the customer's use cases and the alignment on the road map for the upcoming year.",
		"TravelStatus_code": "A",
		"to_Agency_AgencyID": "070001"
	},
	{
		"TravelUUID": "53657221A8E4645C17002DF03754AB66",
		"TravelID": "00000002",
		"BeginDate": "2025-12-04",
		"EndDate": "2025-12-16",
		"BookingFee": "80.00",
		"TotalPrice": "3164.00",
		"CurrencyCode_code": "USD",
		"Description": "Lars Jensen site visit for system rollout support",
		"TravelDetails": "Will be provided soon...",
		"TravelStatus_code": "O",
		"to_Agency_AgencyID": "070002"
	},
	{
		"TravelUUID": "54657221A8E4645C17002DF03754AB66",
		"TravelID": "00000003",
		"BeginDate": "2025-08-04",
		"EndDate": "2025-08-08",
		"BookingFee": "40.00",
		"TotalPrice": "1871.00",
		"CurrencyCode_code": "USD",
		"Description": "John Smith customer workshop at Acme Corp headquarters",
		"TravelDetails": "Will be provided soon...",
		"TravelStatus_code": "O",
		"to_Agency_AgencyID": "070003"
	},
	{
		"TravelUUID": "55657221A8E4645C17002DF03754AB66",
		"TravelID": "00000004",
		"BeginDate": "2025-09-04",
		"EndDate": "2025-09-05",
		"BookingFee": "40.00",
		"TotalPrice": "1240.00",
		"CurrencyCode_code": "USD",
		"Description": "Anna Müller onboarding with new project team in Berlin",
		"TravelDetails": "Will be provided soon...",
		"TravelStatus_code": "X",
		"to_Agency_AgencyID": "070003"
	}
]

```

**FILE**: manifest.json

**LANGUAGE**: JSON

**CODE**:
```json
{
	"_version": "1.12.0",
	"sap.app": {
		"id": "sap.fe.core.fpmExplorer.tableDefault",
		"type": "application",
		"i18n": {
			"bundleUrl": "i18n/i18n.properties",
			"supportedLocales": [""],
			"fallbackLocale": ""
		},
		"applicationVersion": {
			"version": "1.0.0"
		},
		"dataSources": {
			"mainService": {
				"uri": "/sap/fe/core/mock/service/",
				"type": "OData",
				"settings": {
					"annotations": [],
					"odataVersion": "4.0"
				}
			}
		}
	},
	"sap.ui5": {
		"dependencies": {
			"minUI5Version": "1.111.1",
			"libs": {
				"sap.ui.core": {},
				"sap.fe.templates": {}
			}
		},
		"contentDensities": {
			"compact": true,
			"cozy": true
		},
		"models": {
			"": {
				"dataSource": "mainService",
				"settings": {
					"operationMode": "Server",
					"autoExpandSelect": true,
					"earlyRequests": true
				}
			}
		},
		"routing": {
			"routes": [
				{
					"pattern": ":?query:",
					"name": "default",
					"target": "sample"
				}
			],
			"targets": {
				"sample": {
					"type": "Component",
					"id": "Default",
					"name": "sap.fe.core.fpm",
					"viewLevel": 1,
					"options": {
						"settings": {
							"viewName": "sap.fe.core.fpmExplorer.tableDefault.TableDefault",
							"contextPath": "/Travel"
						}
					}
				}
			}
		}
	}
}

```

Table

table overview grid list data rows columns LineItems


**TITLE**: Usage with Filter Bar

**INTRODUCTION**: Linking the Table building block to the FilterBar building block enables you to render a filter bar for the table.

**TAGS**: filter bar, live mode, filtering, search, integration

**STEP**: Implementation

**DESCRIPTION**: You can connect the Table with a Filter Bar by using the 'filterBar' property of the Table building block. You need to provide the ID of the Filter Bar. This ID can be a local or a global one.

**LANGUAGE**: XML

**CODE**:
```xml
<core:FragmentDefinition xmlns:core="sap.ui.core" xmlns="sap.m" xmlns:macros="sap.fe.macros">
	<VBox>
		<macros:FilterBar metaPath="@com.sap.vocabularies.UI.v1.SelectionFields" id="FilterBar" />
		<macros:Table metaPath="@com.sap.vocabularies.UI.v1.LineItem" id="LineItemTable" filterBar="FilterBar" initialLoad="true" />
	</VBox>
</core:FragmentDefinition>
```

Usage with Filter Bar

filter bar
live mode
filtering
search
integration


**TITLE**: Highlighting Lines

**INTRODUCTION**: The Table building block enables you to add semantic highlights to line items in tables, based on their criticality.

**TAGS**: highlighting, lines, conditional formatting, colors, status, Criticality

**STEP**: Implementation

**DESCRIPTION**: Add a LineItem criticality annotation for the line items of the entity type that is used by a table.

**LANGUAGE**: CDS

**CODE**:
```cds
using {TravelService.Travel} from '../../../../../service/service';
using from '../../../../../service/annotations';

annotate TravelService.Travel with @UI.LineItem: {
  ![@UI.Criticality]: TravelStatus.criticality,
  $value            : [
    {Value: TravelID},
    {Value: BeginDate},
    {Value: EndDate},
    {Value: to_Agency_AgencyID},
    {Value: BookingFee},
    {Value: TotalPrice}
  ]
};
```

**LANGUAGE**: XML

**CODE**:
```xml
<Annotation Term="UI.LineItem">
	<Collection>
		<Record Type="UI.DataField">
			<PropertyValue Property="Value" Path="TravelID" />
		</Record>
		<Record Type="UI.DataField">
			<PropertyValue Property="Value" Path="BeginDate" />
		</Record>
		<Record Type="UI.DataField">
			<PropertyValue Property="Value" Path="EndDate" />
		</Record>
		<Record Type="UI.DataField">
			<PropertyValue Property="Value" Path="to_Agency_AgencyID" />
		</Record>
		<Record Type="UI.DataField">
			<PropertyValue Property="Value" Path="BookingFee" />
		</Record>
		<Record Type="UI.DataField">
			<PropertyValue Property="Value" Path="TotalPrice" />
		</Record>
	</Collection>
	<Annotation Term="UI.Criticality" Path="TravelStatus/criticality" />
</Annotation>
```

**ADDITIONAL RELATED CODE BLOCKS**:

**FILE**: Sample.fragment.xml

**LANGUAGE**: XML

**CODE**:
```xml
<core:FragmentDefinition xmlns:core="sap.ui.core" xmlns="sap.m" xmlns:macros="sap.fe.macros">
	<macros:Table metaPath="/Travel/@com.sap.vocabularies.UI.v1.LineItem" />
</core:FragmentDefinition>

```

**FILE**: service.cds

**LANGUAGE**: CDS

**CODE**:
```cds
using {
  sap,
  managed,
  Currency,
  Country
} from '@sap/cds/common';

using from '../service/annotations';

@cds.autoexpose  @readonly
aspect MasterData {}

service TravelService {
  @odata.draft.enabled
  @Common.SemanticKey: [TravelID]

  entity Travel : managed {
    key TravelUUID    : UUID;

        @Common.Label          : 'ID'
        @Common.Text           : Description
        TravelID      : Integer default 0                         @readonly;

        @Common.Label          : 'Begin Date'
        BeginDate     : Date;

        @Common.Label          : 'End Date'
        EndDate       : Date;

        @Common.Label          : 'Booking Fee'
        BookingFee    : Decimal(10, 2) default 0                  @Measures.ISOCurrency: CurrencyCode_code;

        @Common.Label          : 'Total Price'
        TotalPrice    : Decimal(10, 2)                            @readonly  @Measures.ISOCurrency: CurrencyCode_code;

        @Common.Label          : 'Currency'
        CurrencyCode  : Association to CurrencyCode default 'EUR' @mandatory;

        @Common.Label          : 'Description'
        Description   : String(1024);

        @Common.Label          : 'Travel Details'
        @UI.MultiLineText
        TravelDetails : String(1024);

        @title                 : 'Status'
        @Common.Text           : TravelStatus.name
        @Common.TextArrangement: #TextOnly
        TravelStatus  : Association to TravelStatus default 'O'   @readonly;

        @title                 : 'Agency'
        @Common.Text           : to_Agency.Name
        @Common.TextArrangement: #TextFirst
        to_Agency     : Association to TravelAgency               @mandatory;

        to_Booking    : Composition of many Booking
                          on to_Booking.to_Travel = $self;
  };

  entity Booking : managed {
    key BookingUUID   : UUID;

        @Common.Label: 'Booking ID'
        BookingID     : Integer                                  @Core.Computed;

        @Common.Label: 'Booking Date'
        BookingDate   : Date;

        @Common.Label: 'Connection'
        ConnectionID  : String(4)                                @mandatory;

        @Common.Label: 'Flight Date'
        FlightDate    : Date                                     @mandatory;

        @Common.Label: 'Flight Price'
        FlightPrice   : Decimal(10, 2)                           @Measures.ISOCurrency: CurrencyCode_code;

        @Common.Label: 'Currency'
        CurrencyCode  : Currency default 'EUR'                   @mandatory;

        @Common.Label: 'Status'
        BookingStatus : Association to BookingStatus default 'N' @mandatory;
        to_Travel     : Association to Travel                    @mandatory;

        PaymentMethod : String(1) default 'B'                    @Common              : {
          Label                   : 'Payment Method',
          Text                    : _Payment.Method,
          TextArrangement         : #TextOnly,
          ValueListWithFixedValues: true,
          ValueList               : {
            Label         : 'Payment Method',
            CollectionPath: 'Payment',
            Parameters    : [{
              $Type            : 'Common.ValueListParameterInOut',
              LocalDataProperty: PaymentMethod,
              ValueListProperty: 'code'
            }]
          }
        };
        _Payment      : Association to one Payment
                          on _Payment.code = PaymentMethod;
  };

  entity Payment {
    key code   : String(1) @(Common: {
          Label          : 'Payment Code',
          Text           : Method,
          TextArrangement: #TextFirst
        });
        Method : String    @(
          Core.Immutable: true,
          Common.Label  : 'Payment Method'
        );
  }

  entity TravelStatus : sap.common.CodeList {
    key code        : String(1) @Common.Text: descr;
        name        : String(255);
        descr       : String(1000);
        criticality : Int16     @odata.Type : 'Edm.Byte' enum {
          Neutral  = 0;
          Negative = 1;
          Critical = 2;
          Positive = 3;
          NewItem  = 5
        };
  };

  entity CurrencyCode : sap.common.CodeList {
        @Common.Label: 'Currency Code'
    key code  : String(3);

        @Common.Label: 'Currency Description'
        descr : String(255);
  };

  entity BookingStatus : sap.common.CodeList {
    key code : BookingStatusCode
  };

  entity TravelAgency : MasterData {
        @Common.Label: 'Agency ID'
        @Common.Text : Name
    key AgencyID       : String(6);

        @Common.Label: 'Agency Name'
        Name           : String(80);
        Street         : String(60);

        @Common.Label: 'Postal Code'
        PostalCode     : String(10);

        @Common.Label: 'City'
        City           : String(40);

        @Common.Label: 'Country Code'
        CountryCode    : Country;

        @Common.Label: 'Phone Number'
        PhoneNumber    : String(30);

        @Common.Label: 'Email Address'
        EMailAddress   : String(256);

        @Common.Label: 'Web Address'
        WebAddress     : String(256);
        Rating         : Integer;
        Recommendation : Integer;
  };

  type TravelStatusCode  : String(1) enum {
    Open     = 'O';
    Accepted = 'A';
    Canceled = 'X';
  };

  type BookingStatusCode : String(1) enum {
    New      = 'N';
    Booked   = 'B';
    Canceled = 'X';
  };
}

```

**FILE**: annotations.cds

**LANGUAGE**: CDS

**CODE**:
```cds
using TravelService as service from '../service/service';

annotate service.Travel {
  TravelStatus @Common.ValueListWithFixedValues;
  CurrencyCode @Common.ValueList: {
    CollectionPath: 'Currencies',
    Parameters    : [
      {
        $Type            : 'Common.ValueListParameterInOut',
        LocalDataProperty: CurrencyCode_code,
        ValueListProperty: 'code'
      },
      {
        $Type            : 'Common.ValueListParameterDisplayOnly',
        ValueListProperty: 'name'
      },
      {
        $Type            : 'Common.ValueListParameterDisplayOnly',
        ValueListProperty: 'descr'
      }
    ]
  };
}

annotate service.Travel with @UI.LineItem: [
  {Value: TravelID},
  {
    $Type : 'UI.DataFieldForAnnotation',
    Target: '@UI.ConnectedFields#TripDates'
  },
  {Value: to_Agency_AgencyID},
  {
    Value             : TravelStatus_code,
    Criticality       : TravelStatus.criticality,
    @UI.Importance    : #High,
    @HTML5.CssDefaults: {width: '10em'}
  },
  {Value: BookingFee},
  {Value: TotalPrice}
];

annotate service.Travel with @(UI: {SelectionFields: [
  TravelID,
  to_Agency_AgencyID,
  TravelStatus_code,
  BeginDate,
  EndDate
]});

annotate service.Travel with @Capabilities.FilterRestrictions.FilterExpressionRestrictions: [
  {
    Property          : 'BeginDate',
    AllowedExpressions: 'SingleRange'
  },
  {
    Property          : 'EndDate',
    AllowedExpressions: 'SingleRange'
  }
];

annotate service.Travel with @(UI: {
  FieldGroup #TravelData    : {Data: [
    {Value: TravelID},
    {Value: to_Agency_AgencyID},
    {Value: BeginDate},
    {Value: EndDate}
  ]},
  FieldGroup #ApprovalData  : {Data: [
    {
      $Type      : 'UI.DataField',
      Value      : TravelStatus_code,
      Criticality: TravelStatus.criticality,
      Label      : 'Status'
    },
    {Value: BookingFee},
    {Value: TotalPrice}
  ]},
  FieldGroup #HeaderMain    : {Data: [
    {Value: BeginDate},
    {Value: EndDate},
    {Value: TotalPrice}
  ]},
  ConnectedFields #TripDates: {
    Label   : 'Business Trip Dates',
    Template: '{BeginDate} / {EndDate}',
    Data    : {
      BeginDate: {
        $Type: 'UI.DataField',
        Value: BeginDate
      },
      EndDate  : {
        $Type: 'UI.DataField',
        Value: EndDate
      }
    }
  },
  Facets                    : [
    {
      $Type : 'UI.ReferenceFacet',
      ID    : 'TravelData',
      Label : 'Travel Information',
      Target: '@UI.FieldGroup#TravelData',
    },
    {
      $Type : 'UI.ReferenceFacet',
      ID    : 'ApprovalData',
      Label : 'Approval Data',
      Target: '@UI.FieldGroup#ApprovalData'
    },
    {
      $Type : 'UI.ReferenceFacet',
      ID    : 'BookingList',
      Label : 'Bookings',
      Target: 'to_Booking/@UI.LineItem'
    }
  ],
  HeaderFacets              : [{
    $Type : 'UI.ReferenceFacet',
    Target: '@UI.FieldGroup#HeaderMain'
  }],
  HeaderInfo                : {
    TypeName      : 'Travel',
    TypeNamePlural: 'Travels',
    Title         : {
      $Type: 'UI.DataField',
      Value: Description
    },
    Description   : {
      $Type: 'UI.DataField',
      Value: TravelID
    },
    TypeImageUrl  : 'sap-icon://header',
  }
});

annotate service.Travel {
  to_Agency @Common.ValueList: {
    CollectionPath: 'TravelAgency',
    Label         : '',
    Parameters    : [
      {
        $Type            : 'Common.ValueListParameterInOut',
        LocalDataProperty: to_Agency_AgencyID,
        ValueListProperty: 'AgencyID'
      },
      {
        $Type            : 'Common.ValueListParameterDisplayOnly',
        ValueListProperty: 'Name'
      },
      {
        $Type            : 'Common.ValueListParameterDisplayOnly',
        ValueListProperty: 'Street'
      },
      {
        $Type            : 'Common.ValueListParameterDisplayOnly',
        ValueListProperty: 'PostalCode'
      },
      {
        $Type            : 'Common.ValueListParameterDisplayOnly',
        ValueListProperty: 'City'
      },
      {
        $Type            : 'Common.ValueListParameterDisplayOnly',
        ValueListProperty: 'CountryCode_code'
      },
      {
        $Type            : 'Common.ValueListParameterDisplayOnly',
        ValueListProperty: 'PhoneNumber'
      },
      {
        $Type            : 'Common.ValueListParameterDisplayOnly',
        ValueListProperty: 'EMailAddress'
      },
      {
        $Type            : 'Common.ValueListParameterDisplayOnly',
        ValueListProperty: 'WebAddress'
      }
    ]
  };
}

annotate service.TravelAgency with @(UI: {
  DataPoint #Recommendation: {
    Value        : Recommendation,
    TargetValue  : 100.0,
    Title        : 'Recommendation',
    Visualization: #Progress
  },
  DataPoint #Rating        : {
    Value        : Rating,
    TargetValue  : 5.0,
    Title        : 'Rating',
    Visualization: #Rating
  },
  FieldGroup #Contact      : {Data: [{
    $Type : 'UI.DataFieldForAnnotation',
    Target: '@Communication.Contact',
    Label : 'Travel Agency'
  }]}
});

annotate service.TravelAgency with @(
  Communication.Contact : {
    email: [{
      type   : #work,
      address: EMailAddress
    }],
    fn   : Name,
    adr  : [{
      type    : #work,
      code    : PostalCode,
      country : CountryCode_code,
      locality: City
    }]
  },
  Common.IsNaturalPerson: false
);

annotate service.Booking {
  CurrencyCode @Common.ValueList: {
    CollectionPath: 'Currencies',
    Parameters    : [
      {
        $Type            : 'Common.ValueListParameterInOut',
        LocalDataProperty: CurrencyCode_code,
        ValueListProperty: 'code'
      },
      {
        $Type            : 'Common.ValueListParameterDisplayOnly',
        ValueListProperty: 'name'
      },
      {
        $Type            : 'Common.ValueListParameterDisplayOnly',
        ValueListProperty: 'descr'
      }
    ]
  };
}

annotate service.Booking with @(UI: {
  HeaderInfo: {
    TypeName      : 'Booking',
    TypeNamePlural: 'Bookings',
    TypeImageUrl  : 'sap-icon://alert',
    Title         : {
      $Type: 'UI.DataField',
      Value: BookingID
    }
  },
  Facets    : [{
    $Type : 'UI.ReferenceFacet',
    ID    : 'FacetIdentifier1',
    Target: '@UI.FieldGroup'
  }],
  LineItem  : [
    {Value: BookingID},
    {Value: BookingDate},
    {Value: ConnectionID},
    {Value: FlightDate},
    {Value: FlightPrice}
  ],
  FieldGroup: {Data: [
    {
      $Type: 'UI.DataField',
      Value: BookingID
    },
    {
      $Type: 'UI.DataField',
      Value: BookingDate
    },
    {
      $Type: 'UI.DataField',
      Value: FlightDate
    },
    {
      $Type: 'UI.DataField',
      Value: FlightPrice
    }
  ]}
});

annotate service.TravelAgency with @(UI: {FieldGroup #Link: {Data: [{
  $Type: 'UI.DataFieldWithUrl',
  Value: Name,
  Url  : WebAddress
}]}});

```

**FILE**: Travel.json

**LANGUAGE**: JSON

**CODE**:
```json
[
	{
		"TravelUUID": "52657221A8E4645C17002DF03754AB66",
		"TravelID": "00000001",
		"BeginDate": "2025-11-04",
		"EndDate": "2025-11-06",
		"BookingFee": "20.00",
		"TotalPrice": "900.00",
		"CurrencyCode_code": "USD",
		"Description": "Business Trip for Christine, Pierre",
		"TravelStatus_code": "A",
		"to_Agency_AgencyID": "070001"
	},
	{
		"TravelUUID": "53657221A8E4645C17002DF03754AB66",
		"TravelID": "00000002",
		"BeginDate": "2025-12-04",
		"EndDate": "2025-12-16",
		"BookingFee": "80.00",
		"TotalPrice": "3164.00",
		"CurrencyCode_code": "USD",
		"Description": "Lars Jensen site visit for system rollout support",
		"TravelStatus_code": "O",
		"to_Agency_AgencyID": "070002"
	},
	{
		"TravelUUID": "54657221A8E4645C17002DF03754AB66",
		"TravelID": "00000003",
		"BeginDate": "2025-08-04",
		"EndDate": "2025-08-08",
		"BookingFee": "40.00",
		"TotalPrice": "1871.00",
		"CurrencyCode_code": "USD",
		"Description": "John Smith customer workshop at Acme Corp headquarters",
		"TravelStatus_code": "O",
		"to_Agency_AgencyID": "070003"
	},
	{
		"TravelUUID": "55657221A8E4645C17002DF03754AB66",
		"TravelID": "00000004",
		"BeginDate": "2025-09-04",
		"EndDate": "2025-09-05",
		"BookingFee": "40.00",
		"TotalPrice": "1240.00",
		"CurrencyCode_code": "USD",
		"Description": "Anna Müller onboarding with new project team in Berlin",
		"TravelStatus_code": "X",
		"to_Agency_AgencyID": "070003"
	}
]

```

**FILE**: TravelStatus.json

**LANGUAGE**: JSON

**CODE**:
```json
[
	{
		"code": "O",
		"name": "Open",
		"descr": "Open",
		"fieldControl": 7,
		"createDeleteHidden": false,
		"insertDeleteRestriction": true,
		"criticality": 5
	},
	{
		"code": "A",
		"name": "Accepted",
		"descr": "Accepted",
		"fieldControl": 1,
		"createDeleteHidden": true,
		"insertDeleteRestriction": false,
		"criticality": 3
	},
	{
		"code": "X",
		"name": "Canceled",
		"descr": "Canceled",
		"fieldControl": 7,
		"createDeleteHidden": true,
		"insertDeleteRestriction": false,
		"criticality": 1
	}
]

```

Highlighting Lines

highlighting
lines
conditional formatting
colors
status
Criticality


**TITLE**: Mass Edit

**INTRODUCTION**: Mass editing enables users to simultaneously change multiple objects that share the same editable properties.

**TAGS**: mass edit, bulk edit, massedit, mass-edit, quickfilter, quickvariant

**STEP**: Enabling Mass Edit

**DESCRIPTION**: You can enable mass edit by adding the 'massEdit' aggregation to the table. The 'visibleFields' property lets you specify which fields are available in the mass edit dialog, even if these fields are not displayed in the table. The 'ignoredFields' property lets you hide specific fields from the mass edit dialog, even if these fields are displayed in the table.

**LANGUAGE**: XML

**CODE**:
```xml
<core:FragmentDefinition
	xmlns:core="sap.ui.core"
	xmlns="sap.m"
	xmlns:macros="sap.fe.macros"
	xmlns:macrosTable="sap.fe.macros.table"
	xmlns:f="sap.ui.layout.form"
>
	<macros:Table metaPath="/Travel/@com.sap.vocabularies.UI.v1.LineItem">
		<macros:massEdit>
			<macrosTable:MassEdit visibleFields="BeginDate,EndDate,BookingFee" ignoredFields="TravelID,TravelStatus_code">
				<f:FormContainer>
					<f:formElements>
						<f:FormElement label="Custom Element">
							<Text text="This is a custom fragment displayed in the Mass-edit dialog" />
						</f:FormElement>
					</f:formElements>
				</f:FormContainer>
			</macrosTable:MassEdit>
		</macros:massEdit>
	</macros:Table>
</core:FragmentDefinition>
```

**STEP**: Adding Custom Content

**DESCRIPTION**: You can add custom content to the mass edit dialog by using the 'customContent' aggregation of the massEdit. This allows you to include additional fields or controls in the dialog.

**LANGUAGE**: XML

**CODE**:
```xml
<core:FragmentDefinition
	xmlns:core="sap.ui.core"
	xmlns="sap.m"
	xmlns:macros="sap.fe.macros"
	xmlns:macrosTable="sap.fe.macros.table"
	xmlns:f="sap.ui.layout.form"
>
	<macros:Table metaPath="/Travel/@com.sap.vocabularies.UI.v1.LineItem">
		<macros:massEdit>
			<macrosTable:MassEdit visibleFields="BeginDate,EndDate,BookingFee" ignoredFields="TravelID,TravelStatus_code">
				<f:FormContainer>
					<f:formElements>
						<f:FormElement label="Custom Element">
							<Text text="This is a custom fragment displayed in the Mass-edit dialog" />
						</f:FormElement>
					</f:formElements>
				</f:FormContainer>
			</macrosTable:MassEdit>
		</macros:massEdit>
	</macros:Table>
</core:FragmentDefinition>
```

**STEP**: Enabling through Manifest

**DESCRIPTION**: If you want to enable mass edit to your object page table rendered through UI.Facet annotations, you can use the 'enableMassEdit' property in the controlConfiguration section of the respective UI.LineItem.

**LANGUAGE**: JSON

**CODE**:
```json
{
	"sample": {
		"type": "Component",
		"id": "sample",
		"name": "sap.fe.templates.ObjectPage",
		"options": {
			"settings": {
				"contextPath": "/Travel",
				"controlConfiguration": {
					"to_Booking/@com.sap.vocabularies.UI.v1.LineItem": {
						"enableMassEdit": {
							"visibleFields": "BeginDate,EndDate,BookingFee",
							"ignoredFields": "TravelID,TravelStatus_code"
						}
					}
				}
			}
		}
	}
}
```

Mass Edit

mass edit
bulk edit
massedit
mass-edit
quickfilter
quickvariant


**TITLE**: Table APIs

**INTRODUCTION**: The Table building block enables you to extend the table using APIs.

**TAGS**: table APIs, presentation variant, get presentation variant, set presentation variant, message handling, variant management

**STEP**: Message Handling

**DESCRIPTION**: You can add and remove messages using the APIs provided by the Table building block.

**STEP**: No Data

**DESCRIPTION**: You can add a custom illustrated message shown once the table shows no data using the APIs provided by the Table building block.

**STEP**: Presentation Variant

**DESCRIPTION**: You can get and set the presentation variant of a table using the APIs provided by the Table building block.

**STEP**: Selection Variant

**DESCRIPTION**: You can get and set the selection variant of a table using the APIs provided by the Table building block.

**STEP**: Variant Management

**DESCRIPTION**: You can get the currently selected variant and change the variant of a table using the APIs provided by the Table building block.

**STEP**: Column Visibility

**DESCRIPTION**: You can hide and show columns of a table using the APIs provided by the Table building block. Please note, this API is still experimental and may change in the future.

Table APIs

table APIs
presentation variant
get presentation variant
set presentation variant
message handling
variant management


**TITLE**: Quick Variant Selection

**INTRODUCTION**: Quick variant selection provides segmented buttons in the toolbar to enable switching between the table content using a selection presentation variant annotation.

**TAGS**: quick variant, quickfilter, quickvariant, presets, filters, quickVariantSelection, PresentationVariant, SelectionVariant, SelectionPresentationVariant

**STEP**: Enabling Quick Variant Selection

**DESCRIPTION**: You can enable quick variant selection in your table by using the 'quickVariantSelection' aggregation of the table macro. This allows you to define a set of selection presentation variants that users can switch between.

**LANGUAGE**: XML

**CODE**:
```xml
<core:FragmentDefinition xmlns:core="sap.ui.core" xmlns="sap.m" xmlns:macros="sap.fe.macros" xmlns:macrosTable="sap.fe.macros.Table">
	<macros:Table metaPath="/Travel/@com.sap.vocabularies.UI.v1.LineItem">
		<macros:quickVariantSelection>
			<macrosTable:QuickVariantSelection
				paths="com.sap.vocabularies.UI.v1.SelectionPresentationVariant#All,com.sap.vocabularies.UI.v1.SelectionPresentationVariant#Approved"
				showCounts="true"
			/>
		</macros:quickVariantSelection>
	</macros:Table>
</core:FragmentDefinition>
```

**STEP**: Enabling through Manifest

**DESCRIPTION**: If you want to enable quick variant selection to your object page table rendered through UI.Facet annotations, you can use the 'quickVariantSelection' property in the controlConfiguration section of the respective UI.LineItem.

**LANGUAGE**: JSON

**CODE**:
```json
{
	"sample": {
		"type": "Component",
		"id": "sample",
		"name": "sap.fe.templates.ObjectPage",
		"options": {
			"settings": {
				"contextPath": "/Travel",
				"controlConfiguration": {
					"to_Booking/@com.sap.vocabularies.UI.v1.LineItem": {
						"quickVariantSelection": {
							"paths": [
								{
									"annotationPath": "com.sap.vocabularies.UI.v1.SelectionPresentationVariant#All"
								},
								{
									"annotationPath": "com.sap.vocabularies.UI.v1.SelectionPresentationVariant#Approved"
								}
							],
							"showCounts": true
						}
					}
				}
			}
		}
	}
}
```

**STEP**: Defining Selection Presentation Variants

**DESCRIPTION**: You can define selection presentation variants by using the UI.SelectionPresentationVariant in your CDS service. The selection presentation variants point to UI.SelectionVariant and UI.PresentationVariant annotations. These selection presentation variants will be used by the quick variant selection control to switch between different views of the table content.

**LANGUAGE**: CDS

**CODE**:
```cds
using {TravelService.Travel} from '../../../../../service/service';
using from '../../../../../service/annotations';

annotate TravelService.Travel with @UI: {
  LineItem                              : [
    {Value: TravelID},
    {Value: BeginDate},
    {Value: EndDate},
    {Value: to_Agency_AgencyID},
    {Value: BookingFee},
    {Value: TotalPrice}
  ],
  PresentationVariant                   : {
    $Type         : 'UI.PresentationVariantType',
    Visualizations: ['@UI.LineItem']
  },
  SelectionVariant #Approved            : {
    $Type        : 'UI.SelectionVariantType',
    Text         : 'Approved',
    SelectOptions: [{
      $Type       : 'UI.SelectOptionType',
      PropertyName: 'TravelStatus_code',
      Ranges      : [{
        $Type : 'UI.SelectionRangeType',
        Sign  : #I,
        Option: #EQ,
        Low   : 'A'
      }]
    }]
  },
  SelectionPresentationVariant #Approved: {
    $Type              : 'UI.SelectionPresentationVariantType',
    SelectionVariant   : ![@UI.SelectionVariant#Approved],
    PresentationVariant: ![@UI.PresentationVariant],
    Text               : 'Approved',
  },
  SelectionPresentationVariant #All     : {
    $Type              : 'UI.SelectionPresentationVariantType',
    SelectionVariant   : {
      $Type: 'UI.SelectionVariantType',
      Text : 'All'
    },
    PresentationVariant: ![@UI.PresentationVariant],
    Text               : 'All'
  }
};
```

**LANGUAGE**: XML

**CODE**:
```xml
<Annotations Target="TravelService.Travel">
	<Annotation Term="UI.PresentationVariant">
		<Record Type="UI.PresentationVariantType">
			<PropertyValue Property="Visualizations">
				<Collection>
					<AnnotationPath>@UI.LineItem</AnnotationPath>
				</Collection>
			</PropertyValue>
		</Record>
	</Annotation>
	<Annotation Term="UI.SelectionVariant" Qualifier="Approved">
		<Record Type="UI.SelectionVariantType">
			<PropertyValue Property="Text" String="Approved" />
			<PropertyValue Property="SelectOptions">
				<Collection>
					<Record Type="UI.SelectOptionType">
						<PropertyValue Property="PropertyName" PropertyPath="TravelStatus_code" />
						<PropertyValue Property="Ranges">
							<Collection>
								<Record Type="UI.SelectionRangeType">
									<PropertyValue Property="Sign" EnumMember="UI.SelectionRangeSignType/I" />
									<PropertyValue Property="Option" EnumMember="UI.SelectionRangeOptionType/EQ" />
									<PropertyValue Property="Low" String="A" />
								</Record>
							</Collection>
						</PropertyValue>
					</Record>
				</Collection>
			</PropertyValue>
		</Record>
	</Annotation>
	<Annotation Term="UI.SelectionPresentationVariant" Qualifier="Approved">
		<Record Type="UI.SelectionPresentationVariantType">
			<PropertyValue Property="SelectionVariant" Path="@UI.SelectionVariant#Approved" />
			<PropertyValue Property="PresentationVariant" Path="@UI.PresentationVariant" />
			<PropertyValue Property="Text" String="Approved" />
		</Record>
	</Annotation>
	<Annotation Term="UI.SelectionPresentationVariant" Qualifier="All">
		<Record Type="UI.SelectionPresentationVariantType">
			<PropertyValue Property="SelectionVariant">
				<Record Type="UI.SelectionVariantType">
					<PropertyValue Property="Text" String="All" />
				</Record>
			</PropertyValue>
			<PropertyValue Property="PresentationVariant" Path="@UI.PresentationVariant" />
			<PropertyValue Property="Text" String="All" />
		</Record>
	</Annotation>
</Annotations>
```

Quick Variant Selection

quick variant
quickfilter
quickvariant
presets
filters
quickVariantSelection
PresentationVariant
SelectionVariant
SelectionPresentationVariant