**TITLE**: Custom Actions

**INTRODUCTION**: No introduction

**TAGS**: action visibility, action enablement, hide in edit mode, secured execution

**STEP**: Defining the 'Show Message' Manifest Action

**DESCRIPTION**: The Show Message action is defined in the manifest.json file. Its visibility and enablement is controlled by the content of the HeaderActionVisible and HeaderBooleanEnabled fields in the Travel entity. In edit mode, you can change the values of the “Show Message” Enabled and “Show Message” Visible fields to see the action switching between enabled and disabled, visible and hidden.

**LANGUAGE**: JSON

**CODE**:
```json
{
	"_version": "1.12.0",
	"sap.app": {
		"id": "sap.fe.core.fpmExplorer.customAction",
		"type": "application",
		"i18n": {
			"bundleUrl": "i18n/i18n.properties",
			"supportedLocales": [""],
			"fallbackLocale": ""
		},
		"applicationVersion": {
			"version": "1.0.0"
		},
		"dataSources": {
			"mainService": {
				"uri": "/sap/fe/core/mock/customAction/",
				"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": {
			"i18n": {
				"type": "sap.ui.model.resource.ResourceModel",
				"settings": {
					"bundleName": "sap.fe.core.fpmExplorer.customAction.i18n.i18n"
				}
			},
			"@i18n": {
				"type": "sap.ui.model.resource.ResourceModel",
				"settings": {
					"bundleName": "sap.fe.core.fpmExplorer.customAction.i18n.i18n"
				}
			},
			"": {
				"dataSource": "mainService",
				"settings": {
					"operationMode": "Server",
					"autoExpandSelect": true,
					"earlyRequests": true
				}
			}
		},
		"rootView": {
			"viewName": "sap.fe.core.fpmExplorer.customAction.CustomAction"
		},
		"extends": {
			"extensions": {
				"sap.ui.controllerExtensions": {
					"sap.fe.templates.ObjectPage.ObjectPageController": {
						"controllerName": "sap.fe.core.fpmExplorer.customAction.extendOP"
					}
				}
			}
		},
		"routing": {
			"config": {
				"controlId": "customAction"
			},
			"routes": [
				{
					"pattern": "/Travel({key}):?query:",
					"name": "objectPage",
					"target": "objectPage"
				},
				{
					"pattern": "/Travel({key})/to_Booking({key2}):?query:",
					"name": "subObjectPage",
					"target": "subObjectPage"
				}
			],
			"targets": {
				"objectPage": {
					"type": "Component",
					"id": "Default",
					"name": "sap.fe.templates.ObjectPage",
					"viewLevel": 1,
					"options": {
						"settings": {
							"contextPath": "/Travel",

							"content": {
								"header": {
									"actions": {
										"customHeaderActionShowMessage": {
											"press": ".extension.sap.fe.core.fpmExplorer.customAction.extendOP.onPress",
											"visible": "{= %{HeaderActionVisible} === 1 }",
											"enabled": "{= %{HeaderBooleanEnabled}}",
											"text": "{i18n>showMessage}"
										},
										"customHeaderActionShowAlert": {
											"press": "sap.fe.core.fpmExplorer.customAction.CustomAction.alertHeader",
											"visible": "{= ${/EntitiesSingleton/ShowAlertVisible}}",
											"enabled": "{ui>/isEditable}",
											"text": "{i18n>showAlert}"
										},
										"setTravelStatus": {
											"text": "{i18n>setTravelStatus}",
											"press": "sap.fe.core.fpmExplorer.customAction.CustomAction.setTravelStatus"
										},
										"DataFieldForActionGroup::TravelActions": {
											"menu": [
												"DataFieldForAction::TravelService.CopyAction",
												"DataFieldForAction::TravelService.ShareAction",
												"DataFieldForAction::TravelService.CheckStatusAction",
												"setTravelStatus"
											],
											"position": {
												"anchor": "customHeaderActionShowAlert",
												"position": "After"
											}
										}
									}
								},
								"footer": {
									"actions": {
										"customRevertChangesAction": {
											"press": "sap.fe.core.fpmExplorer.customAction.CustomAction.revertChangesAction",
											"visible": "{= !${ui>/isEditable}}",
											"enabled": true,
											"text": "{i18n>customRevertChangesAction}"
										}
									}
								}
							},

							"controlConfiguration": {
								"@com.sap.vocabularies.UI.v1.FieldGroup#TravelData": {
									"actions": {
										"customSectionAction": {
											"press": "sap.fe.core.fpmExplorer.customAction.CustomAction.securedExecution",
											"visible": "{= %{NameProperty} === 'Visible'}",
											"enabled": "{= %{BooleanProperty}}",
											"text": "{i18n>customSectionAction}"
										}
									}
								},
								"to_Booking/@com.sap.vocabularies.UI.v1.LineItem": {
									"actions": {
										"customActionShowTotalPrice": {
											"press": "sap.fe.core.fpmExplorer.customAction.CustomAction.showTotalPrice",
											"text": "{i18n>customShowTotalPrice}",
											"enabled": "{= !${ui>/isEditable}}"
										}
									}
								}
							},
							"navigation": {
								"Booking": {
									"detail": {
										"route": "subObjectPage"
									}
								}
							}
						}
					}
				},
				"subObjectPage": {
					"type": "Component",
					"id": "subObjectPage",
					"name": "sap.fe.templates.ObjectPage",
					"viewLevel": 2,
					"options": {
						"settings": {
							"contextPath": "/Travel/to_Booking"
						}
					}
				}
			}
		}
	}
}
```

**LANGUAGE**: TypeScript

**CODE**:
```typescript
import MessageToast from "sap/m/MessageToast";
import ControllerExtension from "sap/ui/core/mvc/ControllerExtension";
import type Context from "sap/ui/model/odata/v4/Context";

export default class ExtendOPController extends ControllerExtension {
	// controller extensions can be used for handling manifest based custom action events
	public onPress(context: Context): void {
		MessageToast.show("Controller extension based action handler invoked for Travel item '" + context.getObject().Description + "'");
	}
}
```

**STEP**: Defining the 'Show Alert' Manifest Action

**DESCRIPTION**: The Show Alert action is defined in the manifest.json file. Its visibility is controlled by the  /EntitiesSingleton/ShowAlertVisible singleton within the EntitiesSingleton.json file. The enablement depends on the state of the object page: the action is only enabled in edit mode. This is controlled by the ui>/isEditable expression.

**LANGUAGE**: JSON

**CODE**:
```json
{
	"_version": "1.12.0",
	"sap.app": {
		"id": "sap.fe.core.fpmExplorer.customAction",
		"type": "application",
		"i18n": {
			"bundleUrl": "i18n/i18n.properties",
			"supportedLocales": [""],
			"fallbackLocale": ""
		},
		"applicationVersion": {
			"version": "1.0.0"
		},
		"dataSources": {
			"mainService": {
				"uri": "/sap/fe/core/mock/customAction/",
				"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": {
			"i18n": {
				"type": "sap.ui.model.resource.ResourceModel",
				"settings": {
					"bundleName": "sap.fe.core.fpmExplorer.customAction.i18n.i18n"
				}
			},
			"@i18n": {
				"type": "sap.ui.model.resource.ResourceModel",
				"settings": {
					"bundleName": "sap.fe.core.fpmExplorer.customAction.i18n.i18n"
				}
			},
			"": {
				"dataSource": "mainService",
				"settings": {
					"operationMode": "Server",
					"autoExpandSelect": true,
					"earlyRequests": true
				}
			}
		},
		"rootView": {
			"viewName": "sap.fe.core.fpmExplorer.customAction.CustomAction"
		},
		"extends": {
			"extensions": {
				"sap.ui.controllerExtensions": {
					"sap.fe.templates.ObjectPage.ObjectPageController": {
						"controllerName": "sap.fe.core.fpmExplorer.customAction.extendOP"
					}
				}
			}
		},
		"routing": {
			"config": {
				"controlId": "customAction"
			},
			"routes": [
				{
					"pattern": "/Travel({key}):?query:",
					"name": "objectPage",
					"target": "objectPage"
				},
				{
					"pattern": "/Travel({key})/to_Booking({key2}):?query:",
					"name": "subObjectPage",
					"target": "subObjectPage"
				}
			],
			"targets": {
				"objectPage": {
					"type": "Component",
					"id": "Default",
					"name": "sap.fe.templates.ObjectPage",
					"viewLevel": 1,
					"options": {
						"settings": {
							"contextPath": "/Travel",

							"content": {
								"header": {
									"actions": {
										"customHeaderActionShowMessage": {
											"press": ".extension.sap.fe.core.fpmExplorer.customAction.extendOP.onPress",
											"visible": "{= %{HeaderActionVisible} === 1 }",
											"enabled": "{= %{HeaderBooleanEnabled}}",
											"text": "{i18n>showMessage}"
										},
										"customHeaderActionShowAlert": {
											"press": "sap.fe.core.fpmExplorer.customAction.CustomAction.alertHeader",
											"visible": "{= ${/EntitiesSingleton/ShowAlertVisible}}",
											"enabled": "{ui>/isEditable}",
											"text": "{i18n>showAlert}"
										},
										"setTravelStatus": {
											"text": "{i18n>setTravelStatus}",
											"press": "sap.fe.core.fpmExplorer.customAction.CustomAction.setTravelStatus"
										},
										"DataFieldForActionGroup::TravelActions": {
											"menu": [
												"DataFieldForAction::TravelService.CopyAction",
												"DataFieldForAction::TravelService.ShareAction",
												"DataFieldForAction::TravelService.CheckStatusAction",
												"setTravelStatus"
											],
											"position": {
												"anchor": "customHeaderActionShowAlert",
												"position": "After"
											}
										}
									}
								},
								"footer": {
									"actions": {
										"customRevertChangesAction": {
											"press": "sap.fe.core.fpmExplorer.customAction.CustomAction.revertChangesAction",
											"visible": "{= !${ui>/isEditable}}",
											"enabled": true,
											"text": "{i18n>customRevertChangesAction}"
										}
									}
								}
							},

							"controlConfiguration": {
								"@com.sap.vocabularies.UI.v1.FieldGroup#TravelData": {
									"actions": {
										"customSectionAction": {
											"press": "sap.fe.core.fpmExplorer.customAction.CustomAction.securedExecution",
											"visible": "{= %{NameProperty} === 'Visible'}",
											"enabled": "{= %{BooleanProperty}}",
											"text": "{i18n>customSectionAction}"
										}
									}
								},
								"to_Booking/@com.sap.vocabularies.UI.v1.LineItem": {
									"actions": {
										"customActionShowTotalPrice": {
											"press": "sap.fe.core.fpmExplorer.customAction.CustomAction.showTotalPrice",
											"text": "{i18n>customShowTotalPrice}",
											"enabled": "{= !${ui>/isEditable}}"
										}
									}
								}
							},
							"navigation": {
								"Booking": {
									"detail": {
										"route": "subObjectPage"
									}
								}
							}
						}
					}
				},
				"subObjectPage": {
					"type": "Component",
					"id": "subObjectPage",
					"name": "sap.fe.templates.ObjectPage",
					"viewLevel": 2,
					"options": {
						"settings": {
							"contextPath": "/Travel/to_Booking"
						}
					}
				}
			}
		}
	}
}
```

**LANGUAGE**: TypeScript

**CODE**:
```typescript
sap.ui.define(["sap/m/MessageToast", "sap/ui/core/message/Message", "sap/ui/core/Messaging"], function (MessageToast, Message, Messaging) {
	"use strict";

	return {
		message: function (oContext, aSelectedContexts) {
			var sMsgText;
			if (this.getModel("ui").getProperty("/isEditable")) {
				sMsgText = "This action can't be triggered in edit mode";
				MessageToast.show(sMsgText);
			} else if (oContext) {
				// we assume with context = OP, without context = LR
				// Object Page
				sMsgText = "Custom Header action invoked for object '" + oContext.getObject().TitleProperty;
				if (aSelectedContexts.length > 0) {
					sMsgText +=
						"' with selected context \n" +
						aSelectedContexts
							.map(function (ctx) {
								return ctx.getPath();
							})
							.join(",\n");
				}
				MessageToast.show(sMsgText);
			}
		},
		securedExecution: function (oContext, aSelectedContexts) {
			/* This action is encapsulated using the securedExecution method. This ensures the inner function is called
			   only after all previous tasks are fulfilled. By default it sets the UI to busy during execution.
			   Once the task is done, the message handler checks for any new unbound message to be shown to the user.
			   In this example updatesDocument is set to true. As a result, the draft status is updated
			   and the user has to confirm the cancellation of the editing process.
			 */

			this.editFlow.securedExecution(
				function () {
					MessageToast.show("This operation will take a few seconds");
					return new Promise(function (resolve, reject) {
						setTimeout(function () {
							// Adding an unbound message to the message handler which is shown after execution.
							// Same also works for unbound messages sent by any service call.
							Messaging.addMessages(
								new Message({
									message: "The operation was successful",
									target: "",
									persistent: true,
									type: "Success",
									code: "123"
								})
							);
							resolve();
						}, 5000);
					});
				},
				{
					updatesDocument: true
				}
			);
		},
		alertHeader: function (oContext, aSelectedContexts) {
			MessageToast.show("Alert triggered from header action 'Show Alert'");
		},
		revertChangesAction: function (oContext, aSelectedContexts) {
			MessageToast.show("Revert Changes triggered from footer action");
		},
		showTotalPrice: function (oContext, aSelectedContexts) {
			MessageToast.show("Show Total Price triggered from Table Toolbar");
		},
		setTravelStatus: function (oContext, aSelectedContexts) {
			MessageToast.show("Set Travel Status action triggered");
		}
	};
});
```

**STEP**: Enhancing an Action Group

**DESCRIPTION**: The Travel Actions action group is defined in the service by annotations and enhanced in the manifest.json file. The Copy and Share actions are defined by annotations. In the manifest.json file, two more actions, Check Travel Status and Set Travel Status, are added to the action group.

					- Check Travel Status is also defined in the service but added to the action group with the manifest setting.

					- Set Travel Status is a custom action defined and added to the action group in the manifest.json file. It is therefore not part of the service and is only available for a specific application

**LANGUAGE**: CDS

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

extend service TravelService with {
  entity ActionVisibilityEntity {
    key code        : Integer    @(
          Common: {
            Text           : Description,
            TextArrangement: #TextFirst
          },
          title : 'Visibility'
        );
        Description : String(20) @(
          Core.Immutable: true,
          Common        : {Label: 'Value Help Description'}
        );
  }

  @odata.singleton
  entity EntitiesSingleton {
    key DoNotChange      : Integer @Core.Computed;
        ShowAlertVisible : Boolean @Core.Computed;
  }
}

extend entity TravelService.Travel with {
  HeaderBooleanEnabled  : Boolean @title: 'Boolean';
  HeaderActionVisible   : Integer @title: 'Boolean';
  ShowAlertDescription1 : String  @title: 'Description'  @UI.MultiLineText: true  @readonly;
  ShowAlertDescription2 : String  @title: 'Description'  @UI.MultiLineText: true  @readonly;
  NameProperty          : String  @title: 'Secured Execution Visibility';
  BooleanProperty       : Boolean @title: 'Boolean';
  visible               : Association to TravelService.ActionVisibilityEntity
                            on visible.code = $self.HeaderActionVisible;
} actions {
  action CopyAction();
  action ShareAction();
  action CheckStatusAction();
}

extend entity TravelService.Booking with {
  TextProperty : String @title: 'Text';
}

annotate TravelService.Travel with
@(UI: {

  Identification        : [
    {
      $Type  : 'UI.DataFieldForActionGroup',
      ID     : 'TravelActions',
      Label  : 'Travel Actions',
      Actions: [
        {
          $Type : 'UI.DataFieldForAction',
          Label : 'Copy',
          Action: 'TravelService.CopyAction',
        },
        {
          $Type : 'UI.DataFieldForAction',
          Label : 'Share',
          Action: 'TravelService.ShareAction',
        }
      ]
    },
    {
      $Type : 'UI.DataFieldForAction',
      Label : 'Check Travel Status',
      Action: 'TravelService.CheckStatusAction',
    }
  ],

  FieldGroup #HeaderMain: {Data: [
    {
      $Type: 'UI.DataField',
      Label: '"Show Message" Enabled',
      Value: HeaderBooleanEnabled
    },
    {
      $Type: 'UI.DataField',
      Label: '"Show Message" Visible',
      Value: HeaderActionVisible
    },
    {
      $Type: 'UI.DataField',
      Label: '"Show Alert" Enabled',
      Value: ShowAlertDescription1
    },
    {
      $Type: 'UI.DataField',
      Label: '"Show Alert" Visible',
      Value: ShowAlertDescription2
    }
  ]},

  FieldGroup #TravelData: {Data: [
    {Value: TravelID},
    {Value: to_Agency_AgencyID},
    {Value: BeginDate},
    {Value: EndDate},
    {
      $Type      : 'UI.DataField',
      Value      : TravelStatus_code,
      Criticality: TravelStatus.criticality,
      Label      : 'Status'
    },
    {
      $Type: 'UI.DataField',
      Label: 'Secured Execution Enabled',
      Value: BooleanProperty
    },
    {
      $Type: 'UI.DataField',
      Value: NameProperty
    }
  ]}
}) {
  HeaderActionVisible @(Common: {
    Text                    : visible.Description,
    TextArrangement         : #TextOnly,
    ValueListWithFixedValues: true,
    ValueList               : {
      Label         : 'Value with Value Help',
      CollectionPath: 'ActionVisibilityEntity',
      Parameters    : [
        {
          $Type            : 'Common.ValueListParameterInOut',
          LocalDataProperty: HeaderActionVisible,
          ValueListProperty: 'code'
        },
        {
          $Type            : 'Common.ValueListParameterDisplayOnly',
          ValueListProperty: 'Description'
        }
      ]
    }
  });
  NameProperty        @(Common: {
    // Text                    : visible.Description,
    // TextArrangement         : #TextOnly,
    ValueListWithFixedValues: true,
    ValueList               : {
      Label         : 'Value with Value Help',
      CollectionPath: 'ActionVisibilityEntity',
      Parameters    : [{
        $Type            : 'Common.ValueListParameterInOut',
        LocalDataProperty: NameProperty,
        ValueListProperty: 'Description'
      }]
    }
  });
}

annotate TravelService.Travel with @(UI: {Facets: [
  {
    $Type : 'UI.ReferenceFacet',
    ID    : 'TravelData',
    Label : 'Travel Information',
    Target: '@UI.FieldGroup#TravelData',
  },
  {
    $Type : 'UI.ReferenceFacet',
    ID    : 'BookingList',
    Label : 'Bookings',
    Target: 'to_Booking/@UI.LineItem'
  }
]});

annotate TravelService.Booking with @(UI: {LineItem: [
  {Value: BookingID},
  {Value: BookingDate},
  {Value: ConnectionID},
  {Value: FlightDate},
  {Value: FlightPrice},
  {Value: TextProperty},
]});
```

**LANGUAGE**: JSON

**CODE**:
```json
{
	"_version": "1.12.0",
	"sap.app": {
		"id": "sap.fe.core.fpmExplorer.customAction",
		"type": "application",
		"i18n": {
			"bundleUrl": "i18n/i18n.properties",
			"supportedLocales": [""],
			"fallbackLocale": ""
		},
		"applicationVersion": {
			"version": "1.0.0"
		},
		"dataSources": {
			"mainService": {
				"uri": "/sap/fe/core/mock/customAction/",
				"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": {
			"i18n": {
				"type": "sap.ui.model.resource.ResourceModel",
				"settings": {
					"bundleName": "sap.fe.core.fpmExplorer.customAction.i18n.i18n"
				}
			},
			"@i18n": {
				"type": "sap.ui.model.resource.ResourceModel",
				"settings": {
					"bundleName": "sap.fe.core.fpmExplorer.customAction.i18n.i18n"
				}
			},
			"": {
				"dataSource": "mainService",
				"settings": {
					"operationMode": "Server",
					"autoExpandSelect": true,
					"earlyRequests": true
				}
			}
		},
		"rootView": {
			"viewName": "sap.fe.core.fpmExplorer.customAction.CustomAction"
		},
		"extends": {
			"extensions": {
				"sap.ui.controllerExtensions": {
					"sap.fe.templates.ObjectPage.ObjectPageController": {
						"controllerName": "sap.fe.core.fpmExplorer.customAction.extendOP"
					}
				}
			}
		},
		"routing": {
			"config": {
				"controlId": "customAction"
			},
			"routes": [
				{
					"pattern": "/Travel({key}):?query:",
					"name": "objectPage",
					"target": "objectPage"
				},
				{
					"pattern": "/Travel({key})/to_Booking({key2}):?query:",
					"name": "subObjectPage",
					"target": "subObjectPage"
				}
			],
			"targets": {
				"objectPage": {
					"type": "Component",
					"id": "Default",
					"name": "sap.fe.templates.ObjectPage",
					"viewLevel": 1,
					"options": {
						"settings": {
							"contextPath": "/Travel",

							"content": {
								"header": {
									"actions": {
										"customHeaderActionShowMessage": {
											"press": ".extension.sap.fe.core.fpmExplorer.customAction.extendOP.onPress",
											"visible": "{= %{HeaderActionVisible} === 1 }",
											"enabled": "{= %{HeaderBooleanEnabled}}",
											"text": "{i18n>showMessage}"
										},
										"customHeaderActionShowAlert": {
											"press": "sap.fe.core.fpmExplorer.customAction.CustomAction.alertHeader",
											"visible": "{= ${/EntitiesSingleton/ShowAlertVisible}}",
											"enabled": "{ui>/isEditable}",
											"text": "{i18n>showAlert}"
										},
										"setTravelStatus": {
											"text": "{i18n>setTravelStatus}",
											"press": "sap.fe.core.fpmExplorer.customAction.CustomAction.setTravelStatus"
										},
										"DataFieldForActionGroup::TravelActions": {
											"menu": [
												"DataFieldForAction::TravelService.CopyAction",
												"DataFieldForAction::TravelService.ShareAction",
												"DataFieldForAction::TravelService.CheckStatusAction",
												"setTravelStatus"
											],
											"position": {
												"anchor": "customHeaderActionShowAlert",
												"position": "After"
											}
										}
									}
								},
								"footer": {
									"actions": {
										"customRevertChangesAction": {
											"press": "sap.fe.core.fpmExplorer.customAction.CustomAction.revertChangesAction",
											"visible": "{= !${ui>/isEditable}}",
											"enabled": true,
											"text": "{i18n>customRevertChangesAction}"
										}
									}
								}
							},

							"controlConfiguration": {
								"@com.sap.vocabularies.UI.v1.FieldGroup#TravelData": {
									"actions": {
										"customSectionAction": {
											"press": "sap.fe.core.fpmExplorer.customAction.CustomAction.securedExecution",
											"visible": "{= %{NameProperty} === 'Visible'}",
											"enabled": "{= %{BooleanProperty}}",
											"text": "{i18n>customSectionAction}"
										}
									}
								},
								"to_Booking/@com.sap.vocabularies.UI.v1.LineItem": {
									"actions": {
										"customActionShowTotalPrice": {
											"press": "sap.fe.core.fpmExplorer.customAction.CustomAction.showTotalPrice",
											"text": "{i18n>customShowTotalPrice}",
											"enabled": "{= !${ui>/isEditable}}"
										}
									}
								}
							},
							"navigation": {
								"Booking": {
									"detail": {
										"route": "subObjectPage"
									}
								}
							}
						}
					}
				},
				"subObjectPage": {
					"type": "Component",
					"id": "subObjectPage",
					"name": "sap.fe.templates.ObjectPage",
					"viewLevel": 2,
					"options": {
						"settings": {
							"contextPath": "/Travel/to_Booking"
						}
					}
				}
			}
		}
	}
}
```

**STEP**: Defining an Action To Trigger Secured Execution

**DESCRIPTION**: The Secured Execution action triggers a secured execution by calling the this.editFlow.securedExecution() method. It ensures that the UI shows a busy indicator while the action is executed. The visibility and enablement of this action are controlled by the NameProperty and BooleanProperty fields of the entity. In edit mode, you can change the values of the Secured Execution Enabled and Secured Execution Visible fields to see the action switching between enabled and disabled, visible and hidden.

**LANGUAGE**: JSON

**CODE**:
```json
{
	"_version": "1.12.0",
	"sap.app": {
		"id": "sap.fe.core.fpmExplorer.customAction",
		"type": "application",
		"i18n": {
			"bundleUrl": "i18n/i18n.properties",
			"supportedLocales": [""],
			"fallbackLocale": ""
		},
		"applicationVersion": {
			"version": "1.0.0"
		},
		"dataSources": {
			"mainService": {
				"uri": "/sap/fe/core/mock/customAction/",
				"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": {
			"i18n": {
				"type": "sap.ui.model.resource.ResourceModel",
				"settings": {
					"bundleName": "sap.fe.core.fpmExplorer.customAction.i18n.i18n"
				}
			},
			"@i18n": {
				"type": "sap.ui.model.resource.ResourceModel",
				"settings": {
					"bundleName": "sap.fe.core.fpmExplorer.customAction.i18n.i18n"
				}
			},
			"": {
				"dataSource": "mainService",
				"settings": {
					"operationMode": "Server",
					"autoExpandSelect": true,
					"earlyRequests": true
				}
			}
		},
		"rootView": {
			"viewName": "sap.fe.core.fpmExplorer.customAction.CustomAction"
		},
		"extends": {
			"extensions": {
				"sap.ui.controllerExtensions": {
					"sap.fe.templates.ObjectPage.ObjectPageController": {
						"controllerName": "sap.fe.core.fpmExplorer.customAction.extendOP"
					}
				}
			}
		},
		"routing": {
			"config": {
				"controlId": "customAction"
			},
			"routes": [
				{
					"pattern": "/Travel({key}):?query:",
					"name": "objectPage",
					"target": "objectPage"
				},
				{
					"pattern": "/Travel({key})/to_Booking({key2}):?query:",
					"name": "subObjectPage",
					"target": "subObjectPage"
				}
			],
			"targets": {
				"objectPage": {
					"type": "Component",
					"id": "Default",
					"name": "sap.fe.templates.ObjectPage",
					"viewLevel": 1,
					"options": {
						"settings": {
							"contextPath": "/Travel",

							"content": {
								"header": {
									"actions": {
										"customHeaderActionShowMessage": {
											"press": ".extension.sap.fe.core.fpmExplorer.customAction.extendOP.onPress",
											"visible": "{= %{HeaderActionVisible} === 1 }",
											"enabled": "{= %{HeaderBooleanEnabled}}",
											"text": "{i18n>showMessage}"
										},
										"customHeaderActionShowAlert": {
											"press": "sap.fe.core.fpmExplorer.customAction.CustomAction.alertHeader",
											"visible": "{= ${/EntitiesSingleton/ShowAlertVisible}}",
											"enabled": "{ui>/isEditable}",
											"text": "{i18n>showAlert}"
										},
										"setTravelStatus": {
											"text": "{i18n>setTravelStatus}",
											"press": "sap.fe.core.fpmExplorer.customAction.CustomAction.setTravelStatus"
										},
										"DataFieldForActionGroup::TravelActions": {
											"menu": [
												"DataFieldForAction::TravelService.CopyAction",
												"DataFieldForAction::TravelService.ShareAction",
												"DataFieldForAction::TravelService.CheckStatusAction",
												"setTravelStatus"
											],
											"position": {
												"anchor": "customHeaderActionShowAlert",
												"position": "After"
											}
										}
									}
								},
								"footer": {
									"actions": {
										"customRevertChangesAction": {
											"press": "sap.fe.core.fpmExplorer.customAction.CustomAction.revertChangesAction",
											"visible": "{= !${ui>/isEditable}}",
											"enabled": true,
											"text": "{i18n>customRevertChangesAction}"
										}
									}
								}
							},

							"controlConfiguration": {
								"@com.sap.vocabularies.UI.v1.FieldGroup#TravelData": {
									"actions": {
										"customSectionAction": {
											"press": "sap.fe.core.fpmExplorer.customAction.CustomAction.securedExecution",
											"visible": "{= %{NameProperty} === 'Visible'}",
											"enabled": "{= %{BooleanProperty}}",
											"text": "{i18n>customSectionAction}"
										}
									}
								},
								"to_Booking/@com.sap.vocabularies.UI.v1.LineItem": {
									"actions": {
										"customActionShowTotalPrice": {
											"press": "sap.fe.core.fpmExplorer.customAction.CustomAction.showTotalPrice",
											"text": "{i18n>customShowTotalPrice}",
											"enabled": "{= !${ui>/isEditable}}"
										}
									}
								}
							},
							"navigation": {
								"Booking": {
									"detail": {
										"route": "subObjectPage"
									}
								}
							}
						}
					}
				},
				"subObjectPage": {
					"type": "Component",
					"id": "subObjectPage",
					"name": "sap.fe.templates.ObjectPage",
					"viewLevel": 2,
					"options": {
						"settings": {
							"contextPath": "/Travel/to_Booking"
						}
					}
				}
			}
		}
	}
}
```

**LANGUAGE**: TypeScript

**CODE**:
```typescript
sap.ui.define(["sap/m/MessageToast", "sap/ui/core/message/Message", "sap/ui/core/Messaging"], function (MessageToast, Message, Messaging) {
	"use strict";

	return {
		message: function (oContext, aSelectedContexts) {
			var sMsgText;
			if (this.getModel("ui").getProperty("/isEditable")) {
				sMsgText = "This action can't be triggered in edit mode";
				MessageToast.show(sMsgText);
			} else if (oContext) {
				// we assume with context = OP, without context = LR
				// Object Page
				sMsgText = "Custom Header action invoked for object '" + oContext.getObject().TitleProperty;
				if (aSelectedContexts.length > 0) {
					sMsgText +=
						"' with selected context \n" +
						aSelectedContexts
							.map(function (ctx) {
								return ctx.getPath();
							})
							.join(",\n");
				}
				MessageToast.show(sMsgText);
			}
		},
		securedExecution: function (oContext, aSelectedContexts) {
			/* This action is encapsulated using the securedExecution method. This ensures the inner function is called
			   only after all previous tasks are fulfilled. By default it sets the UI to busy during execution.
			   Once the task is done, the message handler checks for any new unbound message to be shown to the user.
			   In this example updatesDocument is set to true. As a result, the draft status is updated
			   and the user has to confirm the cancellation of the editing process.
			 */

			this.editFlow.securedExecution(
				function () {
					MessageToast.show("This operation will take a few seconds");
					return new Promise(function (resolve, reject) {
						setTimeout(function () {
							// Adding an unbound message to the message handler which is shown after execution.
							// Same also works for unbound messages sent by any service call.
							Messaging.addMessages(
								new Message({
									message: "The operation was successful",
									target: "",
									persistent: true,
									type: "Success",
									code: "123"
								})
							);
							resolve();
						}, 5000);
					});
				},
				{
					updatesDocument: true
				}
			);
		},
		alertHeader: function (oContext, aSelectedContexts) {
			MessageToast.show("Alert triggered from header action 'Show Alert'");
		},
		revertChangesAction: function (oContext, aSelectedContexts) {
			MessageToast.show("Revert Changes triggered from footer action");
		},
		showTotalPrice: function (oContext, aSelectedContexts) {
			MessageToast.show("Show Total Price triggered from Table Toolbar");
		},
		setTravelStatus: function (oContext, aSelectedContexts) {
			MessageToast.show("Set Travel Status action triggered");
		}
	};
});
```

**STEP**: Defining the 'Show Total Price' Action

**DESCRIPTION**: The Show Total Price action is defined in the manifest.json file and depends on the editability of the object page. This action is only enabled when the travel item is in display mode.

**LANGUAGE**: JSON

**CODE**:
```json
{
	"_version": "1.12.0",
	"sap.app": {
		"id": "sap.fe.core.fpmExplorer.customAction",
		"type": "application",
		"i18n": {
			"bundleUrl": "i18n/i18n.properties",
			"supportedLocales": [""],
			"fallbackLocale": ""
		},
		"applicationVersion": {
			"version": "1.0.0"
		},
		"dataSources": {
			"mainService": {
				"uri": "/sap/fe/core/mock/customAction/",
				"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": {
			"i18n": {
				"type": "sap.ui.model.resource.ResourceModel",
				"settings": {
					"bundleName": "sap.fe.core.fpmExplorer.customAction.i18n.i18n"
				}
			},
			"@i18n": {
				"type": "sap.ui.model.resource.ResourceModel",
				"settings": {
					"bundleName": "sap.fe.core.fpmExplorer.customAction.i18n.i18n"
				}
			},
			"": {
				"dataSource": "mainService",
				"settings": {
					"operationMode": "Server",
					"autoExpandSelect": true,
					"earlyRequests": true
				}
			}
		},
		"rootView": {
			"viewName": "sap.fe.core.fpmExplorer.customAction.CustomAction"
		},
		"extends": {
			"extensions": {
				"sap.ui.controllerExtensions": {
					"sap.fe.templates.ObjectPage.ObjectPageController": {
						"controllerName": "sap.fe.core.fpmExplorer.customAction.extendOP"
					}
				}
			}
		},
		"routing": {
			"config": {
				"controlId": "customAction"
			},
			"routes": [
				{
					"pattern": "/Travel({key}):?query:",
					"name": "objectPage",
					"target": "objectPage"
				},
				{
					"pattern": "/Travel({key})/to_Booking({key2}):?query:",
					"name": "subObjectPage",
					"target": "subObjectPage"
				}
			],
			"targets": {
				"objectPage": {
					"type": "Component",
					"id": "Default",
					"name": "sap.fe.templates.ObjectPage",
					"viewLevel": 1,
					"options": {
						"settings": {
							"contextPath": "/Travel",

							"content": {
								"header": {
									"actions": {
										"customHeaderActionShowMessage": {
											"press": ".extension.sap.fe.core.fpmExplorer.customAction.extendOP.onPress",
											"visible": "{= %{HeaderActionVisible} === 1 }",
											"enabled": "{= %{HeaderBooleanEnabled}}",
											"text": "{i18n>showMessage}"
										},
										"customHeaderActionShowAlert": {
											"press": "sap.fe.core.fpmExplorer.customAction.CustomAction.alertHeader",
											"visible": "{= ${/EntitiesSingleton/ShowAlertVisible}}",
											"enabled": "{ui>/isEditable}",
											"text": "{i18n>showAlert}"
										},
										"setTravelStatus": {
											"text": "{i18n>setTravelStatus}",
											"press": "sap.fe.core.fpmExplorer.customAction.CustomAction.setTravelStatus"
										},
										"DataFieldForActionGroup::TravelActions": {
											"menu": [
												"DataFieldForAction::TravelService.CopyAction",
												"DataFieldForAction::TravelService.ShareAction",
												"DataFieldForAction::TravelService.CheckStatusAction",
												"setTravelStatus"
											],
											"position": {
												"anchor": "customHeaderActionShowAlert",
												"position": "After"
											}
										}
									}
								},
								"footer": {
									"actions": {
										"customRevertChangesAction": {
											"press": "sap.fe.core.fpmExplorer.customAction.CustomAction.revertChangesAction",
											"visible": "{= !${ui>/isEditable}}",
											"enabled": true,
											"text": "{i18n>customRevertChangesAction}"
										}
									}
								}
							},

							"controlConfiguration": {
								"@com.sap.vocabularies.UI.v1.FieldGroup#TravelData": {
									"actions": {
										"customSectionAction": {
											"press": "sap.fe.core.fpmExplorer.customAction.CustomAction.securedExecution",
											"visible": "{= %{NameProperty} === 'Visible'}",
											"enabled": "{= %{BooleanProperty}}",
											"text": "{i18n>customSectionAction}"
										}
									}
								},
								"to_Booking/@com.sap.vocabularies.UI.v1.LineItem": {
									"actions": {
										"customActionShowTotalPrice": {
											"press": "sap.fe.core.fpmExplorer.customAction.CustomAction.showTotalPrice",
											"text": "{i18n>customShowTotalPrice}",
											"enabled": "{= !${ui>/isEditable}}"
										}
									}
								}
							},
							"navigation": {
								"Booking": {
									"detail": {
										"route": "subObjectPage"
									}
								}
							}
						}
					}
				},
				"subObjectPage": {
					"type": "Component",
					"id": "subObjectPage",
					"name": "sap.fe.templates.ObjectPage",
					"viewLevel": 2,
					"options": {
						"settings": {
							"contextPath": "/Travel/to_Booking"
						}
					}
				}
			}
		}
	}
}
```

**STEP**: Defining the 'Revert Changes' Action

**DESCRIPTION**: The Revert Changes action is defined in the manifest.json file. It is always enabled but only visible in display mode.

**LANGUAGE**: JSON

**CODE**:
```json
{
	"_version": "1.12.0",
	"sap.app": {
		"id": "sap.fe.core.fpmExplorer.customAction",
		"type": "application",
		"i18n": {
			"bundleUrl": "i18n/i18n.properties",
			"supportedLocales": [""],
			"fallbackLocale": ""
		},
		"applicationVersion": {
			"version": "1.0.0"
		},
		"dataSources": {
			"mainService": {
				"uri": "/sap/fe/core/mock/customAction/",
				"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": {
			"i18n": {
				"type": "sap.ui.model.resource.ResourceModel",
				"settings": {
					"bundleName": "sap.fe.core.fpmExplorer.customAction.i18n.i18n"
				}
			},
			"@i18n": {
				"type": "sap.ui.model.resource.ResourceModel",
				"settings": {
					"bundleName": "sap.fe.core.fpmExplorer.customAction.i18n.i18n"
				}
			},
			"": {
				"dataSource": "mainService",
				"settings": {
					"operationMode": "Server",
					"autoExpandSelect": true,
					"earlyRequests": true
				}
			}
		},
		"rootView": {
			"viewName": "sap.fe.core.fpmExplorer.customAction.CustomAction"
		},
		"extends": {
			"extensions": {
				"sap.ui.controllerExtensions": {
					"sap.fe.templates.ObjectPage.ObjectPageController": {
						"controllerName": "sap.fe.core.fpmExplorer.customAction.extendOP"
					}
				}
			}
		},
		"routing": {
			"config": {
				"controlId": "customAction"
			},
			"routes": [
				{
					"pattern": "/Travel({key}):?query:",
					"name": "objectPage",
					"target": "objectPage"
				},
				{
					"pattern": "/Travel({key})/to_Booking({key2}):?query:",
					"name": "subObjectPage",
					"target": "subObjectPage"
				}
			],
			"targets": {
				"objectPage": {
					"type": "Component",
					"id": "Default",
					"name": "sap.fe.templates.ObjectPage",
					"viewLevel": 1,
					"options": {
						"settings": {
							"contextPath": "/Travel",

							"content": {
								"header": {
									"actions": {
										"customHeaderActionShowMessage": {
											"press": ".extension.sap.fe.core.fpmExplorer.customAction.extendOP.onPress",
											"visible": "{= %{HeaderActionVisible} === 1 }",
											"enabled": "{= %{HeaderBooleanEnabled}}",
											"text": "{i18n>showMessage}"
										},
										"customHeaderActionShowAlert": {
											"press": "sap.fe.core.fpmExplorer.customAction.CustomAction.alertHeader",
											"visible": "{= ${/EntitiesSingleton/ShowAlertVisible}}",
											"enabled": "{ui>/isEditable}",
											"text": "{i18n>showAlert}"
										},
										"setTravelStatus": {
											"text": "{i18n>setTravelStatus}",
											"press": "sap.fe.core.fpmExplorer.customAction.CustomAction.setTravelStatus"
										},
										"DataFieldForActionGroup::TravelActions": {
											"menu": [
												"DataFieldForAction::TravelService.CopyAction",
												"DataFieldForAction::TravelService.ShareAction",
												"DataFieldForAction::TravelService.CheckStatusAction",
												"setTravelStatus"
											],
											"position": {
												"anchor": "customHeaderActionShowAlert",
												"position": "After"
											}
										}
									}
								},
								"footer": {
									"actions": {
										"customRevertChangesAction": {
											"press": "sap.fe.core.fpmExplorer.customAction.CustomAction.revertChangesAction",
											"visible": "{= !${ui>/isEditable}}",
											"enabled": true,
											"text": "{i18n>customRevertChangesAction}"
										}
									}
								}
							},

							"controlConfiguration": {
								"@com.sap.vocabularies.UI.v1.FieldGroup#TravelData": {
									"actions": {
										"customSectionAction": {
											"press": "sap.fe.core.fpmExplorer.customAction.CustomAction.securedExecution",
											"visible": "{= %{NameProperty} === 'Visible'}",
											"enabled": "{= %{BooleanProperty}}",
											"text": "{i18n>customSectionAction}"
										}
									}
								},
								"to_Booking/@com.sap.vocabularies.UI.v1.LineItem": {
									"actions": {
										"customActionShowTotalPrice": {
											"press": "sap.fe.core.fpmExplorer.customAction.CustomAction.showTotalPrice",
											"text": "{i18n>customShowTotalPrice}",
											"enabled": "{= !${ui>/isEditable}}"
										}
									}
								}
							},
							"navigation": {
								"Booking": {
									"detail": {
										"route": "subObjectPage"
									}
								}
							}
						}
					}
				},
				"subObjectPage": {
					"type": "Component",
					"id": "subObjectPage",
					"name": "sap.fe.templates.ObjectPage",
					"viewLevel": 2,
					"options": {
						"settings": {
							"contextPath": "/Travel/to_Booking"
						}
					}
				}
			}
		}
	}
}
```

**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.js

**LANGUAGE**: JavaScript

**CODE**:
```javascript
module.exports = {
	executeAction: async function (actionDefinition, actionData, keys, odataRequest) {
		console.log("Method is called: " + actionDefinition.name);

		if (actionDefinition.name === "CopyAction") {
			odataRequest.addMessage(0, "Copy action clicked ", 2, "");
		} else if (actionDefinition.name === "ShareAction") {
			odataRequest.addMessage(0, "Share action clicked", 2, "");
		} else if (actionDefinition.name === "CheckStatusAction") {
			odataRequest.addMessage(0, "Check Status action clicked", 2, "");
		}
		return undefined;
	}
};

```

**FILE**: EntitiesSingleton.json

**LANGUAGE**: JSON

**CODE**:
```json
[
	{
		"DoNotChange": 1,
		"ShowAlertVisible": true
	}
]

```

Custom Actions

action visibility
action enablement
hide in edit mode
secured execution


**TITLE**: Custom Header Facet

**INTRODUCTION**: No introduction

**TAGS**: micro chart, column chart, bullet chart, data point, building block micro chart, building block form element

**STEP**: Defining Service Annotations

**DESCRIPTION**: Add the Chart (#MicroChart) and DataPoint annotations to provide the semantic data (measures, criticality, title and subtitle) that you want to visualize in the custom header facet.

**LANGUAGE**: CDS

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

extend entity TravelService.Travel with {
  NumberProperty               : Decimal(6, 2)  @title: 'Number';
  Currency                     : String         @title: 'Currency';
  BooleanProperty              : Boolean        @title: 'Boolean';
  Progress                     : Decimal(4, 1)  @title: 'Progress';
  IntProperty                  : Integer        @title: 'Number';
  StringProperty               : String         @title: 'Value';
  TextProperty                 : String         @title: 'Text';
  TransactionCurrency          : String(5);
  CustomerCreditForecast       : Decimal(23, 2) @title: 'Forecast';
  CustomerCreditExposureAmount : Decimal(23, 2) @title: 'Exposure Amount';
  CustomerCreditLimitAmount    : Decimal(23, 2) @title: 'Limit Amount';
  Criticality                  : Integer;
};

annotate TravelService.Travel with @(UI: {
  Chart #MicroChart                      : {
    $Type            : 'UI.ChartDefinitionType',
    Title            : 'Credit Limit Bullet',
    Description      : 'Bullet MicroChart',
    ChartType        : #Bullet,
    Measures         : [CustomerCreditExposureAmount],
    MeasureAttributes: [{
      $Type    : 'UI.ChartMeasureAttributeType',
      Measure  : CustomerCreditExposureAmount,
      Role     : #Axis1,
      DataPoint: '@UI.DataPoint#CustomerCreditExposureAmount'
    }]
  },
  DataPoint #CustomerCreditExposureAmount: {
    Title        : 'Exposure Amount',
    Value        : CustomerCreditExposureAmount,
    Description  : 'Bullet Micro Chart',
    TargetValue  : CustomerCreditLimitAmount,
    ForecastValue: CustomerCreditForecast,
    MaximumValue : 7000,
    MinimumValue : 200,
    Criticality  : Criticality,
  },
  Facets                                 : [{
    $Type : 'UI.ReferenceFacet',
    ID    : 'TravelData',
    Label : 'Travel Information',
    Target: '@UI.FieldGroup#TravelData',
  }]
});
```

**STEP**: Configuring Header Facets in the Manifest

**DESCRIPTION**: Map the annotated facet to your custom content and reference the display and edit templates using 'template' and 'templateEdit'. Manifest settings refine or override the base annotations (positioning, titles, and the edit/display behavior).

**LANGUAGE**: JSON

**CODE**:
```json
{
	"_version": "1.12.0",
	"sap.app": {
		"id": "sap.fe.core.fpmExplorer.customHeaderFacet",
		"type": "application",
		"i18n": {
			"bundleUrl": "i18n/i18n.properties",
			"supportedLocales": [""],
			"fallbackLocale": ""
		},
		"applicationVersion": {
			"version": "1.0.0"
		},
		"dataSources": {
			"mainService": {
				"uri": "/sap/fe/core/mock/customHeaderFacet/",
				"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
				}
			}
		},
		"rootView": {
			"viewName": "sap.fe.core.fpmExplorer.customHeaderFacet.CustomHeaderFacet"
		},
		"routing": {
			"config": {
				"controlId": "customHeaderFacet"
			},
			"routes": [
				{
					"pattern": "/Travel({key}):?query:",
					"name": "objectPage",
					"target": "objectPage"
				},
				{
					"pattern": "/Travel({key})/to_Booking({key2}):?query:",
					"name": "subObjectPage",
					"target": "subObjectPage"
				}
			],
			"targets": {
				"objectPage": {
					"type": "Component",
					"id": "Default",
					"name": "sap.fe.templates.ObjectPage",
					"viewLevel": 1,
					"options": {
						"settings": {
							"contextPath": "/Travel",
							"content": {
								"header": {
									"facets": {
										"customColumnChart": {
											"template": "sap.fe.core.fpmExplorer.customHeaderFacet.CustomHeaderFacetColumnChart",
											"requestGroupId": "Heroes",
											"stashed": false,
											"visible": "{= ${BooleanProperty}}",
											"position": {
												"placement": "After",
												"anchor": "HeaderFacetIdentifier1"
											},
											"flexSettings": {
												"designtime": "not-adaptable-visibility"
											}
										},
										"customDataPoint": {
											"template": "sap.fe.core.fpmExplorer.customHeaderFacet.CustomHeaderFacetDataPoint",
											"title": "Custom Data Point",
											"subTitle": "Car Rental",
											"requestGroupId": "LongRunners",
											"position": {
												"placement": "After",
												"anchor": "customColumnChart"
											},
											"templateEdit": "sap.fe.core.fpmExplorer.customHeaderFacet.CustomHeaderFacetDataPointEdit"
										}
									}
								}
							},
							"editableHeaderContent": true,
							"controlConfiguration": {
								"to_Booking/@com.sap.vocabularies.UI.v1.LineItem": {
									"actions": {}
								},
								"@com.sap.vocabularies.UI.v1.HeaderFacets": {
									"facets": {
										"customMicroChart": {
											"template": "sap.fe.core.fpmExplorer.customHeaderFacet.CustomHeaderFacetMicroChart",
											"title": "Custom Micro Chart",
											"requestGroupId": "Workers",
											"position": {
												"placement": "After",
												"anchor": "customDataPoint"
											},
											"templateEdit": "sap.fe.core.fpmExplorer.customHeaderFacet.CustomHeaderFacetMicroChartEdit"
										},
										"customBuildingBlockMicroChart": {
											"template": "sap.fe.core.fpmExplorer.customHeaderFacet.CustomHeaderFacetBuildingBlockMicroChart",
											"title": "Custom Building Block Micro Chart",
											"requestGroupId": "Workers",
											"position": {
												"placement": "After",
												"anchor": "customMicroChart"
											},
											"templateEdit": "sap.fe.core.fpmExplorer.customHeaderFacet.CustomHeaderFacetBuildingBlockMicroChartEdit"
										}
									}
								}
							},
							"navigation": {
								"Booking": {
									"detail": {
										"route": "subObjectPage"
									}
								}
							}
						}
					}
				},
				"subObjectPage": {
					"type": "Component",
					"id": "subObjectPage",
					"name": "sap.fe.templates.ObjectPage",
					"viewLevel": 2,
					"options": {
						"settings": {
							"contextPath": "/Travel/to_Booking"
						}
					}
				}
			}
		}
	}
}
```

**STEP**: Providing XML Fragments

**DESCRIPTION**: Implement your XML fragments: one for display mode and one for edit mode. The runtime selects the correct fragment based on the mode that is used.

**LANGUAGE**: XML

**CODE**:
```xml
<core:FragmentDefinition xmlns="sap.m" xmlns:core="sap.ui.core" xmlns:macros="sap.fe.macros">
	<VBox id="CustomBuildingBlockMicroChart" displayInline="true">
		<macros:MicroChart
			id="radialMicroChart"
			metaPath="@com.sap.vocabularies.UI.v1.Chart#MicroChart"
			contextPath="/Travel"
			batchGroupId="$auto.abc"
		/>
	</VBox>
</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**: CustomHeaderFacetBuildingBlockMicroChartEdit.fragment.xml

**LANGUAGE**: XML

**CODE**:
```xml
<core:FragmentDefinition xmlns="sap.m" xmlns:core="sap.ui.core" xmlns:macros="sap.fe.macros">
	<macros:FormElement metaPath="CustomerCreditForecast" id="CustomerCreditForecastID" />
	<macros:FormElement metaPath="CustomerCreditExposureAmount" id="CustomerCreditExposureAmountID" />
	<macros:FormElement metaPath="CustomerCreditLimitAmount" id="CustomerCreditLimitAmountID" />
</core:FragmentDefinition>

```

**FILE**: CustomHeaderFacetColumnChart.fragment.xml

**LANGUAGE**: XML

**CODE**:
```xml
<core:FragmentDefinition xmlns="sap.m" xmlns:core="sap.ui.core" xmlns:mc="sap.suite.ui.microchart">
	<VBox id="CustomHeaderFacetColumnChart" displayInline="true">
		<Link text="Custom Column Chart" target="_blank" href="https://ui5.sap.com/#/api/sap.suite.ui.microchart.ColumnMicroChartData" />
		<mc:ColumnMicroChart size="S" class="sapUiSmallMarginTop sapUiSmallMarginEnd">
			<mc:columns>
				<mc:ColumnMicroChartData value="75" color="Error" />
				<mc:ColumnMicroChartData value="95" color="Error" />
				<mc:ColumnMicroChartData value="100" color="Error" />
				<mc:ColumnMicroChartData value="90" color="Error" />
				<mc:ColumnMicroChartData value="80" color="Error" />
				<mc:ColumnMicroChartData value="35" color="Neutral" />
				<mc:ColumnMicroChartData value="65" color="Neutral" />
				<mc:ColumnMicroChartData value="5" color="Neutral" />
				<mc:ColumnMicroChartData value="15" color="Neutral" />
				<mc:ColumnMicroChartData value="20" color="Neutral" />
			</mc:columns>
		</mc:ColumnMicroChart>
	</VBox>
</core:FragmentDefinition>

```

**FILE**: CustomHeaderFacetDataPoint.fragment.xml

**LANGUAGE**: XML

**CODE**:
```xml
<core:FragmentDefinition xmlns="sap.m" xmlns:core="sap.ui.core">
	<VBox id="CustomHeaderFacetDataPoint" displayInline="true">
		<HBox>
			<core:Icon src="sap-icon://car-rental" color="#e9730c" size="1.8rem" class="sapUiSmallMarginEnd" />
			<ObjectNumber
				state="Warning"
				number="{parts:[{path:'NumberProperty',type:'sap.ui.model.odata.type.Decimal',constraints:{'precision':15,'scale':10}},{path:'Currency',type:'sap.ui.model.odata.type.String',constraints:{'maxLength':5}},{mode:'OneTime',path:'/##@@requestCurrencyCodes',targetType:'any'}],type:'sap.ui.model.odata.type.Currency'}"
			/>
		</HBox>
	</VBox>
</core:FragmentDefinition>

```

**FILE**: CustomHeaderFacetDataPointEdit.fragment.xml

**LANGUAGE**: XML

**CODE**:
```xml
<core:FragmentDefinition xmlns="sap.m" xmlns:core="sap.ui.core" xmlns:f="sap.ui.layout.form" xmlns:macros="sap.fe.macros">
	<f:FormElement label="Net Amount">
		<f:fields>
			<macros:Field id="NumberProperty" metaPath="NumberProperty" />
		</f:fields>
	</f:FormElement>
</core:FragmentDefinition>

```

**FILE**: CustomHeaderFacetMicroChart.fragment.xml

**LANGUAGE**: XML

**CODE**:
```xml
<core:FragmentDefinition xmlns="sap.m" xmlns:core="sap.ui.core" xmlns:mc="sap.suite.ui.microchart">
	<VBox id="CustomHeaderFacetHarveyBall" displayInline="true">
		<mc:HarveyBallMicroChart size="S" total="100" totalScale="%">
			<mc:items>
				<mc:HarveyBallMicroChartItem
					fraction="{= ((100 > 0) ? ((${Progress} > 100) ? 100 : ((${Progress} < 0) ? 0 : (${Progress} / 100 * 100))) : 0) }"
					color="Good"
					fractionScale="%"
				/>
			</mc:items>
		</mc:HarveyBallMicroChart>
	</VBox>
</core:FragmentDefinition>

```

**FILE**: CustomHeaderFacetMicroChartEdit.fragment.xml

**LANGUAGE**: XML

**CODE**:
```xml
<core:FragmentDefinition xmlns="sap.m" xmlns:core="sap.ui.core" xmlns:f="sap.ui.layout.form" xmlns:macros="sap.fe.macros">
	<f:FormElement label="Progress">
		<f:fields>
			<macros:Field id="Progress" metaPath="Progress" />
		</f:fields>
	</f:FormElement>
</core:FragmentDefinition>

```

Custom Header Facet

micro chart
column chart
bullet chart
data point
building block micro chart
building block form element