Technology Blogs by SAP
Learn how to extend and personalize SAP applications. Follow the SAP technology blog for insights into SAP BTP, ABAP, SAP Analytics Cloud, SAP HANA, and more.
cancel
Showing results for 
Search instead for 
Did you mean: 
3,704

Overview


In this blog I am showcasing a Dynamic Custom Control which can be used to render a form in any UI Application with minimal code. It uses the OData metadata annotation to render control in form field. It supports message handling and perform validation on correctness of values based on data type of that field.

There is a similar kind of Smart Form control available but this Form Control offers far more flexibility and developer have to write much less code to declare it.

So lets start with the looking at Form control in Display and in Edit Mode.

                                                Figure 1: Sales Order Form in Display Mode

 

                                                Figure 2: Sales Order Form in Edit Mode

 

Control Features



Details of Control Type Supported in the control


This control supports varied control types. The usage of these control type and their configuration are based on annotation provided in the metadata of the property. By default this control uses 8 control types which are used commonly in any form. These are listed below along with what annotation to be used.

Additionally this control also supports loading of control type different from default one or overriding of default behavior of these control types (Refer control property propertyMap for more details  regarding this).

Date Picker




Assign Edm.Type = Edm.DateTime or Edm.DateTimeoffset in the entity to that.  an
Note:- Also Provide a custom annotation sap:display-format="Date"






Time Picker





Assign Edm.Type = Edm.Time in the entity.
Note:- Do not provide sap:display-format="Date" annotation



 

Date Time Picker




Assign Edm.Type = Edm.DateTime or  Edm.DateTimeoffset in the entity.
Note:- Do not provide sap:display-format="Date" annotation




 

Text Area




MaxLength in the entity should be more than 50 to render a TextArea control.



 

Amount-Currency Type Control




Assign sap-unit='Name of the Currency property' annotation to to Amount property as it is              done in this example - sap-unit="CurrencyCode" is assigned to NetAmount.



 

Yes-No Option Control (CheckBox like)




Assign sap-isCheckBox='true' annotation to the property for which a ComboBox with option            yes/no is required. It can be interpreted as a Checkbox.





ValueHelps




Assign sap:value-list="fixed-values" annotation to the property for which ValueHelp is to be            rendered. Also assign the name of the property as a reference to the ValueHelp Entity to                    load data in the ValueHelp.






 

Input




By default Input control will be loaded



Field Control


This control uses Field Control feature of OData to dynamically update the visual configuration of Control type. These 4 types of Configuration are as follows:-

1. Mandatory

Pass 7 to Field Control value (here Uxfc01) at the time of fetching data.





2. Read only

Pass 1 to Field Control value (here Uxfc01) at the time of fetching data.

Additionally it also uses sap:creatable and sap:updatable annotation in entity to make a field as read only.
Note: Later will take preference over the former in case of conflict.




3. Hiding fields

Pass 0 to Field Control value (here Uxfc01) at the time of fetching data.

Additionally it also uses sap:visible annotation in entity to hide a field.
Note: Later will take preference over the former in case of conflict.



4. Optional

Pass 3 to Field Control value (here Uxfc01) at the time of fetching data.

In this case the default behavior of the control will be used.
Validations & Checks


Control itself validates whether any field in the form is invalid or not.

It verifies that all the mandatory fields are having values, fields are having valid values or not (based on Edm.Type)



 
Properties available in this control














































































Name Type Default Value Description


entityTypeName

string Specifies Name of the OData entity


title

string null Title of the form


mode

string null Specifies mode in which control needs to be Rendered. "E" for Edit mode and "D" for display Mode


includeOnlyFields



string[]

[]

Specifies Explicit list of fields to display. All other fields will be ignored.

Example of Usage

<Form includeOnlyFields="F1,F2,F3" />




useSplitLayout



boolean true Specifies whether to use split form layout (with two form containers)


required

boolean false If set to true then all the fields in the Form becomes mandatory


odataModelName

string

Specifies name of the OData Model.

Note:- Use this property only when odata model has some name


dataPath

string Specifies the path in the binded model(Name of the model is stored in the property modelName) where Form data is stored


modelName

string Name of the Binded Model where data of the Form is stored




mandatoryFields



string[] []

Specifies name of the field which have to be marked as mandatory and those are not configurable by the user.

Example of Usage

<Form mandatoryFields="F1,F2,F3" />





propertyMap

 
object

Using this property a user can handle:-

1. Custom Behavior of default types*

Using the user can override the the default behavior of the control type and provide their own custom behavior.

2. Custom Control type factory**

Using this user can even user their own control factory if the default one does not suites to their requirement.


*  Let say there is requirement to override enabled property of LifeCycleStatus field then it can be done in following manner
{        
LifeCycleStatus:{
enabled: // Handling of enable property
}
}

 

** Let say there is requirement to use a checkbox type control instead of default Yes/No ComboBox for field then it can be done in following way
{
CreatedByBp: {
editFactory: // bind method name which returns checkBox control factroy which // will be rendered in edit mode,

displayFactory: // bind method name which returns checkBox control factroy // which will be rendered in display mode
}
}

 

Control Events

changeFieldValue - The event is fired when value in any form field control is changed


Visibility: public 
















































Param Type Description
oControlEvent sap.ui.base.Event


getSource

sap.ui.base.EventProvider
getParameters object




event



sap.ui.base.Event

event of the control which is fired by particular form fied







field





string

The name of an updated field



value

string

New field value



entityType

string

Name in the Entity type passed in the property entityTypeName



Now lets create a Sales Order App which is using this form control.



OData project created for this example

                                                            Soheaderdata Entity

Fields to be shown in the control is determined by the properties defined in the Entity(here Soheaderdata). Please note that properties shown in Figure 1 & 2 are same as defined in the Entity.

Value defined in the label section of the entity is used as Label of form field.
Code to fetch data



Download source code of the Form Control 

Source Code Snippet for Sales Order App
SalesOrder.view.xml

<mvc:View controllerName="sa.sap.sample.reuse.form.controller.SalesOrder" 
xmlns:html="http://www.w3.org/1999/xhtml"
xmlns:mvc="sap.ui.core.mvc"
displayBlock="true"
xmlns="sap.m"
xmlns:c="sap.custom.controls.form">
<App id="idAppControl">
<pages>
<Page title="Custom Form Sample">
<content>
<c:Form id="idSalesOrderDetails"
entityTypeName="Soheaderdata"
title="Sales Order Details"
editable="true"
visible="true"
mode="{FormDataModel>/displayMode}"
modelName="FormDataModel"
dataPath="/data" />
</content>
<footer>
<Bar>
<contentRight>
<Button text="Save" visible="{=${FormDataModel>/displayMode} !== 'D'}" press="onSalesOrderSave" />
<Button text="Edit" visible="{=${FormDataModel>/displayMode} === 'D'}" press="onSalesOrderEdit" />
<Button text="Display" visible="{=${FormDataModel>/displayMode} !== 'D'}" press="onSalesOrderDisplay"/>
</contentRight>
</Bar>
</footer>
</Page>
</pages>
</App>
</mvc:View>

Control declaration


SalesOrder.controller.js

sap.ui.define([
"sap/ui/core/mvc/Controller",
"sap/ui/model/json/JSONModel",
"sap/m/MessageToast"
], function (Controller, JSONModel, MessageToast) {
"use strict";
return Controller.extend("sa.sap.sample.reuse.form.controller.SalesOrder", {
onInit: function () {
var oJsonModel = new JSONModel({
data: {},
displayMode: "D"
});
this.getView().setModel(oJsonModel, "FormDataModel");
var oDataModel = this.getOwnerComponent().getModel();
var sPath = "/SoheaderdataSet('500000000')";
oDataModel.read(sPath, {
success: this._onSalesOrderReadSuccess.bind(this),
error: this._onSalesOrderReadFail.bind(this)
});
},
onSalesOrderEdit: function () {
this.getView().getModel("FormDataModel").setProperty("/displayMode", "E");
this.getView().byId("idSalesOrderDetails").refresh();
},
onSalesOrderDisplay: function () {
this.getView().getModel("FormDataModel").setProperty("/displayMode", "D");
this.getView().byId("idSalesOrderDetails").refresh();
},
onSalesOrderSave: function(){
this.byId("idSalesOrderDetails").validate();
},
_onSalesOrderReadSuccess: function (oResponse) {
this.getView().getModel("FormDataModel").setProperty("/data", oResponse);
},
_onSalesOrderReadFail: function () {
MessageToast.show("Error in Reading Sales Order Details");
}
});
});

Note:- In the above code snippet refresh method defined in the control needs to be called on change of the mode of the screen.

As you can see in the above code snippet, with such a minimal code we have rendered a full fledged form control which differentiate it with Smart Form Control.

Download source code of the example used in this blog  from this git repo

Note:- This control renders TypeAhead, SingleSelect ValueHelp, MultiSelect ValueHelp controls(Custom) which I will be showcasing in the next blog .

 
4 Comments