ui5-antares
TypeScript icon, indicating that this package has built-in type declarations

1.124.1002 • Public • Published

UI5 Antares

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.

BEFORE YOU CONTINUE

⚠ 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.

Features GIF

Auto Generated Dialog

UI5 Antares Gif

Auto Generated Object Page

UI5 Antares Object Page Gif

Prerequisites

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

Table of Contents

Versioning

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

Supported SAPUI5 Versions

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

NPM Package Tags

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.

Installation

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

NPM Installation

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"
    }
  }
}

manifest.json

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"
  }
}

Build Script

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

UI5 Tree

TypeScript

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"
    ]
  }
}

tsconfig.json

Approuter

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"
    }    
  ]
}

xs-app.json

Local Start

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/cli

ui5 serve

@sap/ux-ui5-tooling

fiori run

Known Issues

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.

Solution 1

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).

Remove fiori-tools-proxy ui5 config

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.

Load 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.

Solution 2

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).

Different path

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.

Load from the different path

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

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

Use Case

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.

  1. 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
  2. You have to write tons of Value Help code if you don't use sap.ui.comp.smartfield.SmartField with the OData Annotations
  3. You need to validate the user input, such as checking mandatory fields and ensuring that the values entered match your business logic
  4. 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.

Constructor

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");
        }
      });

    });

Create New Entry

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.

Method Parameters

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.

Default Values

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.

Generated Form

Manual Submit

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();    
        }

      });

    });

Label Generation

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.

Resource Model (i18n)

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.

Label Generation From The Technical Names

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

Use Metadata Labels

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(); 
        }
      });

    });

Resource Bundle Prefix

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();          
        }
      });

    });

Naming Strategy

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(); 
        }
      });

    });

NamingStrategies Enum

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

Form Type

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.

  1. The form fields are rendered as Input, DatePicker, DateTimePicker, ComboBox, CheckBox, etc. based on the EDM type of the EntityType property.
  2. 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(); 
        }
      });

    });

FormTypes Enum

Name Description
FormTypes.SMART SmartForm with SmartField content is generated
FormTypes.SIMPLE SimpleForm with Input, DatePicker, DateTimePicker, CheckBox content is generated

Form Title

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(); 
        }
      });

    });

Form Title

Form Grouping

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(); 
        }

      });

    });

Form Grouping

IFormGroups Type Definition

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

Begin Button Text

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(); 
        }
      });

    });

Begin Button Text

Begin Button Type

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(); 
        }
      });

    });

Begin Button Type

End Button Text

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(); 
        }
      });

    });

End Button Text

End Button Type

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(); 
        }
      });

    });

End Button Type

Properties with Edm.Guid Type

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(); 
        }
      });

    });

Guid Strategy

GuidStrategies Enum

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

Form Property Order

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
Before Property Order After Property Order

Excluded Properties

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
Before Excluded Properties After Excluded Properties

Mandatory Properties

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
Before Mandatory Properties After Mandatory Properties

Mandatory Error Message

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(); 
        }
      });

    });

Mandatory Error Message

Readonly Properties

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"
          }); 
        }
      });

    });

Readonly Properties

Attach Submit Completed

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;
          }          
        }
      });

    });

Attach Submit Failed

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!");
          }     
        }
      });

    });

Response Class

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

Value Help

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.

  1. Generates a Value Help Dialog with a table and filterbar consisting of the EntitySet properties defined in the class constructor
  2. Handles the filterbar and search field
  3. Handles the selection

Constructor

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.

  1. Creates a table and makes the settings.valueHelpProperty the first column of the table
  2. Adds all the properties specified in the settings.readonlyProperties array as columns to the table next to the first column
  3. Binds the EntitySet specified in the settings.valueHelpEntity to the created table
  4. Creates a filterbar and UI Controls (Input, DatePicker etc.) for the settings.valueHelpProperty and settings.readonlyProperties if they don't exist in the settings.excludedFilterProperties array
  5. Creates a JSON Model for handling the filterbar
  6. Creates a search field
  7. 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.

Label Generation

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 EntitySets 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(); 
        }
      });

    });

Value Help

categoryID supplierID
Value Help Value Help

Standalone Usage

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.

Value Help

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);
        }
      });

    });

Validation Logic

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.

  1. Validation with Operator
  2. Validation with Validator Function

Constructor

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

Validation with Operator

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 or Edm.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
Validation Failed Invalid Value

Validation with Validator Function

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
        }
      });

    });

ValidationOperator Enum

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

Object Page

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.

Object Page

Sections

To add sections to the generated object page, Form Grouping feature can be utilized.

Header Title

The title in the generated object page is derived from the Form Title feature.

Header Label

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();
        }

      });

    });

Object Page

Header Avatar

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();
        }

      });

    });

Object Page

Custom Content Section Title

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

Custom Control

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.

Constructor

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();
        }
      });

    });

Custom Control

Validation

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          
        }
      });

    });

Custom Control From Fragment

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>

Custom Control From Fragment

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();
        }
      });

    });

Custom Control From Fragment

Validation

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>

Custom Control From Fragment

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
        }        
      });

    });

Custom Content

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(); 
        }
      });

    });

Custom Content

Custom Content From Fragment

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>

Custom Content From Fragment

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();
        }
      });

    });

Custom Content From Fragment

Custom Fragment

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.

  1. Entry Create class provides a public method named submit() which must be called manually to submit the transient entity.
  2. 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>

Custom Fragment

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!");
          }
        }   
      });

    });

Custom Fragment

Auto Mandatory Check

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

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

Use Case

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.

  1. 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
  2. You have to write tons of Value Help code if you don't use sap.ui.comp.smartfield.SmartField with the OData Annotations
  3. You need to validate the user input, such as checking mandatory fields and ensuring that the values entered match your business logic
  4. 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.

Constructor

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.

Constructor with a Table ID

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.

  1. 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.
  2. 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

Table Type Selection Mode
sap.m.Table SingleSelect | SingleSelectLeft | SingleSelectMaster
sap.ui.table.Table Single
sap.ui.comp.smarttable.SmartTable Single
sap.ui.table.AnalyticalTable Single
sap.ui.table.TreeTable Single

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.

Update Constructor Sample

TypeScript

EntryUpdateCL<EntityT, EntityKeysT> is a generic class and can be initialized with 2 types.

  • The EntityT type contains all properties of the EntitySet that is used as a parameter on the class constructor.
  • The EntityKeysT type contains the key properties of the EntitySet 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");
        }
      });

    });

Constructor with a Context Binding

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.

Update Constructor Sample

TypeScript

EntryUpdateCL<EntityT, EntityKeysT> is a generic class and can be initialized with 2 types.

  • The EntityT type contains all properties of the EntitySet that is used as a parameter on the class constructor.
  • The EntityKeysT type contains the key properties of the EntitySet 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");
        }
      });

    });

Constructor with Entity Keys

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 the EntitySet that is used as a parameter on the class constructor.
  • The EntityKeysT type contains the key properties of the EntitySet 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");          
        }
      });

    });

Select Row Message

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.

Update Entry

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.

Method Parameters

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.

Default Values

Term Default Value Description Setter Getter
Naming Strategy NamingStrategies.CAMEL_CASE

Readme

Keywords

Package Sidebar

Install

npm i ui5-antares

Weekly Downloads

1,308

Version

1.124.1002

License

Apache-2.0

Unpacked Size

852 kB

Total Files

87

Last publish

Collaborators

  • hasanciftci