UI5 Antares is a custom SAPUI5 library consisting of some useful classes and methods, specially designed to speed up development time when working with OData V2 services.
UI5 Antares is written in TypeScript. It is compatible with both SAPUI5 JavaScript and SAPUI5 TypeScript applications.
⚠ This library uses the classes and components of the SAPUI5 framework without modifying or copying the source code, which is licensed under the SAP Developer License. Please read the SAP Developer License carefully and remember that you must comply with the restrictions of the SAP Developer License while using the UI5 Antares library.
Features:
- OData V2 metadata-based dialog and Simple Form - Smart Form generation for CRUD operations
- OData V2 metadata-based object page and Simple Form - Smart Form generation for CRUD operations
- Value Help Dialog generation
- User input validation/mandatory checks
- Request handling for OData V2 CRUD operations
- Promisified OData V2 methods based on the sap.ui.model.odata.v2.ODataModel class
Core Classes
The UI5 Antares library offers a comprehensive set of core classes, as outlined below.
Please refer to the Planned Features section to learn about the features that will be included in the next releases.
- Node.js
- NPM
- UI5 Tooling (global or local)
To make sure they are available on your machine, try running the following command.
npm -v && node -v
10.5.1
v20.11.0
Locally installed UI5 Tooling:
npx ui5 -v
3.9.2
Globally installed UI5 Tooling:
ui5 -v
3.9.2
-
UI5 Antares
- BEFORE YOU CONTINUE
- Features GIF
- Prerequisites
- Table of Contents
- Versioning
- Installation
- Local Start
-
Entry Create
- Use Case
- Constructor
- Create New Entry
- Manual Submit
- Label Generation
- Resource Bundle Prefix
- Naming Strategy
- Form Type
- Form Title
- Form Grouping
- Begin Button Text
- Begin Button Type
- End Button Text
- End Button Type
- Properties with Edm.Guid Type
- Form Property Order
- Excluded Properties
- Mandatory Properties
- Readonly Properties
- Attach Submit Completed
- Attach Submit Failed
- Response Class
- Value Help
- Validation Logic
- Object Page
- Custom Control
- Custom Content
- Custom Fragment
- Entry Update
- Entry Delete
- Entry Read
- Promisified OData V2 Classes
- Fragment Class
- Planned Features
- Change Log
- License
UI5 Antares and SAPUI5 versions are directly related. The SAPUI5 version used can be determined by ignoring the last 3 digits of the UI5 Antares version. The last 3 digits of the UI5 Antares version increase sequentially after bug fixes or new features.
You should install the version that corresponds to the version of your SAPUI5/Fiori Elements application.
IMPORTANT: When the patch part of the SAPUI5 version is 0, the UI5 Antares patch part begins with 999 because the NPM does not permit leading zeros in the version parts. For instance, if the SAPUI5 version is 1.124.0, the UI5 Antares version will be 1.124.999001. The last three digits will increase with each bug fix or new feature.
You can see examples of versioning below.
Note: The versions shown in the example below may not exist.
UI5 Antares Version | SAPUI5 Version | Description |
---|---|---|
1.123.1002 | 1.123.1 | Latest Version for 1.123.1 |
1.123.1001 | 1.123.1 | One before the latest version for 1.123.1 |
1.96.32001 | 1.96.32 | Latest Version for 1.96.32 |
1.84.999001 | 1.84.0 | Latest Version for 1.84.0 |
The table below shows the currently supported and planned SAPUI5 versions. UI5 Antares has initially been released to support version 1.123.1. However, development will also be done for versions with long-term maintenance as specified at SAPUI5 Version Overview.
UI5 Antares Version | SAPUI5 Version | Status |
---|---|---|
1.124.1002 | 1.124.1 | Available |
1.124.999002 | 1.124.0 | Available |
1.123.2002 | 1.123.2 | Available |
1.123.1003 | 1.123.1 | Available |
1.120.15002 | 1.120.15 | Available |
1.120.14002 | 1.120.14 | Available |
1.120.13002 | 1.120.13 | Available |
1.120.12002 | 1.120.12 | Available |
1.120.11002 | 1.120.11 | Available |
1.120.1003 | 1.120.1 | Available |
1.108.32002 | 1.108.32 | Available |
1.108.31002 | 1.108.31 | Available |
1.108.30002 | 1.108.30 | Available |
1.108.23002 | 1.108.23 | Available |
1.96.33002 | 1.96.33 | Available |
1.96.32002 | 1.96.32 | Available |
1.96.31002 | 1.96.31 | Available |
1.96.30002 | 1.96.30 | Available |
1.96.25003 | 1.96.25 | Available |
1.120.* | 1.120.* | Planned |
1.108.* | 1.108.* | Planned |
1.96.* | > 1.96.25 | Planned |
If the versioning is confusing, you can use a special tag when installing the package. The most recent version of UI5 Antares that corresponds to a specific SAPUI5 version will always include a tag as follows.
Tag Naming Convention: ui5-${1}-${2}-${3}-latest
- ${1} = Major part of the SAPUI5 version
- ${2} = Minor part of the SAPUI5 version
- ${3} = Patch part of the SAPUI5 version
As an example, if your SAPUI5 application is version 1.124.0, you can utilize the following command.
npm install --save-exact ui5-antares@ui5-1-124-0-latest
Hint: The
--save-exact
argument prevents the addition of a caret or tilda in front of the version in the package.json file.
BEFORE YOU INSTALL: please read the prerequisites and versioning.
To install the library, run the following command in the directory where the package.json file of your SAPUI5/Fiori Elements application is located. It is usually located in the root directory of a SAPUI5/Fiori Elements application.
Note: In the command below, replace
version
with the UI5 Antares version that corresponds to the version of your SAPUI5/Fiori Elements application. For example, applications running with SAPUI5 version 1.123.1 should run the following command: npm install ui5-antares@1.123.1001
Note: If you are using UI5 Tooling v3, you don't need to add ui5-antares to the
ui5.dependencies
in your application's package.json file.
npm install ui5-antares@version
Add "ui5.antares": {}
to the "sap.ui5"."dependencies"."libs"
section of your application's manifest.json file.
{
...
"sap.ui5": {
...
"dependencies": {
...
"libs": {
"sap.m": {},
"sap.ui.core": {},
...
"ui5.antares": {}
}
}
}
}
Add "ui5.antares": "./resources/ui5/antares"
to the "sap.ui5"."resourceRoots"
section of your application's manifest.json file.
{
...
"sap.ui5": {
...
"resourceRoots": {
"ui5.antares": "./resources/ui5/antares"
}
}
}
Add the --all
argument to the build
script in your application's package.json file. This argument ensures that all dependencies are included when the application is built.
{
...
"scripts": {
"build": "ui5 build --all --config=ui5.yaml --clean-dest --dest dist"
}
}
You can make sure that UI5 Antares is a dependency of your application by using the following command.
Locally installed UI5 Tooling:
npx ui5 tree
Globally installed UI5 Tooling:
ui5 tree
If you are developing your SAPUI5/Fiori Elements application with TypeScript, you need to add "./node_modules/ui5-antares" to the compilerOptions.typeRoots
array in your application's tsconfig.json file. This configuration is required to use UI5 Antares type declarations.
{
"compilerOptions": {
"typeRoots": [
...
"./node_modules/ui5-antares"
]
}
}
If you are deploying your application with a Standalone or Managed Approuter, you must add the route below (first route) to your application's xs-app.json file.
Note: Standalone Approuter also has a xs-app.json file, but this configuration should be done on the SAPUI5/Fiori Elements application's xs-app.json file not on the Standalone Approuter's xs-app.json file.
This route must be added before the route (automatically added by the application generator) with "source": "^/resources/(.*)$" and "destination": "ui5" to load the UI5 Antares from the HTML5 Application Repository instead of the UI5 CDN.
The reason for this configuration is that both standard UI5 libraries and UI5 Antares use the /resources path to load the files.
{
"welcomeFile": "/index.html",
"authenticationMethod": "route",
"routes": [
...
{
"source": "^/resources/ui5/antares/(.*)$",
"target": "/resources/ui5/antares/$1",
"service": "html5-apps-repo-rt",
"authenticationType": "xsuaa"
},
{
"source": "^/resources/(.*)$",
"target": "/resources/$1",
"authenticationType": "none",
"destination": "ui5"
},
{
"source": "^/test-resources/(.*)$",
"target": "/test-resources/$1",
"authenticationType": "none",
"destination": "ui5"
},
{
"source": "^(.*)$",
"target": "$1",
"service": "html5-apps-repo-rt",
"authenticationType": "xsuaa"
}
]
}
If you start your application with one of the following commands, UI5 Antares will be loaded automatically, since it's a dependency of your application.
ui5 serve
fiori run
If you load the standard UI5 library on the /resources path using the fiori-tools-proxy
middleware of the @sap/ux-ui5-tooling package while starting your application as below, UI5 Antares will not be loaded because it also uses the /resources path.
fiori-tools-proxy
redirects all requests coming from the /resources path to the url defined in the configuration.ui5.url
property.
Remove the ui5
configuration from the YAML file that is used as the configuration file for the start script (--config
argument of ui5 serve or fiori run command).
Modify the src
attribute of the sap-ui-bootstrap
script in your application's index.html file and load the standard UI5 library from the CDN.
Note: If you deploy your application to an ABAP repository, don't forget to change the
src
attribute to "resources/sap-ui-core.js" because the server may not have internet access. With this change, the standard UI5 library will be loaded directly from the server instead of from the CDN.
Don't use the /resources path in the ui5
configuration of fiori-tools-proxy
on the YAML file that is used as the start script configuration file (--config
argument of ui5 serve or fiori run command).
Modify the src
attribute of the sap-ui-bootstrap
script in your application's index.html file and load the standard UI5 library from the path which is defined in the YAML file.
Note: Do not forget to change the
src
attribute back to "resources/sap-ui-core.js" or "https://sapui5.hana.ondemand.com/resources/sap-ui-core.js" before deploying your application.
Entry Create (EntryCreateCL) is a class that manages the CREATE (POST) operation through the OData V2 model. It basically avoids developers having to deal with fragments, user input validations, Value Help creations while working on custom SAPUI5 applications or Fiori Elements extensions. Below you can see the features that Entry Create has.
Features:
- sap.m.Dialog generation with a SmartForm, SimpleForm or Custom content
- sap.uxap.ObjectPageLayout generation with a SmartForm, SimpleForm or Custom Content
- User input validation via ValidationLogicCL class
- Value Help Dialog generation via ValueHelpCL class
- Property sorting, readonly properties, UUID generation for the properties with Edm.Guid type
- Label generation for the SmartForm, SimpleForm elements
- createEntry(), submitChanges(), and resetChanges() handling based on the user interaction
- Call a fragment and bind the context in case you do not want to use the auto-generated dialog
Let's say that you have an EntitySet named Products
and you want to let the end user to create an entity on a pop-up screen using the OData V2 service in your custom SAPUI5 application. Here are the steps you need to follow.
- You need to create a .fragment.xml file that contains a Dialog with a form content (Simple, Smart etc.) and call it from the controller or generate the dialog directly on the controller
- You have to write tons of Value Help code if you don't use sap.ui.comp.smartfield.SmartField with the OData Annotations
- You need to validate the user input, such as checking mandatory fields and ensuring that the values entered match your business logic
- You need to create a transient entity (createEntry) and either submit it or reset it based on the user interaction
EntryCreateCL class basically handles all of the steps defined above.
You must initialize an object from EntryCreateCL in order to use it.
Parameter | Type | Mandatory | Default Value | Description |
---|---|---|---|---|
controller | sap.ui.core.mvc.Controller | Yes | The controller object (usually this ) |
|
entityPath | string | Yes | The name of the EntitySet. It can start with a "/" | |
modelName? | string | No | undefined | The name of the OData V2 model which can be found on the manifest.json file. Do not specify if the model name = "" |
TypeScript
EntryCreateCL<EntityT> is a generic class and can be initialized with a type that contains the properties of the EntitySet that is used as a parameter on the class constructor. EntityT
is used as the type of the data?
parameter of the createNewEntry(data?: EntityT) method.
Also, it is used as the returning type of the getResponse(): EntityT method of the ResponseCL
class whose object is passed as a parameter into the function attached by the attachSubmitCompleted(submitCompleted: (response: ResponseCL) => void, listener?: object) method.
import Controller from "sap/ui/core/mvc/Controller";
import EntryCreateCL from "ui5/antares/entry/v2/EntryCreateCL"; // Import the class
/**
* @namespace your.apps.namespace
*/
export default class YourController extends Controller {
public onInit() {
}
public async onCreateProduct() {
// Initialize without a type
const entry = new EntryCreateCL(this, "Products");
}
public async onCreateCategory() {
// Initialize with a type
const entry = new EntryCreateCL<ICategory>(this, "Categories");
}
public async onCreateCustomer() {
// Initialize with a model name
const entry = new EntryCreateCL(this, "Customers", "myODataModelName");
}
}
interface ICategory {
ID: string;
name?: string;
}
JavaScript
sap.ui.define([
"sap/ui/core/mvc/Controller",
"ui5/antares/entry/v2/EntryCreateCL" // Import the class
],
/**
* @param {typeof sap.ui.core.mvc.Controller} Controller
*/
function (Controller, EntryCreateCL) {
"use strict";
return Controller.extend("your.apps.namespace.YourController", {
onInit: function () {
},
onCreateProduct: async function () {
// Initialize
const entry = new EntryCreateCL(this, "Products");
},
onCreateCategory: async function () {
// Initialize with a model name
const entry = new EntryCreateCL(this, "Categories", "myODataModelName");
}
});
});
createNewEntry(data?: EntityT) method creates an entry for the EntitySet
which is specified through the class constructor and binds it to the dialog that is automatically generated or loaded from the fragment that is placed in the application files. createEntry() method is used to create an entry. The generated/loaded dialog is opened after the entry is created.
By default, createNewEntry() method uses the ODataMetaModel to determine the EntityType
of the EntitySet
that was set by the constructor and brings all the properties in the same order as the OData metadata into the generated form.
All key properties are marked as mandatory/required and the labels are generated assuming that the naming convention of the EntityType
is camelCase. Please see Label Generation
Important: Please be advised that the createNewEntry() method must be called after any configurations have been made through the public method of the Entry Create class. Any configurations (form title, mandatory properties, etc.) made after the createNewEntry() method will not be reflected. Basically, createNewEntry() method should be called at the end of your code block.
By default, random UUID value is generated for the key properties with Edm.Guid type and these fields are not visible on the generated form. However, this behaviour can be modified using the setGenerateRandomGuid() and setDisplayGuidProperties() methods.
Parameter | Type | Mandatory | Default Value | Description |
---|---|---|---|---|
data? | EntityT or object | No | undefined | The initial values of the entry |
Returns | Description |
---|---|
Promise<void> | After the promise is resolved, the created entry can be retrieved by the getEntryContext() method using the object instantiated from the EntryCreateCL class |
createNewEntry() method uses the default configurations when creating the dialog. However, these configurations can be modified using the public setter methods.
Term | Default Value | Description | Setter | Getter |
---|---|---|---|---|
Naming Strategy | NamingStrategies.CAMEL_CASE | The default naming strategy is CAMEL_CASE | setNamingStrategy() | getNamingStrategy() |
Resource Bundle Prefix | antares | The default resource bundle prefix is antares | setResourceBundlePrefix() | getResourceBundlePrefix() |
Use Metadata Labels | false | The labels are not taken from the metadata but generated | setUseMetadataLabels() | getUseMetadataLabels() |
Form Type | FormTypes.SMART | SmartForm with SmartFields is generated by default | setFormType() | getFormType() |
Form Title | Create New + ${entityPath} | entityPath from the constructor is used | setFormTitle() | getFormTitle() |
Begin Button Text | Create | The default begin button text is Create | setBeginButtonText() | getBeginButtonText() |
Begin Button Type | ButtonType.Success | The default button type is Success | setBeginButtonType() | getBeginButtonType() |
End Button Text | Close | The default end button text is Close | setEndButtonText() | getEndButtonText() |
End Button Type | ButtonType.Negative | The default button type is Negative | setEndButtonType() | getEndButtonType() |
Mandatory Error Message | Please fill in all required fields. | The displayed message when the mandatory check fails | setMandatoryErrorMessage() | getMandatoryErrorMessage() |
TypeScript
import Controller from "sap/ui/core/mvc/Controller";
import EntryCreateCL from "ui5/antares/entry/v2/EntryCreateCL"; // Import the class
/**
* @namespace your.apps.namespace
*/
export default class YourController extends Controller {
public onInit() {
}
public async onCreateProduct() {
// Initialize without a type
const entry = new EntryCreateCL(this, "Products");
// Call without the initial values
entry.createNewEntry();
}
public async onCreateCategory() {
// Initialize with a type
const entry = new EntryCreateCL<ICategory>(this, "Categories");
// Call with the initial values
entry.createNewEntry({
ID: "ELEC",
name: "Electronics"
});
}
}
interface ICategory {
ID: string;
name?: string;
}
JavaScript
sap.ui.define([
"sap/ui/core/mvc/Controller",
"ui5/antares/entry/v2/EntryCreateCL" // Import the class
],
/**
* @param {typeof sap.ui.core.mvc.Controller} Controller
*/
function (Controller, EntryCreateCL) {
"use strict";
return Controller.extend("your.apps.namespace.YourController", {
onInit: function () {
},
onCreateProduct: async function () {
// Initialize
const entry = new EntryCreateCL(this, "Products");
// Call without the initial values
entry.createNewEntry();
},
onCreateCategory: async function () {
// Initialize
const entry = new EntryCreateCL(this, "Categories");
// Call with the initial values
entry.createNewEntry({
ID: "ELEC",
name: "Electronics"
});
}
});
});
The generated form with default values will more or less look like the following. It will vary depending on the configurations and the EntityType
properties of the EntitySet
.
By default, any changes that are made by the end user on the auto-generated form are automatically submitted by the Entry Create and Entry Update classes when the end user presses on the begin button. However, there may be a requirement to run some codes before submitting the changes through the OData V2 model.
It is possible to register a function that will be called instead of running the automatic submit mechanism when the end user presses the begin button.
Important: Please be advised that the manual submit feature is only available for the Entry Create and Entry Update classes.
Important: It is not possible to use this feature with the Object Page feature.
To register a function, registerManualSubmit() method can be utilized. The registered function will be called when the end user presses the begin button and an object constructed from the Entry Create or Entry Update class will be passed as a parameter to the function.
To complete the process after running your own code in the registered function, please call the submitManually() method using the object passed as a parameter to the function.
Additionally, the auto-generated dialog (sap.m.Dialog) can be obtained by calling the getGeneratedDialog() method with the object passed as a parameter to the function.
Setter (registerManualSubmit)
Parameter | Type | Mandatory | Description |
---|---|---|---|
submitter | (entry: EntryCreateCL<EntityT> | EntryUpdateCL<EntityT>) => void | Yes | The function that will be called when the user presses the begin button |
Returns | Description |
---|---|
void |
Getter (getGeneratedDialog)
Returns | Description |
---|---|
sap.m.Dialog | Returns the auto-generated dialog |
Sample
Let us consider an EntitySet
named Products and we wish to run some codes before submitting the changes through the OData V2 model.
TypeScript
import Controller from "sap/ui/core/mvc/Controller";
import EntryCreateCL from "ui5/antares/entry/v2/EntryCreateCL"; // Import the class
import EntryUpdateCL from "ui5/antares/entry/v2/EntryUpdateCL"; // Import the class
/**
* @namespace your.apps.namespace
*/
export default class YourController extends Controller {
public onInit() {
}
public onCreateProduct() {
// initialize
const entry = new EntryCreateCL<IProducts>(this, "Products");
// register the submitter function
entry.registerManualSubmit(this.createProductManually, this);
// call the dialog
entry.createNewEntry();
}
// use the same generic type with the constructor in onCreateProduct method
private async createProductManually(entry: EntryCreateCL<IProducts>) {
// obtain the generated dialog
const dialog = entry.getGeneratedDialog();
dialog.getContent().forEach((content) => {
// here you can access each element of the dialog
});
// run your own code (can also be async)
// do not forget to complete the submit process
entry.submitManually();
}
public async onUpdateProduct() {
// Initialize with a type and use the table id as the initializer
const entry = new EntryUpdateCL<IProducts, IProductKeys>(this, {
entityPath: "Products",
initializer: "tblProducts" // table id
});
// register the submitter function
entry.registerManualSubmit(this.updateProductManually, this);
// call the dialog
entry.updateEntry();
}
// use the same generic type with the constructor in onUpdateProduct method
private async updateProductManually(entry: EntryUpdateCL<IProducts>) {
// obtain the generated dialog
const dialog = entry.getGeneratedDialog();
dialog.getContent().forEach((content) => {
// here you can access each element of the dialog
});
// run your own code (can also be async)
// do not forget to complete the submit process
entry.submitManually();
}
}
interface IProducts {
ID: string;
name: string;
description: string;
brand: string;
price: number;
currency: string;
quantityInStock: number;
categoryID: string;
supplierID: string;
}
interface IProductKeys {
ID: string;
}
JavaScript
sap.ui.define([
"sap/ui/core/mvc/Controller",
"ui5/antares/entry/v2/EntryCreateCL", // Import the class
"ui5/antares/entry/v2/EntryUpdateCL" // Import the class
],
/**
* @param {typeof sap.ui.core.mvc.Controller} Controller
*/
function (Controller, EntryCreateCL, EntryUpdateCL) {
"use strict";
return Controller.extend("your.apps.namespace.YourController", {
onInit: function () {
},
onCreateProduct: async function () {
// initialize
const entry = new EntryCreateCL(this, "Products");
// register the submitter function
entry.registerManualSubmit(this._createProductManually, this);
// call the dialog
entry.createNewEntry();
},
_createProductManually: async function (entry) {
// obtain the generated dialog
const dialog = entry.getGeneratedDialog();
dialog.getContent().forEach((content) => {
// here you can access each element of the dialog
});
// run your own code (can also be async)
// do not forget to complete the submit process
entry.submitManually();
},
onUpdateProduct: async function () {
// Initialize and use the table id as the initializer
const entry = new EntryUpdateCL(this, {
entityPath: "Products",
initializer: "tblProducts" // table id
});
// register the submitter function
entry.registerManualSubmit(this._updateProductManually, this);
// call the dialog
entry.updateEntry();
},
_updateProductManually: async function (entry) {
// obtain the generated dialog
const dialog = entry.getGeneratedDialog();
dialog.getContent().forEach((content) => {
// here you can access each element of the dialog
});
// run your own code (can also be async)
// do not forget to complete the submit process
entry.submitManually();
}
});
});
By default, the Entry Create class generates labels for form elements within the auto-generated SmartForm/SimpleForm. Here are the steps that will be followed during the creation of the labels.
The Resource Model has first priority if the metadata labels are not used when creating the labels.
If the application has a Resource Model named i18n
in the application's manifest.json file, the Entry Create class looks for the texts for each property of the EntityType
by assuming that the key of the i18n text is written in the format below.
Default format of the i18n keys: antares + entityPath + propertyName
Here antares
is a default prefix and can be modified using the setResourceBundlePrefix() method. entityPath
comes from the class constructor and the propertyName
is the technical name of an EntityType
property in the OData V2 metadata.
manifest.json:
{
"_version": "1.59.0",
"sap.app": {
...
"i18n": "path/to/i18n.properties"
},
...
"sap.ui5": {
...
"models": {
"i18n": {
"type": "sap.ui.model.resource.ResourceModel",
"settings": {
"bundleName": "your.apps.namespace.i18n.i18n"
}
}
}
}
}
Sample
Let's say that you have an EntitySet
named Products and its EntityType
has the properties shown in the metadata below. Your application's i18n.properties
file will be checked for the following keys.
i18n.properties
antaresProductsID=Label of the ID property
antaresProductsname=Label of the name property
antaresProductsdescription=Label of the description property
...
<?xml version="1.0" encoding="utf-8"?>
<edmx:Edmx Version="1.0" xmlns:edmx="http://schemas.microsoft.com/ado/2007/06/edmx" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata">
<edmx:DataServices m:DataServiceVersion="2.0">
<Schema Namespace="OnlineShopping" xmlns="http://schemas.microsoft.com/ado/2008/09/edm">
<EntityContainer Name="EntityContainer" m:IsDefaultEntityContainer="true">
<EntitySet Name="Products" EntityType="OnlineShopping.Product"/>
</EntityContainer>
<EntityType Name="Product">
<Key>
<PropertyRef Name="ID"/>
</Key>
<Property Name="ID" Type="Edm.Guid" Nullable="false"/>
<Property Name="name" Type="Edm.String" MaxLength="50"/>
<Property Name="description" Type="Edm.String" MaxLength="255"/>
<Property Name="brand" Type="Edm.String" MaxLength="50"/>
<Property Name="price" Type="Edm.Decimal" Precision="13" Scale="2" Nullable="false"/>
<Property Name="currency" Type="Edm.String" MaxLength="5" Nullable="false"/>
<Property Name="quantityInStock" Type="Edm.Int32"/>
<Property Name="categoryID" Type="Edm.Guid" Nullable="false"/>
<Property Name="supplierID" Type="Edm.Guid" Nullable="false"/>
</EntityType>
</Schema>
</edmx:DataServices>
</edmx:Edmx>
If the Resource Model does not exist or the text cannot be found in the
i18n.properties
file, the Label Generation From The Technical Names takes place.
If no label could be generated from the Resource Model, the Entry Create class tries to split the technical property names of the Entity Type
into human-readable words.
By default, it's assumed that the naming convention for the EntityType
properties is camelCase. However, if you have used a different naming convention when creating the EntityType
properties, setNamingStrategy() can be used to change the default naming convention.
Sample
Here are some samples of how property names are broken down into human-readable words in different naming strategies.
camelCase
Technical Name | Generated Label |
---|---|
productID | Product ID |
firstName | First Name |
lastName | Last Name |
PascalCase
Uid, Id and Url words are accepted as special words and converted to upper case after splitting.
Technical Name | Generated Label |
---|---|
ProductId | Product ID |
FirstName | First Name |
LastName | Last Name |
kebab-case
Technical Name | Generated Label |
---|---|
product-id | Product Id |
first-name | First Name |
last-name | Last Name |
CONSTANT_CASE
Technical Name | Generated Label |
---|---|
PRODUCT_ID | Product Id |
FIRST_NAME | First Name |
LAST_NAME | Last Name |
snake_case
Technical Name | Generated Label |
---|---|
product_id | Product Id |
first_name | First Name |
last_name | Last Name |
If you have com.sap.vocabularies.Common.v1.Label annotation or sap:label extension for your EntityType
properties in the OData V2 metadata, you can use them as labels for the auto-generated form elements.
If you set the value to true using the setter method and the labels could not be found in the metadata, Entry Create class generates the labels as described in Label Generation.
Setter (setUseMetadataLabels)
Parameter | Type | Mandatory | Description |
---|---|---|---|
useMetadataLabels | boolean | Yes | If the value is true, OData V2 metadata labels will be used when creating labels for auto-generated form elements |
Returns | Description |
---|---|
void |
Getter (getUseMetadataLabels)
Returns | Description |
---|---|
boolean | Returns the value that was set using setUseMetadataLabels() method. Default value is false |
TypeScript
import Controller from "sap/ui/core/mvc/Controller";
import EntryCreateCL from "ui5/antares/entry/v2/EntryCreateCL"; // Import the class
/**
* @namespace your.apps.namespace
*/
export default class YourController extends Controller {
public onInit() {
}
public async onCreateProduct() {
const entry = new EntryCreateCL(this, "Products");
// The OData V2 metadata labels will be used for the form elements.
entry.setUseMetadataLabels(true);
entry.createNewEntry();
}
}
JavaScript
sap.ui.define([
"sap/ui/core/mvc/Controller",
"ui5/antares/entry/v2/EntryCreateCL" // Import the class
],
/**
* @param {typeof sap.ui.core.mvc.Controller} Controller
*/
function (Controller, EntryCreateCL) {
"use strict";
return Controller.extend("your.apps.namespace.YourController", {
onInit: function () {
},
onCreateProduct: async function () {
const entry = new EntryCreateCL(this, "Products");
// The OData V2 metadata labels will be used for the form elements.
entry.setUseMetadataLabels(true);
entry.createNewEntry();
}
});
});
To change the default resource bundle prefix that is used in the text lookup described in Resource Model (i18n), setResourceBundlePrefix() method can be used.
If you don't want to have any prefix, you should pass
""
as a parameter to the setResourceBundlePrefix() method.
Setter (setResourceBundlePrefix)
Parameter | Type | Mandatory | Description |
---|---|---|---|
prefix | string | Yes | The prefix that is used for text lookup in the i18n file of the application |
Returns | Description |
---|---|
void |
Getter (getResourceBundlePrefix)
Returns | Description |
---|---|
string | Returns the value that was set using setResourceBundlePrefix() method. Default value is antares |
Sample
Let's say you have an EntitySet
named Products with the properties productID
, productName
, and you set the resource bundle prefix to myPrefix
, Entry Create class will look for the following texts in the application's i18n file.
myPrefixProductsproductID=Label of the productID property
myPrefixProductsproductName=Label of the productName property
TypeScript
import Controller from "sap/ui/core/mvc/Controller";
import EntryCreateCL from "ui5/antares/entry/v2/EntryCreateCL"; // Import the class
/**
* @namespace your.apps.namespace
*/
export default class YourController extends Controller {
public onInit() {
}
public async onCreateProduct() {
const entry = new EntryCreateCL(this, "Products");
// New i18n text lookup format will be => myPrefix + entityPath + propertyName
entry.setResourceBundlePrefix("myPrefix");
entry.createNewEntry();
}
public async onCreateCategory() {
const entry = new EntryCreateCL(this, "Categories");
// New i18n text lookup format will be => entityPath + propertyName
entry.setResourceBundlePrefix("");
entry.createNewEntry();
}
}
JavaScript
sap.ui.define([
"sap/ui/core/mvc/Controller",
"ui5/antares/entry/v2/EntryCreateCL" // Import the class
],
/**
* @param {typeof sap.ui.core.mvc.Controller} Controller
*/
function (Controller, EntryCreateCL) {
"use strict";
return Controller.extend("your.apps.namespace.YourController", {
onInit: function () {
},
onCreateProduct: async function () {
const entry = new EntryCreateCL(this, "Products");
// New i18n text lookup format will be => myPrefix + entityPath + propertyName
entry.setResourceBundlePrefix("myPrefix");
entry.createNewEntry();
},
onCreateCategory: async function () {
const entry = new EntryCreateCL(this, "Categories");
// New i18n text lookup format will be => entityPath + propertyName
entry.setResourceBundlePrefix("");
entry.createNewEntry();
}
});
});
To change the default naming strategy that is used in the label generation as described in Label Generation From The Technical Names, setNamingStrategy() method can be used.
Setter (setNamingStrategy)
Parameter | Type | Mandatory | Description |
---|---|---|---|
strategy | NamingStrategies | Yes | The naming strategy that is used for label generation |
Returns | Description |
---|---|
void |
Getter (getNamingStrategy)
Returns | Description |
---|---|
NamingStrategies | Returns the value that was set using setNamingStrategy() method. Default value is CAMEL_CASE |
Sample
Let's say you have an EntitySet
named Products with the properties product_id
, product_name
, and you don't want to use the labels from the metadata or the i18n file, but you want the library to generate the labels. To do this, you can set the naming strategy as follows.
TypeScript
import Controller from "sap/ui/core/mvc/Controller";
import EntryCreateCL from "ui5/antares/entry/v2/EntryCreateCL"; // Import the class
import { NamingStrategies } from "ui5/antares/types/entry/enums"; // Import the enum
/**
* @namespace your.apps.namespace
*/
export default class YourController extends Controller {
public onInit() {
}
public async onCreateProduct() {
const entry = new EntryCreateCL(this, "Products");
// Set the naming strategy to snake_case
entry.setNamingStrategy(NamingStrategies.SNAKE_CASE);
entry.createNewEntry();
}
}
JavaScript
sap.ui.define([
"sap/ui/core/mvc/Controller",
"ui5/antares/entry/v2/EntryCreateCL", // Import the class
"ui5/antares/types/entry/enums" // Import the enums
],
/**
* @param {typeof sap.ui.core.mvc.Controller} Controller
*/
function (Controller, EntryCreateCL, EntryEnums) {
"use strict";
// Destructure the object to retrieve the NamingStrategies enum
const { NamingStrategies } = EntryEnums;
return Controller.extend("your.apps.namespace.YourController", {
onInit: function () {
},
onCreateProduct: async function () {
const entry = new EntryCreateCL(this, "Products");
// Set the naming strategy to snake_case
entry.setNamingStrategy(NamingStrategies.SNAKE_CASE);
entry.createNewEntry();
}
});
});
Name | Description |
---|---|
NamingStrategies.CAMEL_CASE |
EntityType properties use camelCase naming convention |
NamingStrategies.PASCAL_CASE |
EntityType properties use PascalCase naming convention |
NamingStrategies.KEBAB_CASE |
EntityType properties use kebab-case naming convention |
NamingStrategies.CONSTANT_CASE |
EntityType properties use CONSTANT_CASE naming convention |
NamingStrategies.SNAKE_CASE |
EntityType properties use snake_case naming convention |
By default, a sap.ui.comp.smartform.SmartForm with sap.ui.comp.smartfield.SmartField content is created when the createNewEntry() method is called. This form type already has some advantages.
- The form fields are rendered as Input, DatePicker, DateTimePicker, ComboBox, CheckBox, etc. based on the EDM type of the
EntityType
property. - Value Help is automatically added to the Smart Fields, when the
EntityType
property is annotated with com.sap.vocabularies.Common.v1.ValueList
However, UI5 Antares can also create a sap.ui.layout.form.SimpleForm with sap.m.Input, sap.m.DatePicker, sap.m.DateTimePicker, and sap.m.CheckBox content based on the EDM types.
Important: The Value Help feature is only available when the form type is set to SIMPLE.
Rendered Controls for SIMPLE Form Type
EDM Type | Control | Description |
---|---|---|
Boolean | sap.m.CheckBox | |
DateTime | sap.m.DatePicker or sap.m.DateTimePicker | If the property has sap:display-format="Date" has extension, it is rendered as sap.m.DatePicker, otherwise as sap.m.DateTimePicker |
DateTimeOffset | sap.m.DateTimePicker | |
Others | sap.m.Input | If the EDM type of the property is Edm.Decimal, precision and scale constraints are added into the input |
To change the default form type, setFormType() method can be used.
Setter (setFormType)
Parameter | Type | Mandatory | Description |
---|---|---|---|
formType | FormTypes | Yes | The form type that is generated |
Returns | Description |
---|---|
void |
Getter (getFormType)
Returns | Description |
---|---|
FormTypes | Returns the value that was set using setFormType() method. Default value is SMART |
Sample
Let's say you have an EntitySet
named Products , and you want to have a simple form on the dialog that is created. To do this, you can set the form type as follows.
TypeScript
import Controller from "sap/ui/core/mvc/Controller";
import EntryCreateCL from "ui5/antares/entry/v2/EntryCreateCL"; // Import the class
import { FormTypes } from "ui5/antares/types/entry/enums"; // Import the enum
/**
* @namespace your.apps.namespace
*/
export default class YourController extends Controller {
public onInit() {
}
public async onCreateProduct() {
const entry = new EntryCreateCL(this, "Products");
// Set the form type to SIMPLE
entry.setFormType(FormTypes.SIMPLE);
entry.createNewEntry();
}
}
JavaScript
sap.ui.define([
"sap/ui/core/mvc/Controller",
"ui5/antares/entry/v2/EntryCreateCL", // Import the class
"ui5/antares/types/entry/enums" // Import the enums
],
/**
* @param {typeof sap.ui.core.mvc.Controller} Controller
*/
function (Controller, EntryCreateCL, EntryEnums) {
"use strict";
// Destructure the object to retrieve the FormTypes enum
const { FormTypes } = EntryEnums;
return Controller.extend("your.apps.namespace.YourController", {
onInit: function () {
},
onCreateProduct: async function () {
const entry = new EntryCreateCL(this, "Products");
// Set the form type to SIMPLE
entry.setFormType(FormTypes.SIMPLE);
entry.createNewEntry();
}
});
});
Name | Description |
---|---|
FormTypes.SMART | SmartForm with SmartField content is generated |
FormTypes.SIMPLE | SimpleForm with Input, DatePicker, DateTimePicker, CheckBox content is generated |
By default, the generated form's title is a combination of the words Create New and the entityPath
defined in the constructor. For instance, if the entityPath
is set to Products, the title will be Create New Products.
To modify the default form title, please utilize the setFormTitle() method.
Setter (setFormTitle)
Parameter | Type | Mandatory | Description |
---|---|---|---|
title | string | Yes | The generated form's title |
Returns | Description |
---|---|
void |
Getter (getFormTitle)
Returns | Description |
---|---|
string | Returns the value that was set using setFormTitle() method. Default value is Create new ${entityPath} |
Sample
Please find the result below after the code blocks.
TypeScript
import Controller from "sap/ui/core/mvc/Controller";
import EntryCreateCL from "ui5/antares/entry/v2/EntryCreateCL"; // Import the class
/**
* @namespace your.apps.namespace
*/
export default class YourController extends Controller {
public onInit() {
}
public async onCreateProduct() {
const entry = new EntryCreateCL(this, "Products");
// Set the form title
entry.setFormTitle("My Form Title");
entry.createNewEntry();
}
}
JavaScript
sap.ui.define([
"sap/ui/core/mvc/Controller",
"ui5/antares/entry/v2/EntryCreateCL" // Import the class
],
/**
* @param {typeof sap.ui.core.mvc.Controller} Controller
*/
function (Controller, EntryCreateCL) {
"use strict";
return Controller.extend("your.apps.namespace.YourController", {
onInit: function () {
},
onCreateProduct: async function () {
const entry = new EntryCreateCL(this, "Products");
// Set the form title
entry.setFormTitle("My Form Title");
entry.createNewEntry();
}
});
});
By default, all the properties of an EntitySet
are placed in a single group or section in the auto-generated dialog or object page and the title for that group is hidden (it is visible on the object page). It is possible to categorize the properties into different groups in the auto-generated form.
Important: The form grouping feature creates sections in the object page when the Object Page feature is activated.
To create the form groups or object page sections, setFormGroups() method can be utilized.
Important: All of the key properties of the
EntitySet
are placed into a default group, and this behavior is not open to modification. The title of this group can be modified using the setDefaultGroupTitle() method. If you don't use setDefaultGroupTitle() method, the default group title will remain hidden in the auto-generated dialog. However, it is always visible in the auto-generated object page and the title is derived from the Form Title feature for the object page.
Important: Any properties that are not included in the setFormGroups() method or the default group are placed in a group designated as the Unknown Group. To disable the Unknown Group set the second parameter of the setFormGroups() method to
false
. This configuration allows only the key properties and the other properties specified in the setFormGroups() method to be visible in the auto-generated dialog or auto-generated object page.
Important: Should you wish to retain the Unknown Group but modify the group title, you may use the setUnknownGroupTitle() method.
Setter (setFormGroups)
Parameter | Type | Mandatory | Description |
---|---|---|---|
groups | IFormGroups[] | Yes | The form groups or sections displayed in the auto-generated dialog or object page |
includeAllProperties | boolean | No | If set to false all the other non-key properties will not be included. Default is true |
Returns | Description |
---|---|
void |
Getter (getFormGroups)
Returns | Description |
---|---|
IFormGroups[] | Returns the groups that were set using setFormGroups() method. Default value is [] |
Setter (setDefaultGroupTitle)
Parameter | Type | Mandatory | Description |
---|---|---|---|
title | string | Yes | The title of the default group or section that is generated for the key properties |
Returns | Description |
---|---|
void |
Getter (getDefaultGroupTitle)
Returns | Description |
---|---|
string | Returns the title that was set using setDefaultGroupTitle() method. Default value is undefined for the dialog. However, it is derived from the Form Title for the object page |
Setter (setUnknownGroupTitle)
Parameter | Type | Mandatory | Description |
---|---|---|---|
title | string | Yes | The title of the unknown group or section that is generated for the other properties |
Returns | Description |
---|---|
void |
Getter (getUnknownGroupTitle)
Returns | Description |
---|---|
string | Returns the title that was set using setUnknownGroupTitle() method. Default value is Unknown Group |
Sample:
Let us consider an EntitySet
named Products and we wish to categorize the properties into different groups in the auto-generated form. Please see the results after the code blocks.
TypeScript
import Controller from "sap/ui/core/mvc/Controller";
import EntryCreateCL from "ui5/antares/entry/v2/EntryCreateCL"; // Import the class
/**
* @namespace your.apps.namespace
*/
export default class YourController extends Controller {
public onInit() {
}
public onCreateProduct() {
// initialize
const entry = new EntryCreateCL<IProducts>(this, "Products");
// set the form groups and include all the other properties
entry.setFormGroups([{
title: "My Group 1",
properties: ["name", "description"]
},{
title: "My Group 2",
properties: ["brand", "price", "currency"]
}]);
// set the default group title
entry.setDefaultGroupTitle("My Default Group");
// set the unknown group title
entry.setUnknownGroupTitle("My Unknown Group");
// call the dialog
entry.createNewEntry();
}
}
interface IProducts {
ID: string;
name: string;
description: string;
brand: string;
price: number;
currency: string;
quantityInStock: number;
categoryID: string;
supplierID: string;
}
JavaScript
sap.ui.define([
"sap/ui/core/mvc/Controller",
"ui5/antares/entry/v2/EntryCreateCL" // Import the class
],
/**
* @param {typeof sap.ui.core.mvc.Controller} Controller
*/
function (Controller, EntryCreateCL) {
"use strict";
return Controller.extend("your.apps.namespace.YourController", {
onInit: function () {
},
onCreateProduct: async function () {
// initialize
const entry = new EntryCreateCL(this, "Products");
// set the form groups and include all the other properties
entry.setFormGroups([{
title: "My Group 1",
properties: ["name", "description"]
},{
title: "My Group 2",
properties: ["brand", "price", "currency"]
}]);
// set the default group title
entry.setDefaultGroupTitle("My Default Group");
// set the unknown group title
entry.setUnknownGroupTitle("My Unknown Group");
// call the dialog
entry.createNewEntry();
}
});
});
Property | Type | Description |
---|---|---|
IFormGroups | object |
|
title | string |
The title of the form group or object page section |
properties | string[] |
The properties that will be included into the group |
Upon pressing the Begin Button
by the end user, the Entry Create class initiates the validation process and submits the transient entity through the OData V2 Model. The default text displayed on the begin button is Create. This text can be modified using the setBeginButtonText() method.
Setter (setBeginButtonText)
Parameter | Type | Mandatory | Description |
---|---|---|---|
text | string | Yes | The text displayed on the begin button |
Returns | Description |
---|---|
void |
Getter (getBeginButtonText)
Returns | Description |
---|---|
string | Returns the value that was set using setBeginButtonText() method. Default value is Create |
Sample
Please find the result below after the code blocks.
TypeScript
import Controller from "sap/ui/core/mvc/Controller";
import EntryCreateCL from "ui5/antares/entry/v2/EntryCreateCL"; // Import the class
/**
* @namespace your.apps.namespace
*/
export default class YourController extends Controller {
public onInit() {
}
public async onCreateProduct() {
const entry = new EntryCreateCL(this, "Products");
// Set the begin button text
entry.setBeginButtonText("My Begin Button Text");
entry.createNewEntry();
}
}
JavaScript
sap.ui.define([
"sap/ui/core/mvc/Controller",
"ui5/antares/entry/v2/EntryCreateCL" // Import the class
],
/**
* @param {typeof sap.ui.core.mvc.Controller} Controller
*/
function (Controller, EntryCreateCL) {
"use strict";
return Controller.extend("your.apps.namespace.YourController", {
onInit: function () {
},
onCreateProduct: async function () {
const entry = new EntryCreateCL(this, "Products");
// Set the begin button text
entry.setBeginButtonText("My Begin Button Text");
entry.createNewEntry();
}
});
});
The default type used on the Begin Button
is ButtonType.Success. To modify the default begin button type, please utilize the setBeginButtonType() method.
Setter (setBeginButtonType)
Parameter | Type | Mandatory | Description |
---|---|---|---|
type | ButtonType | Yes | The type of the begin button |
Returns | Description |
---|---|
void |
Getter (getBeginButtonType)
Returns | Description |
---|---|
ButtonType | Returns the value that was set using setBeginButtonType() method. Default value is Success |
Sample
Please find the result below after the code blocks.
TypeScript
import Controller from "sap/ui/core/mvc/Controller";
import EntryCreateCL from "ui5/antares/entry/v2/EntryCreateCL"; // Import the class
import { ButtonType } from "sap/m/library"; // Import the ButtonType enum
/**
* @namespace your.apps.namespace
*/
export default class YourController extends Controller {
public onInit() {
}
public async onCreateProduct() {
const entry = new EntryCreateCL(this, "Products");
// Set the begin button type
entry.setBeginButtonType(ButtonType.Attention);
entry.createNewEntry();
}
}
JavaScript
sap.ui.define([
"sap/ui/core/mvc/Controller",
"ui5/antares/entry/v2/EntryCreateCL", // Import the class
"sap/m/ButtonType" // Import the ButtonType enum
],
/**
* @param {typeof sap.ui.core.mvc.Controller} Controller
*/
function (Controller, EntryCreateCL, ButtonType) {
"use strict";
return Controller.extend("your.apps.namespace.YourController", {
onInit: function () {
},
onCreateProduct: async function () {
const entry = new EntryCreateCL(this, "Products");
// Set the begin button type
entry.setBeginButtonType(ButtonType.Attention);
entry.createNewEntry();
}
});
});
Upon pressing the End Button
by the end user, the Entry Create class resets the transient entity through the OData V2 Model and destroys the created dialog. The default text displayed on the end button is Close. This text can be modified using the setEndButtonText() method.
Setter (setEndButtonText)
Parameter | Type | Mandatory | Description |
---|---|---|---|
text | string | Yes | The text displayed on the end button |
Returns | Description |
---|---|
void |
Getter (getEndButtonText)
Returns | Description |
---|---|
string | Returns the value that was set using setEndButtonText() method. Default value is Close |
Sample
Please find the result below after the code blocks.
TypeScript
import Controller from "sap/ui/core/mvc/Controller";
import EntryCreateCL from "ui5/antares/entry/v2/EntryCreateCL"; // Import the class
/**
* @namespace your.apps.namespace
*/
export default class YourController extends Controller {
public onInit() {
}
public async onCreateProduct() {
const entry = new EntryCreateCL(this, "Products");
// Set the end button text
entry.setEndButtonText("My End Button Text");
entry.createNewEntry();
}
}
JavaScript
sap.ui.define([
"sap/ui/core/mvc/Controller",
"ui5/antares/entry/v2/EntryCreateCL" // Import the class
],
/**
* @param {typeof sap.ui.core.mvc.Controller} Controller
*/
function (Controller, EntryCreateCL) {
"use strict";
return Controller.extend("your.apps.namespace.YourController", {
onInit: function () {
},
onCreateProduct: async function () {
const entry = new EntryCreateCL(this, "Products");
// Set the end button text
entry.setEndButtonText("My End Button Text");
entry.createNewEntry();
}
});
});
The default type used on the End Button
is ButtonType.Negative. To modify the default end button type, please utilize the setEndButtonType() method.
Setter (setEndButtonType)
Parameter | Type | Mandatory | Description |
---|---|---|---|
type | ButtonType | Yes | The type of the end button |
Returns | Description |
---|---|
void |
Getter (getEndButtonType)
Returns | Description |
---|---|
ButtonType | Returns the value that was set using setEndButtonType() method. Default value is Negative |
Sample
Please find the result below after the code blocks.
TypeScript
import Controller from "sap/ui/core/mvc/Controller";
import EntryCreateCL from "ui5/antares/entry/v2/EntryCreateCL"; // Import the class
import { ButtonType } from "sap/m/library"; // Import the ButtonType enum
/**
* @namespace your.apps.namespace
*/
export default class YourController extends Controller {
public onInit() {
}
public async onCreateProduct() {
const entry = new EntryCreateCL(this, "Products");
// Set the end button type
entry.setEndButtonType(ButtonType.Transparent);
entry.createNewEntry();
}
}
JavaScript
sap.ui.define([
"sap/ui/core/mvc/Controller",
"ui5/antares/entry/v2/EntryCreateCL", // Import the class
"sap/m/ButtonType" // Import the ButtonType enum
],
/**
* @param {typeof sap.ui.core.mvc.Controller} Controller
*/
function (Controller, EntryCreateCL, ButtonType) {
"use strict";
return Controller.extend("your.apps.namespace.YourController", {
onInit: function () {
},
onCreateProduct: async function () {
const entry = new EntryCreateCL(this, "Products");
// Set the end button type
entry.setEndButtonType(ButtonType.Transparent);
entry.createNewEntry();
}
});
});
By default, Entry Create class generates random UUID values for the key properties (with Edm.Guid
type) of the EntityType
and makes them invisible on the form to the end user.
To modify the default random UUID generation behavior, please utilize the setGenerateRandomGuid() method.
Setter (setGenerateRandomGuid)
Parameter | Type | Mandatory | Description |
---|---|---|---|
strategy | GuidStrategies | Yes | The random UUID generation strategy |
Returns | Description |
---|---|
void |
Getter (getGenerateRandomGuid)
Returns | Description |
---|---|
GuidStrategies | Returns the value that was set using setGenerateRandomGuid() method. Default value is ONLY_KEY |
To modify the default visibility behavior of the properties with Edm.Guid
type, please utilize the setDisplayGuidProperties() method.
Setter (setDisplayGuidProperties)
Parameter | Type | Mandatory | Description |
---|---|---|---|
strategy | GuidStrategies | Yes | The visibility strategy for the properties with Edm.Guid type |
Returns | Description |
---|---|
void |
Getter (getDisplayGuidProperties)
Returns | Description |
---|---|
GuidStrategies | Returns the value that was set using setDisplayGuidProperties() method. Default value is ONLY_NON_KEY |
Sample
Let us consider the following scenario: You have an EntitySet
named Products with ID
, categoryID
, and supplierID
, all of which have the Edm.Guid
type. You would like to allow the end user to view all Edm.Guid
properties and have the library generate random UUID values only for the non-key properties.
TypeScript
import Controller from "sap/ui/core/mvc/Controller";
import EntryCreateCL from "ui5/antares/entry/v2/EntryCreateCL"; // Import the class
import { GuidStrategies } from "ui5/antares/types/entry/enums"; // Import the GuidStrategies enum
/**
* @namespace your.apps.namespace
*/
export default class YourController extends Controller {
public onInit() {
}
public async onCreateProduct() {
const entry = new EntryCreateCL(this, "Products");
// Let the end user to display all the properties with Edm.Guid type
entry.setDisplayGuidProperties(GuidStrategies.ALL);
// Have the library generate random UUID values only for the non-key properties
entry.setGenerateRandomGuid(GuidStrategies.ONLY_NON_KEY);
entry.createNewEntry();
}
}
JavaScript
sap.ui.define([
"sap/ui/core/mvc/Controller",
"ui5/antares/entry/v2/EntryCreateCL", // Import the class
"ui5/antares/types/entry/enums" // Import the enums
],
/**
* @param {typeof sap.ui.core.mvc.Controller} Controller
*/
function (Controller, EntryCreateCL, EntryEnums) {
"use strict";
// Destructure the object to retrieve the GuidStrategies enum
const { GuidStrategies } = EntryEnums;
return Controller.extend("your.apps.namespace.YourController", {
onInit: function () {
},
onCreateProduct: async function () {
const entry = new EntryCreateCL(this, "Products");
// Let the end user to display all the properties with Edm.Guid type
entry.setDisplayGuidProperties(GuidStrategies.ALL);
// Have the library generate random UUID values only for the non-key properties
entry.setGenerateRandomGuid(GuidStrategies.ONLY_NON_KEY);
entry.createNewEntry();
}
});
});
Important: Please note that if a random UUID is generated for a property and marked as visible, this field cannot be edited by the end user.
Name | Description for setGenerateRandomGuid
|
---|---|
GuidStrategies.ALL | Generate random UUID values for all the properties with Edm.Guid type |
GuidStrategies.ONLY_KEY | Generate random UUID values only for the key properties with Edm.Guid type |
GuidStrategies.ONLY_NON_KEY | Generate random UUID values only for the properties that are not key and have Edm.Guid type |
GuidStrategies.NONE | No random UUID generation |
Name | Description for setDisplayGuidProperties
|
---|---|
GuidStrategies.ALL | The end user can display all the properties with Edm.Guid type |
GuidStrategies.ONLY_KEY | The end user can display only the key properties with Edm.Guid type |
GuidStrategies.ONLY_NON_KEY | The end user can display only the properties that are not key and have Edm.Guid type |
GuidStrategies.NONE | No property with Edm.Guid is visible to the end user |
The auto-generated form elements are displayed in the same order as the OData V2 metadata by default.
Important: It should be noted that the key properties always come first on the auto-generated form. Please be advised that this behavior is not open to modification.
The order of the non-key properties can be modified using setPropertyOrder() method.
Setter (setPropertyOrder)
Parameter | Type | Mandatory | Description |
---|---|---|---|
order | string[] | Yes | The order of the non-key properties that will be placed into the auto-generated form will be in the same order as this parameter |
useAllProperties? | boolean | No | If the value is set to false, only the key properties and the properties specified in the order parameter will be visible to the end user |
Returns | Description |
---|---|
void |
Getter (getPropertyOrder)
Returns | Description |
---|---|
string[] | Returns the value that was set using setPropertyOrder() method. Default value is [] |
Sample
Please find the result below after the code blocks.
TypeScript
import Controller from "sap/ui/core/mvc/Controller";
import EntryCreateCL from "ui5/antares/entry/v2/EntryCreateCL"; // Import the class
/**
* @namespace your.apps.namespace
*/
export default class YourController extends Controller {
public onInit() {
}
public async onCreateProduct() {
const entry = new EntryCreateCL(this, "Products");
// Set the property order and bring all the properties
entry.setPropertyOrder(["categoryID", "supplierID", "price", "currency", "name"]);
entry.createNewEntry();
}
public async onCreateCustomer() {
const entry = new EntryCreateCL(this, "Customers");
// Set the property order and exclude the other properties
entry.setPropertyOrder(["country", "name"], false);
entry.createNewEntry();
}
}
JavaScript
sap.ui.define([
"sap/ui/core/mvc/Controller",
"ui5/antares/entry/v2/EntryCreateCL" // Import the class
],
/**
* @param {typeof sap.ui.core.mvc.Controller} Controller
*/
function (Controller, EntryCreateCL) {
"use strict";
return Controller.extend("your.apps.namespace.YourController", {
onInit: function () {
},
onCreateProduct: async function () {
const entry = new EntryCreateCL(this, "Products");
// Set the property order and bring all the properties
entry.setPropertyOrder(["categoryID", "supplierID", "price", "currency", "name"]);
entry.createNewEntry();
},
onCreateCustomer: async function () {
const entry = new EntryCreateCL(this, "Customers");
// Set the property order and exclude the other properties
entry.setPropertyOrder(["country", "name"], false);
entry.createNewEntry();
}
});
});
Before | After |
---|---|
By default, all the EntityType
properties of the EntitySet
that is set in the class constructor are visible to the end user.
To exclude properties from the auto-generated form, please use setExcludedProperties() method. Please be advised that it is still possible to set initial values for excluded properties through the createNewEntry() method's parameter.
Important: It is not possible to exclude any of the key properties.
Setter (setExcludedProperties)
Parameter | Type | Mandatory | Description |
---|---|---|---|
properties | string[] | Yes | The properties that will be excluded from the auto-generated form |
Returns | Description |
---|---|
void |
Getter (getExcludedProperties)
Returns | Description |
---|---|
string[] | Returns the value that was set using setExcludedProperties() method. Default value is [] |
Sample
Please find the result below after the code blocks.
TypeScript
import Controller from "sap/ui/core/mvc/Controller";
import EntryCreateCL from "ui5/antares/entry/v2/EntryCreateCL"; // Import the class
/**
* @namespace your.apps.namespace
*/
export default class YourController extends Controller {
public onInit() {
}
public async onCreateProduct() {
const entry = new EntryCreateCL(this, "Products");
// Set the excluded properties
entry.setExcludedProperties(["categoryID", "supplierID"]);
entry.createNewEntry();
}
}
JavaScript
sap.ui.define([
"sap/ui/core/mvc/Controller",
"ui5/antares/entry/v2/EntryCreateCL" // Import the class
],
/**
* @param {typeof sap.ui.core.mvc.Controller} Controller
*/
function (Controller, EntryCreateCL) {
"use strict";
return Controller.extend("your.apps.namespace.YourController", {
onInit: function () {
},
onCreateProduct: async function () {
const entry = new EntryCreateCL(this, "Products");
// Set the excluded properties
entry.setExcludedProperties(["categoryID", "supplierID"]);
entry.createNewEntry();
}
});
});
Before | After |
---|---|
Entry Create class includes a built-in validation mechanism that checks the mandatory properties and applies Validation Logic before submitting the transient entity.
Important: By default, all the key properties and the properties with the
Nullable=false
attribute are marked as mandatory.
In order to include properties in the mandatory check mechanism, setMandatoryProperties() method can be utilized.
Setter (setMandatoryProperties)
Parameter | Type | Mandatory | Description |
---|---|---|---|
properties | string[] | Yes | The properties that will be included into the mandatory check mechanism |
Returns | Description |
---|---|
void |
Getter (getMandatoryProperties)
Returns | Description |
---|---|
string[] | Returns the value that was set using setMandatoryProperties() method. Default value is [] |
Sample
Please find the result below after the code blocks.
TypeScript
import Controller from "sap/ui/core/mvc/Controller";
import EntryCreateCL from "ui5/antares/entry/v2/EntryCreateCL"; // Import the class
/**
* @namespace your.apps.namespace
*/
export default class YourController extends Controller {
public onInit() {
}
public async onCreateProduct() {
const entry = new EntryCreateCL(this, "Products");
// Set the mandatory properties
entry.setMandatoryProperties(["name", "description"]);
entry.createNewEntry();
}
}
JavaScript
sap.ui.define([
"sap/ui/core/mvc/Controller",
"ui5/antares/entry/v2/EntryCreateCL" // Import the class
],
/**
* @param {typeof sap.ui.core.mvc.Controller} Controller
*/
function (Controller, EntryCreateCL) {
"use strict";
return Controller.extend("your.apps.namespace.YourController", {
onInit: function () {
},
onCreateProduct: async function () {
const entry = new EntryCreateCL(this, "Products");
// Set the mandatory properties
entry.setMandatoryProperties(["name", "description"]);
entry.createNewEntry();
}
});
});
Before | After |
---|---|
If a property fails the mandatory check mechanism, the value state of the UI control (SmartField, Input, etc.) is set to Error
, and a default message is displayed in the sap.m.MessageBox.error to the end user.
Default Message: Please fill in all required fields.
To customize the default error message, please utilize the setMandatoryErrorMessage() method.
Setter (setMandatoryErrorMessage)
Parameter | Type | Mandatory | Description |
---|---|---|---|
message | string | Yes | The displayed message when the mandatory check mechanism fails |
Returns | Description |
---|---|
void |
Getter (getMandatoryErrorMessage)
Returns | Description |
---|---|
string | Returns the value that was set using setMandatoryErrorMessage() method. Default value is Please fill in all required fields. |
Sample
Please find the result below after the code blocks.
TypeScript
import Controller from "sap/ui/core/mvc/Controller";
import EntryCreateCL from "ui5/antares/entry/v2/EntryCreateCL"; // Import the class
/**
* @namespace your.apps.namespace
*/
export default class YourController extends Controller {
public onInit() {
}
public async onCreateProduct() {
const entry = new EntryCreateCL(this, "Products");
// Set the mandatory error message
entry.setMandatoryErrorMessage("My Mandatory Error Message");
entry.createNewEntry();
}
}
JavaScript
sap.ui.define([
"sap/ui/core/mvc/Controller",
"ui5/antares/entry/v2/EntryCreateCL" // Import the class
],
/**
* @param {typeof sap.ui.core.mvc.Controller} Controller
*/
function (Controller, EntryCreateCL) {
"use strict";
return Controller.extend("your.apps.namespace.YourController", {
onInit: function () {
},
onCreateProduct: async function () {
const entry = new EntryCreateCL(this, "Products");
// Set the mandatory error message
entry.setMandatoryErrorMessage("My Mandatory Error Message");
entry.createNewEntry();
}
});
});
By default, if the property's type is Edm.Guid
and the library generates a random UUID for it, the end user is unable to edit it.
For further information on properties with an
Edm.Guid
type, please refer to the Properties with Edm.Guid Type section.
In order to prevent end users from editing certain properties, setReadonlyProperties() method can be utilized.
Important: It is possible to set the initial values for readonly properties.
Setter (setReadonlyProperties)
Parameter | Type | Mandatory | Description |
---|---|---|---|
properties | string[] | Yes | The read-only properties |
Returns | Description |
---|---|
void |
Getter (getReadonlyProperties)
Returns | Description |
---|---|
string[] | Returns the value that was set using setReadonlyProperties() method. Default value is [] |
Sample
Please find the result below after the code blocks.
TypeScript
import Controller from "sap/ui/core/mvc/Controller";
import EntryCreateCL from "ui5/antares/entry/v2/EntryCreateCL"; // Import the class
/**
* @namespace your.apps.namespace
*/
export default class YourController extends Controller {
public onInit() {
}
public async onCreateProduct() {
const entry = new EntryCreateCL(this, "Products");
// Set the read-only properties
entry.setReadonlyProperties(["name", "description"]);
entry.createNewEntry({
name: "My Product Name",
description: "My Product Description"
});
}
}
JavaScript
sap.ui.define([
"sap/ui/core/mvc/Controller",
"ui5/antares/entry/v2/EntryCreateCL" // Import the class
],
/**
* @param {typeof sap.ui.core.mvc.Controller} Controller
*/
function (Controller, EntryCreateCL) {
"use strict";
return Controller.extend("your.apps.namespace.YourController", {
onInit: function () {
},
onCreateProduct: async function () {
const entry = new EntryCreateCL(this, "Products");
// Set the read-only properties
entry.setReadonlyProperties(["name", "description"]);
entry.createNewEntry({
name: "My Product Name",
description: "My Product Description"
});
}
});
});
Once the transient entity has been successfully submitted, Entry Create class can then call a function with a specific signature. The result of the submission is then passed to the attached function.
To attach a function, attachSubmitCompleted() method can be utilized.
Setter (attachSubmitCompleted)
Parameter | Type | Mandatory | Description |
---|---|---|---|
submitCompleted | (response: ResponseCL<ResponseT = object>) => void | Yes | The function that will be called after the successful submit |
listener? | object | No | The default listener is the controller from constructor |
Returns | Description |
---|---|
void |
Sample
Once the submission is successful, you would like to receive a response and take the necessary actions.
TypeScript
import Controller from "sap/ui/core/mvc/Controller";
import EntryCreateCL from "ui5/antares/entry/v2/EntryCreateCL"; // Import the class
import ResponseCL from "ui5/antares/entry/v2/ResponseCL"; // Import the ResponseCL class
/**
* @namespace your.apps.namespace
*/
export default class YourController extends Controller {
public onInit() {
}
public async onCreateProduct() {
const entry = new EntryCreateCL<IProducts>(this, "Products");
// Attach the submit completed function
entry.attachSubmitCompleted(this.productSubmitCompleted, this);
entry.createNewEntry();
}
// Please use the same type for the ResponseCL generic as you did for EntryCreateCL
private productSubmitCompleted(response: ResponseCL<IProducts>): void {
// Get the status code. Please be aware, it may also be undefined
const statusCode = response.getStatusCode();
// Get the data that was submitted. Please be aware, it may also be undefined
const submittedData = response.getResponse();
if (submittedData) {
// Some operations
const createdProductID = submittedData.ID;
}
}
}
interface IProducts {
ID: string;
name: string;
description: string;
brand: string;
price: number;
currency: string;
quantityInStock: number;
categoryID: string;
supplierID: string;
}
JavaScript
sap.ui.define([
"sap/ui/core/mvc/Controller",
"ui5/antares/entry/v2/EntryCreateCL" // Import the class
],
/**
* @param {typeof sap.ui.core.mvc.Controller} Controller
*/
function (Controller, EntryCreateCL) {
"use strict";
return Controller.extend("your.apps.namespace.YourController", {
onInit: function () {
},
onCreateProduct: async function () {
const entry = new EntryCreateCL(this, "Products");
// Attach the submit completed function
entry.attachSubmitCompleted(this._productSubmitCompleted, this);
entry.createNewEntry();
},
_productSubmitCompleted: function (response) {
// Get the status code. Please be aware, it may also be undefined
const statusCode = response.getStatusCode();
// Get the data that was submitted. Please be aware, it may also be undefined
const submittedData = response.getResponse();
if (submittedData) {
// Some operations
const createdProductID = submittedData.ID;
}
}
});
});
In the event that the submission of the transient entity is unsuccessful, Entry Create class can then call a function with a specific signature. The result of the submission will then be passed to the attached function.
To attach a function, attachSubmitFailed() method can be utilized.
Setter (attachSubmitFailed)
Parameter | Type | Mandatory | Description |
---|---|---|---|
submitFailed | (response: ResponseCL<ISubmitResponse>) => void | Yes | The function that will be called after the submission fail |
listener? | object | No | The default listener is the controller from constructor |
Returns | Description |
---|---|
void |
TypeScript
import Controller from "sap/ui/core/mvc/Controller";
import MessageBox from "sap/m/MessageBox";
import EntryCreateCL from "ui5/antares/entry/v2/EntryCreateCL"; // Import the class
import ResponseCL from "ui5/antares/entry/v2/ResponseCL"; // Import the ResponseCL class
import { ISubmitResponse } from "ui5/antares/types/entry/submit"; // Import the error type
/**
* @namespace your.apps.namespace
*/
export default class YourController extends Controller {
public onInit() {
}
public async onCreateProduct() {
const entry = new EntryCreateCL<IProducts>(this, "Products");
// Attach the submit failed function
entry.attachSubmitFailed(this.productSubmitFailed, this);
entry.createNewEntry();
}
// Please use the ISubmitResponse type for the ResponseCL generic
private productSubmitFailed(response: ResponseCL<ISubmitResponse>): void {
// Get the status code. Please be aware, it may also be undefined
const statusCode = response.getStatusCode();
// Get the response. Please be aware, it may also be undefined
const reason = response.getResponse();
// Get the statusText
if (reason) {
MessageBox.error(reason.statusText || "The product was not created!");
}
}
}
interface IProducts {
ID: string;
name: string;
description: string;
brand: string;
price: number;
currency: string;
quantityInStock: number;
categoryID: string;
supplierID: string;
}
JavaScript
sap.ui.define([
"sap/ui/core/mvc/Controller",
"sap/m/MessageBox",
"ui5/antares/entry/v2/EntryCreateCL" // Import the class
],
/**
* @param {typeof sap.ui.core.mvc.Controller} Controller
*/
function (Controller, MessageBox, EntryCreateCL) {
"use strict";
return Controller.extend("your.apps.namespace.YourController", {
onInit: function () {
},
onCreateProduct: async function () {
const entry = new EntryCreateCL(this, "Products");
// Attach the submit failed function
entry.attachSubmitFailed(this._productSubmitFailed, this);
entry.createNewEntry();
},
_productSubmitFailed: function (response) {
// Get the status code. Please be aware, it may also be undefined
const statusCode = response.getStatusCode();
// Get the response. Please be aware, it may also be undefined
const reason = response.getResponse();
// Get the statusText
if (reason) {
MessageBox.error(reason.statusText || "The product was not created!");
}
}
});
});
Once the transient entity has been submitted, the generic ResponseCL<ResponseT = object> object is instantiated and passed to the functions attached using the attachSubmitCompleted() or attachSubmitFailed() methods.
The class has 2 public methods that can be used to retrieve information once the submit has been completed. The return type of the getResponse() method is dependent on the response type (success or failure).
Submit Completed (getResponse)
Returns | Description |
---|---|
ResponseT or object or undefined | Returns the data that was submitted successfully through the OData V2 Model. |
Submit Failed (getResponse)
Returns | Description |
---|---|
object | |
statusCode?: string | undefined
|
The status code of the HTTP request. |
body?: string | undefined
|
The HTTP response body. |
statusText?: string | undefined
|
The HTTP status text. |
headers?: object | undefined
|
The HTTP response headers. |
Submit Completed and Failed (getStatusCode)
Returns | Description |
---|---|
string or undefined | Returns the status code of the HTTP Request |
Entry Create class can create a Value Help Dialog for the properties that are rendered as sap.m.Input on the auto-generated form. Please find below a list of the features that the Value Help class offers.
Important: Please be advised that the Value Help feature is only available for the SIMPLE Form. Should you require further information, please refer to the Form Type section.
- Generates a Value Help Dialog with a table and filterbar consisting of the
EntitySet
properties defined in the class constructor - Handles the filterbar and search field
- Handles the selection
You must initialize an object from ValueHelpCL in order to use it.
Parameter | Type | Mandatory | Default Value | Description |
---|---|---|---|---|
controller | sap.ui.core.mvc.Controller | Yes | The controller object (usually this ) |
|
settings | object | Yes | ||
propertyName | string | Yes | The property of the entity for which the Value Help is being created | |
valueHelpEntity | string | Yes | The EntitySet name that will be bound to the table in the value help dialog |
|
valueHelpProperty | string | Yes | The property of the valueHelpEntity whose value will be set to propertyName after the selection is made in the table |
|
readonlyProperties? | string[] | No | [] | The properties of the valueHelpEntity that are displayed in the columns of the table |
excludedFilterProperties? | string[] | No | [] | The properties of the valueHelpEntity that are excluded from the filterbar |
title? | string | No | valueHelpEntity |
The title of the Value Help Dialog |
searchPlaceholder? | string | No | Search valueHelpEntity
|
The placeholder in the search field of the Value Help Dialog |
namingStrategy? | NamingStrategies | No | CAMEL_CASE | The naming strategy that is used to generate the labels for filterbar and table column headers |
resourceBundlePrefix? | string | No | antaresVH | The resource bundle prefix that is used for the i18n text lookup |
useMetadataLabels? | boolean | No | false | Indicates if the labels in metadata should be used for the filterbar and table column headers |
filterModelName? | string | No | UI5AntaresVHFilterModel | The JSONModel name of the filterbar which is needed by the ValueHelpCL |
filterCaseSensitive? | boolean | No | false | Set to true for case sensitive search in the filterbar |
modelName? | string | No | undefined | The name of the OData V2 model. Do not specify if the model name = "" |
Here are the steps that ValueHelpCL follows when creating the Value Help Dialog.
- Creates a table and makes the
settings.valueHelpProperty
the first column of the table - Adds all the properties specified in the
settings.readonlyProperties
array as columns to the table next to the first column - Binds the
EntitySet
specified in thesettings.valueHelpEntity
to the created table - Creates a filterbar and UI Controls (Input, DatePicker etc.) for the
settings.valueHelpProperty
andsettings.readonlyProperties
if they don't exist in thesettings.excludedFilterProperties
array - Creates a JSON Model for handling the filterbar
- Creates a search field
- Uses internal functions to handle the selection and filterbar search
Important: By default, all properties defined in the readonlyProperties parameter are included in the filterbar. To exclude properties from the filter bar, use the excludedFilterProperties parameter. Properties excluded from the filter bar will still be visible in the table of the Value Help Dialog. Please be advised that the key property defined in the valueHelpProperty parameter cannot be excluded from the filter bar.
The ValueHelpCL class uses the same methodology as that defined in Label Generation for the generation of labels for table column headers and filter bar elements. Please find below a list of the settings that can be applied in different label generation scenarios.
Scenario 1: In order to utilise the labels defined in the OData metadata, please set the settings.useMetadataLabels parameter to true.
Scenario 2: In order to use i18n labels on the label generation, please either use the default format (antaresVH + valueHelpEntity
+ propertyName) for the text keys or modify the prefix by setting the settings.resourceBundlePrefix parameter.
Scenario 3: In order for the library to generate labels from the technical property names of the EntitySet
that is defined, it is necessary to set the correct value for the settings.namingStrategy parameter.
Sample
Let us consider the following scenario: You have an EntitySet
named Products with the following properties: ID
, name
, categoryID
, and supplierID
. You also have other EntitySet
s named Suppliers and Categories, which you would like to use as a Value Help for the Products-supplierID and Products-categoryID properties.
TypeScript
import Controller from "sap/ui/core/mvc/Controller";
import EntryCreateCL from "ui5/antares/entry/v2/EntryCreateCL"; // Import the class
import ValueHelpCL from "ui5/antares/ui/ValueHelpCL"; // Import the Value Help class
import { FormTypes } from "ui5/antares/types/entry/enums"; // Import the FormTypes enum
/**
* @namespace your.apps.namespace
*/
export default class YourController extends Controller {
public onInit() {
}
public async onCreateProduct() {
const entry = new EntryCreateCL(this, "Products");
// Create an object from the ValueHelpCL class
const categoryVH = new ValueHelpCL(this, {
propertyName: "categoryID", // This is the property of the Products entity
valueHelpEntity: "Categories", // This is the entity set that brings data
valueHelpProperty: "ID", // This is the property of the entity set that will be mapped to propertyName after the selection is made
readonlyProperties: ["name"] // These properties will be the columns of the table on the Value Help Dialog
});
// Create an object from the ValueHelpCL class
const supplierVH = new ValueHelpCL(this, {
propertyName: "supplierID", // This is the property of the Products entity
valueHelpEntity: "Suppliers", // This is the entity set that brings data
valueHelpProperty: "ID", // This is the property of the entity set that will be mapped to propertyName after the selection is made
readonlyProperties: [ // These properties will be the columns of the table on the Value Help Dialog
"companyName",
"contactName",
"contactTitle",
"country",
"city",
"paymentTerms"
],
excludedFilterProperties: ["contactName"] // These properties will be excluded from the filterbar
});
// Set the form type to SIMPLE to be able to use Value Help feature
entry.setFormType(FormTypes.SIMPLE);
// Add the value help object for categoryID
entry.addValueHelp(categoryVH);
// Add the value help object for supplierID
entry.addValueHelp(supplierVH);
entry.createNewEntry();
}
}
JavaScript
sap.ui.define([
"sap/ui/core/mvc/Controller",
"ui5/antares/entry/v2/EntryCreateCL", // Import the class
"ui5/antares/ui/ValueHelpCL", // Import the Value Help class
"ui5/antares/types/entry/enums" // Import the enums
],
/**
* @param {typeof sap.ui.core.mvc.Controller} Controller
*/
function (Controller, EntryCreateCL, ValueHelpCL, EntryEnums) {
"use strict";
// Destructure the object to retrieve the FormTypes enum
const { FormTypes } = EntryEnums;
return Controller.extend("your.apps.namespace.YourController", {
onInit: function () {
},
onCreateProduct: async function () {
const entry = new EntryCreateCL(this, "Products");
// Create an object from the ValueHelpCL class
const categoryVH = new ValueHelpCL(this, {
propertyName: "categoryID", // This is the property of the Products entity
valueHelpEntity: "Categories", // This is the entity set that brings data
valueHelpProperty: "ID", // This is the property of the entity set that will be mapped to propertyName after the selection is made
readonlyProperties: ["name"] // These properties will be the columns of the table on the Value Help Dialog
});
// Create an object from the ValueHelpCL class
const supplierVH = new ValueHelpCL(this, {
propertyName: "supplierID", // This is the property of the Products entity
valueHelpEntity: "Suppliers", // This is the entity set that brings data
valueHelpProperty: "ID", // This is the property of the entity set that will be mapped to propertyName after the selection is made
readonlyProperties: [ // These properties will be the columns of the table on the Value Help Dialog
"companyName",
"contactName",
"contactTitle",
"country",
"city",
"paymentTerms"
],
excludedFilterProperties: ["contactName"] // These properties will be excluded from the filterbar
});
// Set the form type to SIMPLE to be able to use Value Help feature
entry.setFormType(FormTypes.SIMPLE);
// Add the value help object for categoryID
entry.addValueHelp(categoryVH);
// Add the value help object for supplierID
entry.addValueHelp(supplierVH);
entry.createNewEntry();
}
});
});
categoryID | supplierID |
---|---|
The ValueHelpCL class can also be utilized as a standalone solution with the sap.m.Input control.
Sample
Let us consider a scenario in which a sap.m.Input is present on an XML View. The objective is to create a Value Help Dialog when the valueHelpRequest event is triggered by the end user.
TypeScript
import Controller from "sap/ui/core/mvc/Controller";
import ValueHelpCL from "ui5/antares/ui/ValueHelpCL"; // Import the Value Help class
import { Input$ValueHelpRequestEvent } from "sap/m/Input"; // Import the Value Help Request event type
/**
* @namespace your.apps.namespace
*/
export default class YourController extends Controller {
public onInit() {
}
// The parameter type should be Input$ValueHelpRequestEvent
public async onValueHelpRequest(event: Input$ValueHelpRequestEvent) {
// Create an object from the ValueHelpCL class
const supplierVH = new ValueHelpCL(this, {
propertyName: "STANDALONE", // Since this is a mandatory param and not relevant for the standalone usage, you can set anything
valueHelpEntity: "Suppliers", // This is the entity set that brings data
valueHelpProperty: "ID", // This is the property of the entity set whose value will be set to the input
readonlyProperties: [ // These properties will be the columns of the table on the Value Help Dialog
"companyName",
"contactName",
"contactTitle",
"country",
"city",
"paymentTerms"
],
excludedFilterProperties: ["contactName"] // These properties will be excluded from the filterbar
});
// Pass the Input$ValueHelpRequestEvent to the public openValueHelpDialog method.
supplierVH.openValueHelpDialog(event);
}
}
JavaScript
sap.ui.define([
"sap/ui/core/mvc/Controller",
"ui5/antares/ui/ValueHelpCL" // Import the Value Help class
],
/**
* @param {typeof sap.ui.core.mvc.Controller} Controller
*/
function (Controller, ValueHelpCL) {
"use strict";
return Controller.extend("your.apps.namespace.YourController", {
onInit: function () {
},
onValueHelpRequest: async function (event) {
// Create an object from the ValueHelpCL class
const supplierVH = new ValueHelpCL(this, {
propertyName: "STANDALONE", // Since this is a mandatory param and not relevant for the standalone usage, you can set anything
valueHelpEntity: "Suppliers", // This is the entity set that brings data
valueHelpProperty: "ID", // This is the property of the entity set whose value will be set to the input
readonlyProperties: [ // These properties will be the columns of the table on the Value Help Dialog
"companyName",
"contactName",
"contactTitle",
"country",
"city",
"paymentTerms"
],
excludedFilterProperties: ["contactName"] // These properties will be excluded from the filterbar
});
// Pass the event to the public openValueHelpDialog method.
supplierVH.openValueHelpDialog(event);
}
});
});
The UI5 Antares classes includes a built-in validation mechanism to ensure that the input provided by the end user is accurate and complete before submission through the OData V2 Model.
In the event of a validation failure, the end user is promptly informed via an sap.m.MessageBox.error and the submission remains in a pending status until the validation is successfully completed.
There are 2 possible approaches to user input validation.
You must initialize an object from ValidationLogicCL in order to use it.
Parameter | Type | Mandatory | Default Value | Description |
---|---|---|---|---|
settings | object | Yes | ||
propertyName | string | Yes | The property of the entity set in the constructor for which the validation will be done | |
validator? | (value: ValidatorValueParameter) => boolean | No | The validator function | |
listener? | object | No | The object that is bind to the validator function | |
value1? | string | number | Date | UI5 Date | No | First value to use with the given operator | |
value2? | string | number | Date | UI5 Date | No | Second value to use with the given operator, used only for the BT and NB operators | |
operator? | ValidationOperator | No | Operator used for the validation | |
message? | string | No | Validation failed for propertyName
|
The message that is displayed when the validation fails |
showMessageBox? | boolean | No | true | Indicates if the message box should be displayed by the end user |
invalidValueMessage? | string | No | Invalid value for propertyName
|
Displayed message when the end user types in an invalid value. For instance: string to a number field |
If there are specific values that should be used for user input validation, they can be defined easily on the constructor.
Important: Please note that value1 and value2 determine the type of the property. For example, if the property type is
Edm.DateTime
orEdm.DateTimeOffset
, then value1 and value2 must be either JavaScript Date or UI5 Date.
Sample
Let us consider an EntitySet
named Products with the following properties: ID
, name
, description
, price
, and currency
. We wish to implement a logic that allows the price to be between 1500 and 2500, and that the currency is limited to EUR.
TypeScript
import Controller from "sap/ui/core/mvc/Controller";
import EntryCreateCL from "ui5/antares/entry/v2/EntryCreateCL"; // Import the class
import ValidationLogicCL from "ui5/antares/ui/ValidationLogicCL"; // Import the ValidationLogicCL class
import { ValidationOperator } from "ui5/antares/types/ui/enums"; // Import the ValidationOperator enum
/**
* @namespace your.apps.namespace
*/
export default class YourController extends Controller {
public onInit() {
}
public async onCreateProduct() {
const entry = new EntryCreateCL<IProducts>(this, "Products");
// Create an object from the Validation Logic class for the price validation
const priceValidation = new ValidationLogicCL({
propertyName: "price", // price property of the Products
operator: ValidationOperator.BT,
value1: 1500,
value2: 2500,
message: "The price must be between 1500 and 2500",
invalidValueMessage: "Please only type number for the price field"
});
// Create an object from the Validation Logic class for the currency validation
const currencyValidation = new ValidationLogicCL({
propertyName: "currency", // Currency property of the Products
operator: ValidationOperator.EQ,
value1: "EUR",
message: "Only EUR currency can be used"
});
// Add the price validation object
entry.addValidationLogic(priceValidation);
// Add the currency validation object
entry.addValidationLogic(currencyValidation);
entry.createNewEntry();
}
}
interface IProducts {
ID: string;
name: string;
description: string;
brand: string;
price: number;
currency: string;
quantityInStock: number;
categoryID: string;
supplierID: string;
}
JavaScript
sap.ui.define([
"sap/ui/core/mvc/Controller",
"ui5/antares/entry/v2/EntryCreateCL", // Import the class
"ui5/antares/ui/ValidationLogicCL", // Import the ValidationLogicCL class
"ui5/antares/types/ui/enums" // Import the enums
],
/**
* @param {typeof sap.ui.core.mvc.Controller} Controller
*/
function (Controller, EntryCreateCL, ValidationLogicCL, UIEnums) {
"use strict";
// Destructure the object to retrieve the ValidationOperator enum
const { ValidationOperator } = UIEnums;
return Controller.extend("your.apps.namespace.YourController", {
onInit: function () {
},
onCreateProduct: async function () {
const entry = new EntryCreateCL(this, "Products");
// Create an object from the Validation Logic class for the price validation
const priceValidation = new ValidationLogicCL({
propertyName: "price", // price property of the Products
operator: ValidationOperator.BT,
value1: 1500,
value2: 2500,
message: "The price must be between 1500 and 2500",
invalidValueMessage: "Please only type number for the price field"
});
// Create an object from the Validation Logic class for the currency validation
const currencyValidation = new ValidationLogicCL({
propertyName: "currency", // Currency property of the Products
operator: ValidationOperator.EQ,
value1: "EUR",
message: "Only EUR currency can be used"
});
// Add the price validation object
entry.addValidationLogic(priceValidation);
// Add the currency validation object
entry.addValidationLogic(currencyValidation);
entry.createNewEntry();
}
});
});
Validation Failed | Invalid Value |
---|---|
If the validation logic is more complex than simply checking specific values, a custom function can be used for the validation.
The function that will be used for the validation must have a parameter to retrieve the value entered by the end user. UI5 Antares passes the user's input or the Custom Control to the validator function as a parameter.
Important: The value can be of the following types: string, number, boolean, Date, UI5 Date, or Control.
Important: If the validator function is utilized for the purpose of validating a Custom Control, the type of the parameter will be the control that is added. To illustrate, if a sap.m.ComboBox is added as a custom control, the sap.m.ComboBox class object will be passed back to the validator function.
Important: Please note that for auto-generated form elements, the value can only be one of the following types: string, number, boolean, Date, or UI5 Date
The validator function should return a boolean value indicating whether the validation was successful or not.
Return Value | Description |
---|---|
true | Validation is successful |
false | Validation is not successful |
TypeScript
import Controller from "sap/ui/core/mvc/Controller";
import EntryCreateCL from "ui5/antares/entry/v2/EntryCreateCL"; // Import the class
import ValidationLogicCL from "ui5/antares/ui/ValidationLogicCL"; // Import the ValidationLogicCL class
import { ValidatorValueParameter } from "ui5/antares/types/ui/validation"; // Import the validator function parameter type
/**
* @namespace your.apps.namespace
*/
export default class YourController extends Controller {
public onInit() {
}
public async onCreateProduct() {
const entry = new EntryCreateCL<IProducts>(this, "Products");
// Create an object from the Validation Logic class for the currency validation
const currencyValidation = new ValidationLogicCL({
propertyName: "currency", // Currency property of the Products
validator: this.validateCurrency,
listener: this,
message: "Only EUR currency can be used"
});
// Add the currency validation object
entry.addValidationLogic(currencyValidation);
entry.createNewEntry();
}
public validateCurrency(value: ValidatorValueParameter): boolean {
// Here you can write your own validation logic
if ((value as string) !== "EUR") {
return false; // Validation is not successful
}
return true; // Validation is successful
}
}
interface IProducts {
ID: string;
name: string;
description: string;
brand: string;
price: number;
currency: string;
quantityInStock: number;
categoryID: string;
supplierID: string;
}
JavaScript
sap.ui.define([
"sap/ui/core/mvc/Controller",
"ui5/antares/entry/v2/EntryCreateCL", // Import the class
"ui5/antares/ui/ValidationLogicCL" // Import the ValidationLogicCL class
],
/**
* @param {typeof sap.ui.core.mvc.Controller} Controller
*/
function (Controller, EntryCreateCL, ValidationLogicCL) {
"use strict";
return Controller.extend("your.apps.namespace.YourController", {
onInit: function () {
},
onCreateProduct: async function () {
const entry = new EntryCreateCL(this, "Products");
// Create an object from the Validation Logic class for the currency validation
const currencyValidation = new ValidationLogicCL({
propertyName: "currency", // Currency property of the Products
validator: this._validateCurrency,
listener: this,
message: "Only EUR currency can be used"
});
// Add the currency validation object
entry.addValidationLogic(currencyValidation);
entry.createNewEntry();
},
_validateCurrency: function (value) {
// Here you can write your own validation logic
if (value !== "EUR") {
return false; // Validation is not successful
}
return true; // Validation is successful
}
});
});
Name | Description |
---|---|
ValidationOperator.BT | Between. Boundries are included |
ValidationOperator.Contains | Contains. It can only be used with string type |
ValidationOperator.EndsWith | Ends with. It can only be used with string type |
ValidationOperator.EQ | Equals |
ValidationOperator.GE | Greater than or equals |
ValidationOperator.GT | Greater than |
ValidationOperator.LE | Little than or equals |
ValidationOperator.LT | Little than |
ValidationOperator.NB | Not between. Boundries are included |
ValidationOperator.NE | Not equals |
ValidationOperator.NotContains | Not contains. It can only be used with string type |
ValidationOperator.NotEndsWith | Not ends with. It can only be used with string type |
ValidationOperator.NotStartsWith | Not starts with. It can only be used with string type |
ValidationOperator.StartsWith | Starts with. It can only be used with string type |
By default, the createNewEntry() method generates a sap.m.Dialog Simple Form or Smart Form content, with the configurations done using the public methods. However, there may be a need for a larger screen for some of the reasons listed below.
- The
EntitySet
may have many properties that are not user friendly when displayed in a dialog. - The custom content may not fit in the dialog.
In such cases, UI5 Antares has the capability to generate an sap.uxap.ObjectPageLayout instead of a sap.m.Dialog.
Hint: All features of a dialog generation process are also available for the object page generation process.
By default, Entry classes generates an object page with a single section including all the properties of an EntitySet
. The default title for this section is derived from the Form Title. To change the title of this section, please use the setDefaultGroupTitle() method.
Important: Please be aware that any custom content added using the addCustomContent() or addContentFromFragment() methods will be added to a separate section with a default title. The default title for the custom content is Custom Contents, but this can be modified using the setCustomContentSectionTitle() method.
To generate an object page for the EntitySet
, the setDisplayObjectPage() method can be utilized. The second parameter of this method is the target name of the current view. This information is required by the library to return the end user back to the view where the object page was called. The target information can be obtained from the application's manifest.json file. To find the target name of the current page, please look into the "sap.ui5"."routing"."targets" section in the manifest.json file.
IMPORTANT: The object page generation is only available when the SAPUI5 application has a router initialized in the UI Component (Component.js). UI5 Antares, uses the router of the application and does not initialize a new router instance.
Important: UI5 Antares does not change the hash when displaying the generated object page. Instead, a new target named UI5AntaresObjectPageTarget is added using the application's router. Then, the created target is displayed on the fly.
The target name is MyTarget in the sample of the manifest.json file provided below.
{
"sap.app": {
...
},
"sap.ui": {
...
},
"sap.ui5": {
...
"routing": {
"config": {
...
},
"routes": [
...
],
"targets": {
"MyTarget": {
"viewType": "XML",
"transition": "slide",
"clearControlAggregation": "true",
"viewId": "MyViewId",
"viewName": "MyViewName"
},
...
}
}
}
}
Setter (setDisplayObjectPage)
Parameter | Type | Mandatory | Description |
---|---|---|---|
display | boolean | Yes | If set to true, the library will generate an object page instead of a dialog |
fromTarget | string | Yes | The target name of the view to where the end user should return after finishing the process on the generated object page |
Returns | Description |
---|---|
void |
Getter (getDisplayObjectPage)
Returns | Description |
---|---|
boolean | Returns all the value that was set using setDisplayObjectPage() method. Default value is false |
Sample
Let us consider an EntitySet
named Products and we wish to have an object page instead of a dialog for the creation process.
TypeScript
import Controller from "sap/ui/core/mvc/Controller";
import EntryCreateCL from "ui5/antares/entry/v2/EntryCreateCL"; // Import the class
/**
* @namespace your.apps.namespace
*/
export default class YourController extends Controller {
public onInit() {
}
public onCreateProduct() {
// initialize
const entry = new EntryCreateCL<IProducts>(this, "Products");
// set the default section title
entry.setDefaultGroupTitle("My Default Section");
// activate the object page with the target
entry.setDisplayObjectPage(true, "MyCurrentViewTarget");
// call the object page
entry.createNewEntry();
}
}
interface IProducts {
ID: string;
name: string;
description: string;
brand: string;
price: number;
currency: string;
quantityInStock: number;
categoryID: string;
supplierID: string;
}
JavaScript
sap.ui.define([
"sap/ui/core/mvc/Controller",
"ui5/antares/entry/v2/EntryCreateCL" // Import the class
],
/**
* @param {typeof sap.ui.core.mvc.Controller} Controller
*/
function (Controller, EntryCreateCL) {
"use strict";
return Controller.extend("your.apps.namespace.YourController", {
onInit: function () {
},
onCreateProduct: async function () {
// initialize
const entry = new EntryCreateCL(this, "Products");
// set the default section title
entry.setDefaultGroupTitle("My Default Section");
// activate the object page with the target
entry.setDisplayObjectPage(true, "MyCurrentViewTarget");
// call the object page
entry.createNewEntry();
}
});
});
The generated object page with the default values will look more or less like the following.
To add sections to the generated object page, Form Grouping feature can be utilized.
The title in the generated object page is derived from the Form Title feature.
The label which is displayed on the right side of the sap.m.Avatar can be modified using the setObjectPageHeaderLabel() method. The default values for the header label are listed below.
Default Values
Class | Default Value |
---|---|
Entry Create | You can create a new ${this.entityName} on this page. |
Entry Update | You can update ${this.entityName} on this page. |
Entry Delete | You can delete ${this.entityName} on this page. |
Entry Read | You can display ${this.entityName} on this page. |
Setter (setObjectPageHeaderLabel)
Parameter | Type | Mandatory | Description |
---|---|---|---|
label | string | Yes | The label which is displayed on the right side of the sap.m.Avatar |
Returns | Description |
---|---|
void |
Getter (getObjectPageHeaderLabel)
Returns | Description |
---|---|
boolean | Returns all the value that was set using setObjectPageHeaderLabel() method. Default value differs based on the Entry class |
TypeScript
import Controller from "sap/ui/core/mvc/Controller";
import EntryCreateCL from "ui5/antares/entry/v2/EntryCreateCL"; // Import the class
/**
* @namespace your.apps.namespace
*/
export default class YourController extends Controller {
public onInit() {
}
public onCreateProduct() {
// initialize
const entry = new EntryCreateCL<IProducts>(this, "Products");
// set the header title
entry.setFormTitle("My Header Title");
// set the default section title
entry.setDefaultGroupTitle("My Default Section");
// set the header label
entry.setObjectPageHeaderLabel("My Header Label");
// activate the object page with the target
entry.setDisplayObjectPage(true, "MyCurrentViewTarget");
// call the object page
entry.createNewEntry();
}
}
interface IProducts {
ID: string;
name: string;
description: string;
brand: string;
price: number;
currency: string;
quantityInStock: number;
categoryID: string;
supplierID: string;
}
JavaScript
sap.ui.define([
"sap/ui/core/mvc/Controller",
"ui5/antares/entry/v2/EntryCreateCL" // Import the class
],
/**
* @param {typeof sap.ui.core.mvc.Controller} Controller
*/
function (Controller, EntryCreateCL) {
"use strict";
return Controller.extend("your.apps.namespace.YourController", {
onInit: function () {
},
onCreateProduct: async function () {
// initialize
const entry = new EntryCreateCL(this, "Products");
// set the header title
entry.setFormTitle("My Header Title");
// set the default section title
entry.setDefaultGroupTitle("My Default Section");
// set the header label
entry.setObjectPageHeaderLabel("My Header Label");
// activate the object page with the target
entry.setDisplayObjectPage(true, "MyCurrentViewTarget");
// call the object page
entry.createNewEntry();
}
});
});
To change the src of the sap.m.Avatar displayed in the object page, the setObjectPageAvatarSrc() method can be utilized. The default values for the avatar are listed below.
Default Values
Class | Default Value |
---|---|
Entry Create | sap-icon://add |
Entry Update | sap-icon://edit |
Entry Delete | sap-icon://delete |
Entry Read | sap-icon://display |
Setter (setObjectPageAvatarSrc)
Parameter | Type | Mandatory | Description |
---|---|---|---|
src | string | Yes | The src attribute of the sap.m.Avatar |
Returns | Description |
---|---|
void |
Getter (getObjectPageAvatarSrc)
Returns | Description |
---|---|
string | Returns all the value that was set using setObjectPageAvatarSrc() method. Default value differs based on the Entry class |
TypeScript
import Controller from "sap/ui/core/mvc/Controller";
import EntryCreateCL from "ui5/antares/entry/v2/EntryCreateCL"; // Import the class
/**
* @namespace your.apps.namespace
*/
export default class YourController extends Controller {
public onInit() {
}
public onCreateProduct() {
// initialize
const entry = new EntryCreateCL<IProducts>(this, "Products");
// set the avatar src
entry.setObjectPageAvatarSrc("https://upload.wikimedia.org/wikipedia/commons/thumb/c/c1/Google_%22G%22_logo.svg/1024px-Google_%22G%22_logo.svg.png");
// call the object page
entry.createNewEntry();
}
}
interface IProducts {
ID: string;
name: string;
description: string;
brand: string;
price: number;
currency: string;
quantityInStock: number;
categoryID: string;
supplierID: string;
}
JavaScript
sap.ui.define([
"sap/ui/core/mvc/Controller",
"ui5/antares/entry/v2/EntryCreateCL" // Import the class
],
/**
* @param {typeof sap.ui.core.mvc.Controller} Controller
*/
function (Controller, EntryCreateCL) {
"use strict";
return Controller.extend("your.apps.namespace.YourController", {
onInit: function () {
},
onCreateProduct: async function () {
// initialize
const entry = new EntryCreateCL(this, "Products");
// set the avatar src
entry.setObjectPageAvatarSrc("https://upload.wikimedia.org/wikipedia/commons/thumb/c/c1/Google_%22G%22_logo.svg/1024px-Google_%22G%22_logo.svg.png");
// call the object page
entry.createNewEntry();
}
});
});
To change the default title for the custom contents in the generated object page, the setCustomContentSectionTitle() method can be utilized.
Setter (setCustomContentSectionTitle)
Parameter | Type | Mandatory | Description |
---|---|---|---|
title | string | Yes | The title of the section that is generated for the custom contents |
Returns | Description |
---|---|
void |
Getter (getCustomContentSectionTitle)
Returns | Description |
---|---|
string | Returns all the value that was set using setCustomContentSectionTitle() method. Default value is Custom Contents |
By default, UI5 Antares creates sap.ui.comp.smartfield.SmartField when the form type is SMART or sap.m.Input, sap.m.DatePicker, sap.m.DateTimePicker, sap.m.CheckBox depending on the Edm Type
of the properties when the form type is SIMPLE.
The Custom Control class enables the addition of various UI controls (e.g., sap.m.Slider) to the properties of the EntityType
of the EntitySet
, as defined in the constructor.
Important: Please note that a custom control can only be added for the properties of an
EntitySet
that have been defined in the constructor.
When generating the form, UI5 Antares first checks to see if there is a corresponding custom control for the property. If one is found, it is added to the form. Otherwise, another UI Control will be generated.
You must initialize an object from CustomControlCL in order to use it.
Parameter | Type | Mandatory | Default Value | Description |
---|---|---|---|---|
control | Control | Yes | The UI Control to add into the auto-generated form | |
propertyName | string | Yes | The property of the entity set in the constructor for which the custom control be added | |
validator? | ValidationLogicCL | No | The validation object |
Sample
Let us consider an EntitySet
named Products with the following properties: ID
, name
, description
, price
, and currency
. We wish to add a sap.m.ComboBox with some predefined items for the currency
property.
TypeScript
import Controller from "sap/ui/core/mvc/Controller";
import EntryCreateCL from "ui5/antares/entry/v2/EntryCreateCL"; // Import the class
import CustomControlCL from "ui5/antares/ui/CustomControlCL"; // Import the Custom Control Class
import ComboBox from "sap/m/ComboBox"; // Import the ComboBox
import Item from "sap/ui/core/Item"; // Import the Item for ComboBox items
/**
* @namespace your.apps.namespace
*/
export default class YourController extends Controller {
public onInit() {
}
public async onCreateProduct() {
const entry = new EntryCreateCL<IProducts>(this, "Products");
// Create a custom control which is ComboBox in this sample
const currencyComboBox = new ComboBox({
selectedKey: "{currency}", // Do not forget to add the path of the property
items: [
new Item({ key: "EUR", text: "Euro" }),
new Item({ key: "USD", text: "US Dollar" }),
new Item({ key: "TRY", text: "Turkish Lira" }),
]
});
// Create an object from the CustomControlCL class with the UI Control and property name
const currencyControl = new CustomControlCL(currencyComboBox, "currency");
// Add the custom control
entry.addCustomControl(currencyControl);
entry.createNewEntry();
}
}
interface IProducts {
ID: string;
name: string;
description: string;
brand: string;
price: number;
currency: string;
quantityInStock: number;
categoryID: string;
supplierID: string;
}
JavaScript
sap.ui.define([
"sap/ui/core/mvc/Controller",
"ui5/antares/entry/v2/EntryCreateCL", // Import the class
"ui5/antares/ui/CustomControlCL", // Import the Custom Control Class
"sap/m/ComboBox", // Import the ComboBox
"sap/ui/core/Item" // Import the Item for ComboBox items
],
/**
* @param {typeof sap.ui.core.mvc.Controller} Controller
*/
function (Controller, EntryCreateCL, CustomControlCL, ComboBox, Item) {
"use strict";
return Controller.extend("your.apps.namespace.YourController", {
onInit: function () {
},
onCreateProduct: async function () {
const entry = new EntryCreateCL(this, "Products");
// Create a custom control which is ComboBox in this sample
const currencyComboBox = new ComboBox({
selectedKey: "{currency}", // Do not forget to add the path of the property
items: [
new Item({ key: "EUR", text: "Euro" }),
new Item({ key: "USD", text: "US Dollar" }),
new Item({ key: "TRY", text: "Turkish Lira" }),
]
});
// Create an object from the CustomControlCL class with the UI Control and property name
const currencyControl = new CustomControlCL(currencyComboBox, "currency");
// Add the custom control
entry.addCustomControl(currencyControl);
entry.createNewEntry();
}
});
});
Furthermore, the custom controls can be configured to execute a Validation Logic before the transient entity is submitted.
Important: Since the custom UI control added to the form cannot be predicted by the library, validation and mandatory check can only be performed using the Validator Function.
UI5 Antares, passes the custom UI control as a parameter to the validator function.
Sample
Let us consider an EntitySet
named Products with the following properties: ID
, name
, description
, price
, and currency
. We wish to add a sap.m.ComboBox with some predefined items for the currency
property.
We also want to validate that the end user cannot leave the currency
field blank, but must make a selection.
TypeScript
import Controller from "sap/ui/core/mvc/Controller";
import EntryCreateCL from "ui5/antares/entry/v2/EntryCreateCL"; // Import the class
import CustomControlCL from "ui5/antares/ui/CustomControlCL"; // Import the Custom Control Class
import ValidationLogicCL from "ui5/antares/ui/ValidationLogicCL"; // Import the ValidationLogicCL class
import { ValidatorValueParameter } from "ui5/antares/types/ui/validation"; // Import the validator function parameter type
import ComboBox from "sap/m/ComboBox"; // Import the ComboBox
import Item from "sap/ui/core/Item"; // Import the Item for ComboBox items
/**
* @namespace your.apps.namespace
*/
export default class YourController extends Controller {
public onInit() {
}
public async onCreateProduct() {
const entry = new EntryCreateCL<IProducts>(this, "Products");
// Create a custom control which is ComboBox in this sample
const currencyComboBox = new ComboBox({
selectedKey: "{currency}", // Do not forget to add the path of the property
items: [
new Item({ key: "EUR", text: "Euro" }),
new Item({ key: "USD", text: "US Dollar" }),
new Item({ key: "TRY", text: "Turkish Lira" }),
]
});
// Create the validation object for the custom control
const currencyValidation = new ValidationLogicCL({
propertyName: "currency", // Currency property of the Products
validator: this.validateCurrency,
listener: this,
message: "The currency field is mandatory"
});
// Create an object from the CustomControlCL class with the UI Control, property name and validation object
const currencyControl = new CustomControlCL(currencyComboBox, "currency", currencyValidation);
// Add the custom control
entry.addCustomControl(currencyControl);
entry.createNewEntry();
}
// UI5 Antares will pass the added combobox back to the validator function
public validateCurrency (control: ValidatorValueParameter): boolean {
if (!(control as ComboBox).getSelectedKey()) {
return false; // Validation is unsuccessful
}
return true; // Validation is successful
}
}
interface IProducts {
ID: string;
name: string;
description: string;
brand: string;
price: number;
currency: string;
quantityInStock: number;
categoryID: string;
supplierID: string;
}
JavaScript
sap.ui.define([
"sap/ui/core/mvc/Controller",
"ui5/antares/entry/v2/EntryCreateCL", // Import the class
"ui5/antares/ui/CustomControlCL", // Import the Custom Control Class
"ui5/antares/ui/ValidationLogicCL", // Import the ValidationLogicCL class
"sap/m/ComboBox", // Import the ComboBox
"sap/ui/core/Item" // Import the Item for ComboBox items
],
/**
* @param {typeof sap.ui.core.mvc.Controller} Controller
*/
function (Controller, EntryCreateCL, CustomControlCL, ValidationLogicCL, ComboBox, Item) {
"use strict";
return Controller.extend("your.apps.namespace.YourController", {
onInit: function () {
},
onCreateProduct: async function () {
const entry = new EntryCreateCL(this, "Products");
// Create a custom control which is ComboBox in this sample
const currencyComboBox = new ComboBox({
selectedKey: "{currency}", // Do not forget to add the path of the property
items: [
new Item({ key: "EUR", text: "Euro" }),
new Item({ key: "USD", text: "US Dollar" }),
new Item({ key: "TRY", text: "Turkish Lira" }),
]
});
// Create the validation object for the custom control
const currencyValidation = new ValidationLogicCL({
propertyName: "currency", // Currency property of the Products
validator: this._validateCurrency,
listener: this,
message: "The currency field is mandatory"
});
// Create an object from the CustomControlCL class with the UI Control, property name and validation object
const currencyControl = new CustomControlCL(currencyComboBox, "currency", currencyValidation);
// Add the custom control
entry.addCustomControl(currencyControl);
entry.createNewEntry();
},
// UI5 Antares will pass the added combobox back to the validator function
_validateCurrency: function (control) {
if (!control.getSelectedKey()) {
return false; // Validation is unsuccessful
}
return true; // Validation is successful
}
});
});
Another way to add custom controls to the auto-generated form is to load the UI controls from a custom fragment created in the application files.
Advantage: It's possible to add multiple controls at once with this approach. It also avoids having to create UI controls in the controller. The custom controls can be organized in the
.fragment.xml
files.
Important: It is mandatory to add a custom data with UI5AntaresEntityPropertyName key to the each UI control in the fragment. The value of the UI5AntaresEntityPropertyName key should be the property name that the control is added for. Otherwise, UI5 Antares will be unable to understand for which property the UI control will be added.
Sample
Let us consider an EntitySet
named Products with the following properties: ID
, name
, description
, price
, and currency
. We wish to add a sap.m.ComboBox with some predefined items for the currency
property and a sap.m.Slider for the price
property.
Firstly, a file with .fragment.xml
extension should be created in the application files. The UI controls will be placed into this file.
<core:FragmentDefinition
xmlns="sap.m"
xmlns:core="sap.ui.core"
xmlns:app="http://schemas.sap.com/sapui5/extension/sap.ui.core.CustomData/1"
>
<ComboBox
app:UI5AntaresEntityPropertyName="currency"
selectedKey="{currency}"
>
<items>
<core:Item
key="EUR"
text="Euro"
/>
<core:Item
key="USD"
text="US Dollar"
/>
<core:Item
key="TRY"
text="Turkish Lira"
/>
</items>
</ComboBox>
<Slider
app:UI5AntaresEntityPropertyName="price"
width="100%"
min="1000"
max="100000"
showAdvancedTooltip="true"
showHandleTooltip="true"
inputsAsTooltips="true"
enableTickmarks="true"
step="1000"
class="sapUiMediumMarginBottom"
value="{price}"
/>
</core:FragmentDefinition>
Secondly, an object from the FragmentCL should be instantiated with the controller and fragment path parameters.
Information: Please be aware that addControlFromFragment() function is asynchronous and must be awaited.
TypeScript
import Controller from "sap/ui/core/mvc/Controller";
import EntryCreateCL from "ui5/antares/entry/v2/EntryCreateCL"; // Import the class
import FragmentCL from "ui5/antares/ui/FragmentCL"; // Import the Fragment class
/**
* @namespace your.apps.namespace
*/
export default class YourController extends Controller {
public onInit() {
}
public async onCreateProduct() {
const entry = new EntryCreateCL<IProducts>(this, "Products");
// Create an object from the FragmentCL class with the controller and fragment path parameters.
const fragment = new FragmentCL(this, "your.apps.namespace.path.to.FragmentFileName");
// Add the controls from the fragment. It is an asynchronous method and must be awaited.
await entry.addControlFromFragment(fragment);
entry.createNewEntry();
}
}
interface IProducts {
ID: string;
name: string;
description: string;
brand: string;
price: number;
currency: string;
quantityInStock: number;
categoryID: string;
supplierID: string;
}
JavaScript
sap.ui.define([
"sap/ui/core/mvc/Controller",
"ui5/antares/entry/v2/EntryCreateCL", // Import the class
"ui5/antares/ui/FragmentCL" // Import the Fragment class
],
/**
* @param {typeof sap.ui.core.mvc.Controller} Controller
*/
function (Controller, EntryCreateCL, FragmentCL) {
"use strict";
return Controller.extend("your.apps.namespace.YourController", {
onInit: function () {
},
onCreateProduct: async function () {
const entry = new EntryCreateCL(this, "Products");
// Create an object from the FragmentCL class with the controller and fragment path parameters.
const fragment = new FragmentCL(this, "your.apps.namespace.path.to.FragmentFileName");
// Add the controls from the fragment. It is an asynchronous method and must be awaited.
await entry.addControlFromFragment(fragment);
entry.createNewEntry();
}
});
});
Furthermore, the custom controls loaded from a fragment can be configured to execute a Validation Logic before the transient entity is submitted.
Important: Since the custom UI control added to the form cannot be predicted by the library, validation and mandatory check can only be performed using the Validator Function.
UI5 Antares, passes the custom UI control as a parameter to the validator function.
To implement validation logic for controls loaded from a fragment, a custom data with the UI5AntaresValidationLogic key must be added to the control. The value of the UI5AntaresValidationLogic key should be the name of the validator function in the controller.
Additionally, the default message displayed by the end user when the validation fails can be modified by setting a custom data with the key UI5AntaresValidationMessage. The value of the UI5AntaresValidationMessage can be either the message itself or the i18n binding.
Sample
Let us consider an EntitySet
named Products with the following properties: ID
, name
, description
, price
, and currency
. We wish to add a sap.m.ComboBox with some predefined items for the currency
property and a sap.m.Slider for the price
property Furthermore, we would like to include a validation and validation messages.
Firstly, a file with .fragment.xml
extension should be created in the application files. The UI controls will be placed into this file.
<core:FragmentDefinition
xmlns="sap.m"
xmlns:core="sap.ui.core"
xmlns:app="http://schemas.sap.com/sapui5/extension/sap.ui.core.CustomData/1"
>
<ComboBox
app:UI5AntaresEntityPropertyName="currency"
app:UI5AntaresValidationLogic="onValidateCurrency"
app:UI5AntaresValidationMessage="{i18n>currencyValidationFailed}"
selectedKey="{currency}"
>
<items>
<core:Item
key="EUR"
text="Euro"
/>
<core:Item
key="USD"
text="US Dollar"
/>
<core:Item
key="TRY"
text="Turkish Lira"
/>
</items>
</ComboBox>
<Slider
app:UI5AntaresEntityPropertyName="price"
app:UI5AntaresValidationLogic="onValidatePrice"
app:UI5AntaresValidationMessage="The price must be bigger than 15000"
width="100%"
min="1000"
max="100000"
showAdvancedTooltip="true"
showHandleTooltip="true"
inputsAsTooltips="true"
enableTickmarks="true"
step="1000"
class="sapUiMediumMarginBottom"
value="{price}"
/>
</core:FragmentDefinition>
Secondly, an object from the FragmentCL should be instantiated with the controller and fragment path parameters.
Information: Please be aware that addControlFromFragment() function is asynchronous and must be awaited.
TypeScript
import Controller from "sap/ui/core/mvc/Controller";
import EntryCreateCL from "ui5/antares/entry/v2/EntryCreateCL"; // Import the class
import FragmentCL from "ui5/antares/ui/FragmentCL"; // Import the Fragment class
import { ValidatorValueParameter } from "ui5/antares/types/ui/validation"; // Import the validator function parameter type
import ComboBox from "sap/m/ComboBox";
import Slider from "sap/m/Slider";
/**
* @namespace your.apps.namespace
*/
export default class YourController extends Controller {
public onInit() {
}
public async onCreateProduct() {
const entry = new EntryCreateCL<IProducts>(this, "Products");
// Create an object from the FragmentCL class with the controller and fragment path parameters.
const fragment = new FragmentCL(this, "your.apps.namespace.path.to.FragmentFileName");
// Add the controls from the fragment. It is an asynchronous method and must be awaited.
await entry.addControlFromFragment(fragment);
entry.createNewEntry();
}
// The name of the validator function must match to the custom data UI5AntaresValidationLogic defined in the .fragment.xml file
public onValidateCurrency (control: ValidatorValueParameter): boolean {
if (!(control as ComboBox).getSelectedKey()) {
return false; // Validation is unsuccessful
}
return true; // Validation is successful
}
// The name of the validator function must match to the custom data UI5AntaresValidationLogic defined in the .fragment.xml file
public onValidatePrice (control: ValidatorValueParameter): boolean {
if ((control as Slider).getValue() <= 15000) {
return false; // Validation is unsuccessful
}
return true; // Validation is successful
}
}
interface IProducts {
ID: string;
name: string;
description: string;
brand: string;
price: number;
currency: string;
quantityInStock: number;
categoryID: string;
supplierID: string;
}
JavaScript
sap.ui.define([
"sap/ui/core/mvc/Controller",
"ui5/antares/entry/v2/EntryCreateCL", // Import the class
"ui5/antares/ui/FragmentCL" // Import the Fragment class
],
/**
* @param {typeof sap.ui.core.mvc.Controller} Controller
*/
function (Controller, EntryCreateCL, FragmentCL) {
"use strict";
return Controller.extend("your.apps.namespace.YourController", {
onInit: function () {
},
onCreateProduct: async function () {
const entry = new EntryCreateCL(this, "Products");
// Create an object from the FragmentCL class with the controller and fragment path parameters.
const fragment = new FragmentCL(this, "your.apps.namespace.path.to.FragmentFileName");
// Add the controls from the fragment. It is an asynchronous method and must be awaited.
await entry.addControlFromFragment(fragment);
entry.createNewEntry();
},
// The name of the validator function must match to the custom data UI5AntaresValidationLogic defined in the .fragment.xml file
onValidateCurrency: function (control) {
if (!control.getSelectedKey()) {
return false; // Validation is unsuccessful
}
return true; // Validation is successful
},
// The name of the validator function must match to the custom data UI5AntaresValidationLogic defined in the .fragment.xml file
onValidatePrice: function (control) {
if (control.getValue() <= 15000) {
return false; // Validation is unsuccessful
}
return true; // Validation is successful
}
});
});
It is possible to add any UI control to the dialog below the auto-generated form. The distinction between Custom Control and Custom Content is that the custom control can only be added for the properties of the EntitySet
specified in the constructor, whereas the custom content is a UI control that is required on the dialog but is not included in the transient entity.
Important: Custom contents are not included into the Validation Logic process. The UI5 Antares is designed just to add custom contents to the dialog. However, it is important to note that the custom content must be managed manually.
For example, a custom content could be a sap.m.Image, sap.m.upload.UploadSet, or any other UI control that is required on the dialog.
To add a custom content to the dialog, addCustomContent() method can be utilized.
Setter (addCustomContent)
Parameter | Type | Mandatory | Description |
---|---|---|---|
content | Control | Yes | The UI control to add into the dialog |
Returns | Description |
---|---|
void |
Getter (getCustomContents)
Returns | Description |
---|---|
Control[] | Returns all the UI controls that were added using addCustomContent() method. Default value is [] |
Sample
Let us consider an EntitySet
named Products and we wish to add an sap.m.upload.UploadSet to the dialog that UI5 Antares will generate.
TypeScript
import Controller from "sap/ui/core/mvc/Controller";
import EntryCreateCL from "ui5/antares/entry/v2/EntryCreateCL"; // Import the class
import UploadSet from "sap/m/upload/UploadSet"; // Import the Upload Set
/**
* @namespace your.apps.namespace
*/
export default class YourController extends Controller {
public onInit() {
}
public async onCreateProduct() {
const entry = new EntryCreateCL(this, "Products");
// Create the custom content
const upload = new UploadSet();
upload.addStyleClass("sapUiSmallMargin");
// Add the custom content
entry.addCustomContent(upload);
entry.createNewEntry();
}
}
JavaScript
sap.ui.define([
"sap/ui/core/mvc/Controller",
"ui5/antares/entry/v2/EntryCreateCL", // Import the class
"sap/m/upload/UploadSet" // Import the Upload Set
],
/**
* @param {typeof sap.ui.core.mvc.Controller} Controller
*/
function (Controller, EntryCreateCL, UploadSet) {
"use strict";
return Controller.extend("your.apps.namespace.YourController", {
onInit: function () {
},
onCreateProduct: async function () {
const entry = new EntryCreateCL(this, "Products");
// Create the custom content
const upload = new UploadSet();
upload.addStyleClass("sapUiSmallMargin");
// Add the custom content
entry.addCustomContent(upload);
entry.createNewEntry();
}
});
});
Another way to add custom contents to the dialog is to load the UI controls from a custom fragment created in the application files.
Advantage: It's possible to add multiple contents at once with this approach. It also avoids having to create UI controls in the controller. The custom contents can be organized in the
.fragment.xml
files.
Sample
Let us consider an EntitySet
named Products and we wish to add an sap.m.Image and an sap.m.RadioButtonGroup loaded from a fragment to the dialog that UI5 Antares will generate.
Firstly, a file with .fragment.xml
extension should be created in the application files. The UI controls will be placed into this file.
<core:FragmentDefinition
xmlns="sap.m"
xmlns:core="sap.ui.core"
>
<VBox>
<FlexBox justifyContent="Center">
<Image
class="sapUiSmallMargin"
src="./img/antares.jpg"
width="10rem"
/>
</FlexBox>
<RadioButtonGroup selectedIndex="0">
<buttons>
<RadioButton text="Option 1" />
<RadioButton text="Option 2" />
<RadioButton text="Option 3" />
</buttons>
</RadioButtonGroup>
</VBox>
</core:FragmentDefinition>
Secondly, an object from the FragmentCL should be instantiated with the controller and fragment path parameters.
Information: Please be aware that addContentFromFragment() function is asynchronous and must be awaited.
TypeScript
import Controller from "sap/ui/core/mvc/Controller";
import EntryCreateCL from "ui5/antares/entry/v2/EntryCreateCL"; // Import the class
import FragmentCL from "ui5/antares/ui/FragmentCL"; // Import the Fragment class
/**
* @namespace your.apps.namespace
*/
export default class YourController extends Controller {
public onInit() {
}
public async onCreateProduct() {
const entry = new EntryCreateCL<IProducts>(this, "Products");
// Create an object from the FragmentCL class with the controller and fragment path parameters.
const fragment = new FragmentCL(this, "your.apps.namespace.path.to.FragmentFileName");
// Add the controls from the fragment. It is an asynchronous method and must be awaited.
await entry.addContentFromFragment(fragment);
entry.createNewEntry();
}
}
interface IProducts {
ID: string;
name: string;
description: string;
brand: string;
price: number;
currency: string;
quantityInStock: number;
categoryID: string;
supplierID: string;
}
JavaScript
sap.ui.define([
"sap/ui/core/mvc/Controller",
"ui5/antares/entry/v2/EntryCreateCL", // Import the class
"ui5/antares/ui/FragmentCL" // Import the Fragment class
],
/**
* @param {typeof sap.ui.core.mvc.Controller} Controller
*/
function (Controller, EntryCreateCL, FragmentCL) {
"use strict";
return Controller.extend("your.apps.namespace.YourController", {
onInit: function () {
},
onCreateProduct: async function () {
const entry = new EntryCreateCL(this, "Products");
// Create an object from the FragmentCL class with the controller and fragment path parameters.
const fragment = new FragmentCL(this, "your.apps.namespace.path.to.FragmentFileName");
// Add the controls from the fragment. It is an asynchronous method and must be awaited.
await entry.addContentFromFragment(fragment);
entry.createNewEntry();
}
});
});
If you prefer not to have the library generate a form and content, you may also use your own fragment and dialog with any content you desire. UI5 Antares will create a transient entity and open the dialog loaded from your fragment. Additionally, the transient entity will be bound to the dialog.
Please be aware that there are some manual steps that must be taken when using a custom fragment.
- Entry Create class provides a public method named submit() which must be called manually to submit the transient entity.
- Entry Create class provides a public method named reset() that must be called in the event that the transient entity will not be submitted and the dialog is closed and destroyed.
Information: The submit(resetAllOnFail:boolean = false) method accepts an optional parameter with a default value of false. This parameter indicates whether all transient entities in the OData V2 Model should be reset or only the current context. If you wish to reset all transient entities, please set this parameter to true. If you only wish to reset the current transient entity, there is no need to set this parameter.
Important: Please be advised that the fragment to be loaded must contain a sap.m.Dialog and that all UI controls must be placed as the content of the dialog.
Important: It should be noted that only a limited number of features of the UI5 Antares can be utilized with a custom fragment.
Supported Features
Feature | Description |
---|---|
Mandatory Properties | By default, UI5 Antares performs a mandatory check for the properties with Nullable="false" attribute and the properties defined using setMandatoryProperties() method. However, this feature can be deactived using setAutoMandatoryCheck() method |
Mandatory Error Message | The default message that is displayed when the mandatory check fails can be modified |
Attach Submit Completed | It is possible to create a function that will be called after the transient entity has been submitted successfully |
Attach Submit Failed | It is possible to create a function that will be called if the transient entity submission fails |
Properties with Edm.Guid Type | By default, UI5 Antares generates random UUID for the key properties with Edm.Guid type |
To use a custom fragment, setFragmentPath() method can be utilized.
Setter (setFragmentPath)
Parameter | Type | Mandatory | Description |
---|---|---|---|
fragmentPath | string | Yes | The path of the fragment that will be loaded by the library |
containsSmartForm? | boolean | No | It should be set to true if the dialog contains a Smart Form |
Returns | Description |
---|---|
void |
Getter (getFragmentPath)
Returns | Description |
---|---|
string | undefined | Returns all the fragment path that was set using getFragmentPath() method. Default value is undefined |
Sample
Let us consider an EntitySet
named Products and we wish to create a custom fragment instead of having the library generate a form.
Firstly, a file with .fragment.xml
extension should be created in the application files. The UI controls will be placed into this file.
<core:FragmentDefinition
xmlns:form="sap.ui.layout.form"
xmlns="sap.m"
xmlns:core="sap.ui.core"
>
<Dialog title="Create New Product">
<form:SimpleForm>
<form:content>
<Label text="Product ID" />
<MaskInput
mask="CCCCCCCC-CCCC-CCCC-CCCC-CCCCCCCCCCCC"
value="{ID}"
placeholderSymbol="_"
>
<rules>
<MaskInputRule
maskFormatSymbol="C"
regex="[a-f0-9]"
/>
</rules>
</MaskInput>
<Label text="Name" />
<Input value="{name}" />
<Label text="Description" />
<TextArea
value="{description}"
rows="5"
/>
<Label text="Price" />
<Slider
width="100%"
min="1000"
max="100000"
showAdvancedTooltip="true"
showHandleTooltip="true"
inputsAsTooltips="true"
enableTickmarks="true"
step="1000"
class="sapUiMediumMarginBottom"
value="{price}"
/>
<Label text="Currency" />
<ComboBox selectedKey="{currency}">
<items>
<core:Item
key="EUR"
text="Euro"
/>
<core:Item
key="USD"
text="US Dollar"
/>
<core:Item
key="TRY"
text="Turkish Lira"
/>
</items>
</ComboBox>
</form:content>
</form:SimpleForm>
<beginButton>
<Button
text="Complete"
press="onCompleteProduct"
/>
</beginButton>
<endButton>
<Button
text="Close"
press="onCloseProductDialog"
/>
</endButton>
</Dialog>
</core:FragmentDefinition>
Secondly, an object from the Entry Create should be instantiated with the controller and EntitySet
name.
TypeScript
import Controller from "sap/ui/core/mvc/Controller";
import EntryCreateCL from "ui5/antares/entry/v2/EntryCreateCL"; // Import the class
import ResponseCL from "ui5/antares/entry/v2/ResponseCL"; // Import the ResponseCL class
import { ISubmitResponse } from "ui5/antares/types/entry/submit"; // Import the error type
import MessageBox from "sap/m/MessageBox";
/**
* @namespace your.apps.namespace
*/
export default class YourController extends Controller {
// Class property
private productEntry: EntryCreateCL<IProducts>;
public onInit() {
}
public async onCreateProduct () {
// Create an object and set it to the class property
this.productEntry = new EntryCreateCL<IProducts>(this, "Products");
// Set the path of the custom fragment
this.productEntry.setFragmentPath("your.apps.namespace.path.to.FragmentFileName");
// Attach submit completed
this.productEntry.attachSubmitCompleted(this.productSubmitCompleted, this);
// Attach submit failed
this.productEntry.attachSubmitFailed(this.productSubmitFailed, this);
// Load the fragment
this.productEntry.createNewEntry();
}
// Press event of the begin button in the dialog
public onCompleteProduct () {
// Do your validation
// Submit the entity
this.productEntry.submit();
}
// Press event of the end button in the dialog
public onCloseProductDialog () {
// Reset the entity and close the dialog
this.productEntry.reset();
}
// Submit Completed Handler
private productSubmitCompleted (response: ResponseCL<IProducts>): void {
// Get the status code. Please be aware, it may also be undefined
const statusCode = response.getStatusCode();
// Get the data that was submitted. Please be aware, it may also be undefined
const submittedData = response.getResponse();
if (submittedData) {
// Some operations
const createdProductID = submittedData.ID;
}
}
// Please use the ISubmitResponse type for the ResponseCL generic
private productSubmitFailed(response: ResponseCL<ISubmitResponse>): void {
// Get the status code. Please be aware, it may also be undefined
const statusCode = response.getStatusCode();
// Get the response. Please be aware, it may also be undefined
const reason = response.getResponse();
// Get the statusText
if (reason) {
MessageBox.error(reason.statusText || "The product was not created!");
}
}
}
interface IProducts {
ID: string;
name: string;
description: string;
brand: string;
price: number;
currency: string;
quantityInStock: number;
categoryID: string;
supplierID: string;
}
JavaScript
sap.ui.define([
"sap/ui/core/mvc/Controller",
"ui5/antares/entry/v2/EntryCreateCL", // Import the class
"sap/m/MessageBox" // Import the Fragment class
],
/**
* @param {typeof sap.ui.core.mvc.Controller} Controller
*/
function (Controller, EntryCreateCL, MessageBox) {
"use strict";
return Controller.extend("your.apps.namespace.YourController", {
onInit: function () {
},
onCreateProduct: async function () {
// Create an object and set it to the class property
this.productEntry = new EntryCreateCL(this, "Products");
// Set the path of the custom fragment
this.productEntry.setFragmentPath("your.apps.namespace.path.to.FragmentFileName");
// Attach submit completed
this.productEntry.attachSubmitCompleted(this.productSubmitCompleted, this);
// Attach submit failed
this.productEntry.attachSubmitFailed(this.productSubmitFailed, this);
// Load the fragment
this.productEntry.createNewEntry();
},
// Press event of the begin button in the dialog
onCompleteProduct: function () {
// Do your validation
// Submit the entity
this.productEntry.submit();
},
// Press event of the end button in the dialog
onCloseProductDialog: function () {
// Reset the entity and close the dialog
this.productEntry.reset();
},
// Submit Completed Handler
productSubmitCompleted: function (response) {
// Get the status code. Please be aware, it may also be undefined
const statusCode = response.getStatusCode();
// Get the data that was submitted. Please be aware, it may also be undefined
const submittedData = response.getResponse();
if (submittedData) {
// Some operations
const createdProductID = submittedData.ID;
}
},
// Submit Failed Handler
productSubmitFailed: function (response) {
// Get the status code. Please be aware, it may also be undefined
const statusCode = response.getStatusCode();
// Get the response. Please be aware, it may also be undefined
const reason = response.getResponse();
// Get the statusText
if (reason) {
MessageBox.error(reason.statusText || "The product was not created!");
}
}
});
});
By default, UI5 Antares performs a mandatory check for the properties with Nullable="false" attribute and the properties defined using setMandatoryProperties() method. However, this feature can be deactived using setAutoMandatoryCheck() method.
Setter (setAutoMandatoryCheck)
Parameter | Type | Mandatory | Description |
---|---|---|---|
autoMandatoryCheck | boolean | Yes | If set to false, mandatory check is deactivated |
Returns | Description |
---|---|
void |
Getter (getAutoMandatoryCheck)
Returns | Description |
---|---|
boolean | Returns the value that was set using setAutoMandatoryCheck() method. Default value is true |
Entry Update (EntryUpdateCL) is a class that manages the UPDATE (PATCH/MERGE/PUT) operation through the OData V2 model. It basically avoids developers having to deal with fragments, user input validations, Value Help creations while working on custom SAPUI5 applications or Fiori Elements extensions. Below you can see the features that Entry Update has.
Features:
- sap.m.Dialog generation with a SmartForm, SimpleForm or Custom content
- sap.uxap.ObjectPageLayout generation with a SmartForm, SimpleForm or Custom Content
- User input validation via ValidationLogicCL class
- Value Help Dialog generation via ValueHelpCL class
- Property sorting, readonly properties
- Label generation for the SmartForm, SimpleForm elements
- submitChanges(), and resetChanges() handling based on the user interaction
- Call a fragment and bind the context in case you do not want to use the auto-generated dialog
Let's say that you have an EntitySet named Products
which is bound to a table and you want to let the end user select a line from the table and edit the selected entity on a pop-up screen using the OData V2 service in your custom SAPUI5 application. Here are the steps you need to follow.
- You need to create a .fragment.xml file that contains a Dialog with a form content (Simple, Smart etc.) and call it from the controller or generate the dialog directly on the controller
- You have to write tons of Value Help code if you don't use sap.ui.comp.smartfield.SmartField with the OData Annotations
- You need to validate the user input, such as checking mandatory fields and ensuring that the values entered match your business logic
- You need to handle the table selection and the binding of the selected entity to the dialog or form
EntryUpdateCL class basically handles all of the steps defined above.
You must initialize an object from EntryUpdateCL in order to use it.
Parameter | Type | Mandatory | Default Value | Description |
---|---|---|---|---|
controller | sap.ui.core.mvc.Controller | Yes | The controller object (usually this ) |
|
settings | object | Yes | ||
entityPath | string | Yes | The name of the EntitySet. It can start with a "/" | |
initializer | string | sap.ui.model.Context | EntityKeysT | Yes | The ID of the table or the context binding or the key values of the entity that will be updated | |
modelName? | string | No | undefined | The name of the OData V2 model which can be found on the manifest.json file. Do not specify if the model name = "" |
There are three distinct methods for constructing an object from the Entry Update class.
The most straightforward method for utilizing the capabilities of the Entry Update class is to construct an object with the ID of a table that you have on your XML view. This method offers several advantages.
- The table row selected by the end user is automatically detected by the Entry Update class, and the context binding of the selected row is bound to the auto-generated dialog.
- If no table row is selected by the end user, a default message is displayed in the sap.m.MessageBox.error to the end user.
Important: This method supports only the table types and selection modes listed below. If the selection mode of the table whose ID is being used for object construction is not supported, the library throws an error.
Information: The default message displayed when the end user has not selected a row from the table yet can be modified using setSelectRowMessage() method.
Supported Table Types
Sample
Let us consider an EntitySet
named Products, which is bound to an sap.m.Table on the XML view. Our objective is to add a sap.m.Button to the header toolbar of the table. When the user selects a row from the table and presses the Update Product button, we will open a dialog so the end user can modify the entity.
TypeScript
EntryUpdateCL<EntityT, EntityKeysT> is a generic class and can be initialized with 2 types.
- The
EntityT
type contains all properties of theEntitySet
that is used as a parameter on the class constructor. - The
EntityKeysT
type contains the key properties of theEntitySet
that is used as a parameter on the class constructor.
EntityT
is used as the returning type of the getResponse(): EntityT method of the ResponseCL
class whose object is passed as a parameter into the function attached by the attachSubmitCompleted(submitCompleted: (response: ResponseCL) => void, listener?: object) method.
EntityKeysT
is used as one of the types of the initializer
parameter in the class constructor.
import Controller from "sap/ui/core/mvc/Controller";
import EntryUpdateCL from "ui5/antares/entry/v2/EntryUpdateCL"; // Import the class
/**
* @namespace your.apps.namespace
*/
export default class YourController extends Controller {
public onInit() {
}
public async onUpdateCategory() {
// Initialize without a type and with the table id
const entry = new EntryUpdateCL(this, {
entityPath: "Categories",
initializer: "tblCategories" // table id
});
}
public async onUpdateProduct() {
// Initialize with a type and the table id
const entry = new EntryUpdateCL<IProducts, IProductKeys>(this, {
entityPath: "Products",
initializer: "tblProducts" // table id
});
}
public async onUpdateCustomer() {
// Initialize with a model name and the table id
const entry = new EntryUpdateCL(this, {
entityPath: "Customers",
initializer: "tblCustomers" // table id
}, "myODataModelName");
}
}
interface IProducts {
ID: string;
name: string;
description: string;
brand: string;
price: number;
currency: string;
quantityInStock: number;
categoryID: string;
supplierID: string;
}
interface IProductKeys {
ID: string;
}
JavaScript
sap.ui.define([
"sap/ui/core/mvc/Controller",
"ui5/antares/entry/v2/EntryUpdateCL" // Import the class
],
/**
* @param {typeof sap.ui.core.mvc.Controller} Controller
*/
function (Controller, EntryUpdateCL) {
"use strict";
return Controller.extend("your.apps.namespace.YourController", {
onInit: function () {
},
onUpdateProduct: async function () {
// Initialize with the table id
const entry = new EntryUpdateCL(this, {
entityPath: "Products",
initializer: "tblProducts" // table id
});
},
onUpdateCategory: async function () {
// Initialize with a model name
const entry = new EntryUpdateCL(this, {
entityPath: "Categories",
initializer: "tblCategories" // table id
}, "myODataModelName");
}
});
});
An alternative approach to constructing an object from the Entry Update class is to utilise the context of the entity that will be updated by the end user.
Sample
Let us consider an EntitySet
named Products, which is bound to an sap.m.Table on the XML view. Our objective is to add a sap.m.Button to the header toolbar of the table. When the user selects a row from the table and presses the Update Product button, we will retrieve the context of the selected row and use to construct an object from the Entry Update class.
TypeScript
EntryUpdateCL<EntityT, EntityKeysT> is a generic class and can be initialized with 2 types.
- The
EntityT
type contains all properties of theEntitySet
that is used as a parameter on the class constructor. - The
EntityKeysT
type contains the key properties of theEntitySet
that is used as a parameter on the class constructor.
EntityT
is used as the returning type of the getResponse(): EntityT method of the ResponseCL
class whose object is passed as a parameter into the function attached by the attachSubmitCompleted(submitCompleted: (response: ResponseCL) => void, listener?: object) method.
EntityKeysT
is used as one of the types of the initializer
parameter in the class constructor.
import Controller from "sap/ui/core/mvc/Controller";
import EntryUpdateCL from "ui5/antares/entry/v2/EntryUpdateCL"; // Import the class
import MessageBox from "sap/m/MessageBox";
import Table from "sap/m/Table";
/**
* @namespace your.apps.namespace
*/
export default class YourController extends Controller {
public onInit() {
}
public async onUpdateCategory() {
// Get the selected item and warn the end user if no row was selected
const selectedItem = (this.getView().byId("tblCategories") as Table).getSelectedItem();
if (!selectedItem) {
MessageBox.error("Please select a row from the table");
return;
}
// Get the selected context
const selectedContext = selectedItem.getBindingContext();
// Initialize without a type and use the binding context
const entry = new EntryUpdateCL(this, {
entityPath: "Categories",
initializer: selectedContext // binding context
});
}
public async onUpdateProduct() {
// Get the selected item and warn the end user if no row was selected
const selectedItem = (this.getView().byId("tblProducts") as Table).getSelectedItem();
if (!selectedItem) {
MessageBox.error("Please select a row from the table");
return;
}
// Get the selected context
const selectedContext = selectedItem.getBindingContext();
// Initialize with a type and use the binding context
const entry = new EntryUpdateCL<IProducts, IProductKeys>(this, {
entityPath: "Products",
initializer: selectedContext // binding context
});
}
public async onUpdateCustomer() {
// Get the selected item and warn the end user if no row was selected
const selectedItem = (this.getView().byId("tblCustomers") as Table).getSelectedItem();
if (!selectedItem) {
MessageBox.error("Please select a row from the table");
return;
}
// Get the selected context
const selectedContext = selectedItem.getBindingContext();
// Initialize with a model name and use the binding context
const entry = new EntryUpdateCL(this, {
entityPath: "Customers",
initializer: selectedContext // binding context
}, "myODataModelName");
}
}
interface IProducts {
ID: string;
name: string;
description: string;
brand: string;
price: number;
currency: string;
quantityInStock: number;
categoryID: string;
supplierID: string;
}
interface IProductKeys {
ID: string;
}
JavaScript
sap.ui.define([
"sap/ui/core/mvc/Controller",
"ui5/antares/entry/v2/EntryUpdateCL", // Import the class
"sap/m/MessageBox"
],
/**
* @param {typeof sap.ui.core.mvc.Controller} Controller
*/
function (Controller, EntryUpdateCL, MessageBox) {
"use strict";
return Controller.extend("your.apps.namespace.YourController", {
onInit: function () {
},
onUpdateProduct: async function () {
// Get the selected item and warn the end user if no row was selected
const selectedItem = this.getView().byId("tblProducts").getSelectedItem();
if (!selectedItem) {
MessageBox.error("Please select a row from the table");
return;
}
// Get the selected context
const selectedContext = selectedItem.getBindingContext();
// Initialize with the binding context
const entry = new EntryUpdateCL(this, {
entityPath: "Products",
initializer: selectedContext // binding context
});
},
onUpdateCategory: async function () {
// Get the selected item and warn the end user if no row was selected
const selectedItem = this.getView().byId("tblCategories").getSelectedItem();
if (!selectedItem) {
MessageBox.error("Please select a row from the table");
return;
}
// Get the selected context
const selectedContext = selectedItem.getBindingContext();
// Initialize with the binding context
const entry = new EntryUpdateCL(this, {
entityPath: "Categories",
initializer: selectedContext // binding context
}, "myODataModelName");
}
});
});
The final method for constructing an object from the Entry Update class is to utilize the key values of the entity that will be updated by the end user.
Sample
For the purposes of this example, let us consider an EntitySet
named Products with a single key property named ID
, whose type is Edm.Guid
. We would like to allow the end user to edit a specific entity with the key value: ID = "b2f0013e-418f-42aa-9a24-3770fe17ce18".
Hint: Please note that if the
EntitySet
is bound to a table, you can retrieve the values of the key properties of the selected row using the getBindingContext().getObject() method.
Information: The EntryUpdateCL class creates a binding context with the values of the specified key properties using the
initializer
parameter in the class constructor and subsequently binds the created context to the dialog.
TypeScript
EntryUpdateCL<EntityT, EntityKeysT> is a generic class and can be initialized with 2 types.
- The
EntityT
type contains all properties of theEntitySet
that is used as a parameter on the class constructor. - The
EntityKeysT
type contains the key properties of theEntitySet
that is used as a parameter on the class constructor.
EntityT
is used as the returning type of the getResponse(): EntityT method of the ResponseCL
class whose object is passed as a parameter into the function attached by the attachSubmitCompleted(submitCompleted: (response: ResponseCL) => void, listener?: object) method.
EntityKeysT
is used as one of the types of the initializer
parameter in the class constructor.
import Controller from "sap/ui/core/mvc/Controller";
import EntryUpdateCL from "ui5/antares/entry/v2/EntryUpdateCL"; // Import the class
/**
* @namespace your.apps.namespace
*/
export default class YourController extends Controller {
public onInit() {
}
public async onUpdateCategory() {
// Prepare the key values of a specific entity
const keyValues = {
ID: "b2f0013e-418f-42aa-9a24-3770fe17ce18"
};
// Initialize without a type and use the key values as the initializer
const entry = new EntryUpdateCL(this, {
entityPath: "Categories",
initializer: keyValues // key values of the entity
});
}
public async onUpdateProduct() {
// Prepare the key values of a specific entity
const keyValues = {
ID: "b2f0013e-418f-42aa-9a24-3770fe17ce18"
};
// Initialize with a type and use the key values as the initializer
const entry = new EntryUpdateCL<IProducts, IProductKeys>(this, {
entityPath: "Products",
initializer: keyValues // key values of the entity
});
}
public async onUpdateCustomer() {
// Prepare the key values of a specific entity
const keyValues = {
ID: "b2f0013e-418f-42aa-9a24-3770fe17ce18"
};
// Initialize with a model name and use the key values as the initializer
const entry = new EntryUpdateCL(this, {
entityPath: "Customers",
initializer: keyValues // key values of the entity
}, "myODataModelName");
}
}
interface IProducts {
ID: string;
name: string;
description: string;
brand: string;
price: number;
currency: string;
quantityInStock: number;
categoryID: string;
supplierID: string;
}
interface IProductKeys {
ID: string;
}
JavaScript
sap.ui.define([
"sap/ui/core/mvc/Controller",
"ui5/antares/entry/v2/EntryUpdateCL"
],
/**
* @param {typeof sap.ui.core.mvc.Controller} Controller
*/
function (Controller, EntryUpdateCL) {
"use strict";
return Controller.extend("your.apps.namespace.YourController", {
onInit: function () {
},
onUpdateProduct: async function () {
// Prepare the key values of a specific entity
const keyValues = {
ID: "b2f0013e-418f-42aa-9a24-3770fe17ce18"
};
// Initialize with the entity set name and use the key values as the initializer
const entry = new EntryUpdateCL(this, {
entityPath: "Products",
initializer: keyValues // key values of the entity
});
},
onUpdateCategory: async function () {
// Prepare the key values of a specific entity
const keyValues = {
ID: "b2f0013e-418f-42aa-9a24-3770fe17ce18"
};
// Initialize with the entity set name and use the key values as the initializer
const entry = new EntryUpdateCL(this, {
entityPath: "Categories",
initializer: keyValues // key values of the entity
}, "myODataModelName");
}
});
});
If the object from the Entry Update class is constructed using the Constructor with a Table ID approach, a default error message is displayed in an sap.m.MessageBox.error to the end user when the user has not yet selected a row from the table.
To change the default message, setSelectRowMessage() method can be utilized.
Setter (setSelectRowMessage)
Parameter | Type | Mandatory | Description |
---|---|---|---|
message | string | Yes | The message that is displayed when the end user has not selected a row from the table |
Returns | Description |
---|---|
void |
Getter (getSelectRowMessage)
Returns | Description |
---|---|
string | Returns the value that was set using setSelectRowMessage() method. Default value is Please select a row from the table. |
updateEntry() method binds the context, which is determined using the initializer
parameter in the class constructor, to the dialog that is automatically generated or loaded from the fragment that is placed in the application files. Once the context is bound, the generated/loaded dialog is opened.
By default, updateEntry() method uses the ODataMetaModel to determine the EntityType
of the EntitySet
that was set by the constructor and brings all the properties in the same order as the OData metadata into the generated form.
All key properties are marked as mandatory/required and the labels are generated assuming that the naming convention of the EntityType
is camelCase. Please see Label Generation
Important: It is not possible to modify any of the key properties of an
EntitySet
on the auto-generated dialog. This behaviour cannot be altered.
Important: Please be advised that the updateEntry() method must be called after any configurations have been made through the public method of the Entry Update class. Any configurations (form title, mandatory properties, etc.) made after the updateEntry() method will not be reflected. Basically, updateEntry() method should be called at the end of your code block.
By default, the key properties with Edm.Guid type are not visible on the generated form. However, this behavior can be modified using the setDisplayGuidProperties() method.
Important: Please be advised that the random UUID generation for properties with the
Edm.Guid
type is not available in the Entry Update class.
Returns | Description |
---|---|
Promise<void> | After the promise is resolved, the context can be retrieved by the getEntryContext() method using the object instantiated from the EntryUpdateCL class |
updateEntry() method uses the default configurations when creating the dialog. However, these configurations can be modified using the public setter methods.
Term | Default Value | Description | Setter | Getter |
---|---|---|---|---|
Naming Strategy | NamingStrategies.CAMEL_CASE |