Data Binding In Sapui5 665g4q

  • ed by: Praveen Kumar
  • 0
  • 0
  • June 2022
  • PDF

This document was ed by and they confirmed that they have the permission to share it. If you are author or own the copyright of this book, please report to us by using this report form. Report 3b7i


Overview 3e4r5l

& View Data Binding In Sapui5 as PDF for free.

More details w3441

  • Words: 14,239
  • Pages: 73


Since the value of text property of the sap.m.Text control has been hard-coded, it is unrelated to any data that might exist within a model object. Therefore, this is an example of how data binding is not used!

July 2015

6

SAPUI5 Tutorial – Data Binding

Step 2:

Creating a Model Object

A model object is a container for the data upon which your application operates. The business data within a model can be defined using various formats: 

JavaScript Object Notation (JSON)



Extensible Markup Language (XML)



OData (covered in another tutorial)



Your own custom format (not covered in this tutorial)

There is also a special type of model object called a "Resource Model". This model type is used as a wrapper object around a resource bundle file. The names of such files must end with ".properties" and are used typically for holding language specific text. When JSON, XML and Resource Models are created, all the data they contain is entirely loaded in a single request (typically by requesting it from a web server). In other words, after the model's data has been requested, the entire model is known to the SAPUI5 application. These models are known as “client-side” models because once created, their data lives entirely within the client-side JavaScript coding. Tasks such as filtering and sorting can be performed locally on the client. An OData model however, is a “server-side” model. This means that whenever a SAPUI5 application needs data from such a model, it must be requested on demand. Such a request will almost never return all the data in the model, typically because this would be far more data than is required by the client application. Consequently, tasks such as sorting and filtering should always be delegated to the server. In this tutorial, we will focus on JSON models since they do not require the presence of a backend business system.

2.1. Preview

Although there is no visual difference between this screen shot and the previous one, the greeting text has now been derived from a model object, rather than being hard-coded into the UI control's definition.

July 2015

7

SAPUI5 Tutorial – Data Binding

2.2. ./index.html ...SNIP... <script> // -----------------------------------------------------------------------// Attach an anonymous function to the SAPUI5 'init' event sap.ui.getCore().attachInit(function () { // Create a new JSON model object var oModel = new sap.ui.model.json.JSONModel({ greetingText : "Hi, my name is Harry Hawk" }); // Assign the model object to the SAPUI5 core sap.ui.getCore().setModel(oModel); // Display a text element whose text is derived from the model object new sap.m.Text({ text : "{/greetingText}" }). addStyleClass("sapUiSmallMargin"). placeAt("content"); }); ...SNIP...

Inside the anonymous function ed to sap.ui.getCore().attachInit(), we perform two extra tasks: 1. Create a new JSON model using a JSON literal object and store the resulting model object in a local variable called oModel. 2. Set oModel to be the default model object within the entire SAPUI5 core. In this example, the JSON model object has been bound to the core of SAPUI5 framework without giving it a specific name. This action has two immediate consequences: 1. It makes the model object globally available to all other parts of the SAPUI5 application. 2. The call to the setModel function was made using only one parameter. By omitting the second parameter to the setModel function, we have created an unnamed model that automatically becomes the default model object for the whole of the SAPUI5 core. Consequently, when we want to refer to any of the properties within this model, we can simply state the path to the property name, without stating to which model the property belongs. Next, the text property of the sap.m.Text UI control is set to the value "{/greetingText}". The curly brackets enclosing some path name are known as the data binding syntax. In this case, we are stating the UI control's text property will have its value derived from a property called greetingText in the default model.

Warning! Normally, you would never hardcode a model object within your coding. Instead the data would typically be obtained from some backend business system. In this case we have bound the model object to the SAPUI5 core. This has been done for simplicity, but is not considered good practice. Generally speaking, a model object holding business data is bound only to the view that displays the data. We will correct this situation later on in the tutorial.

July 2015

8

SAPUI5 Tutorial – Data Binding

Step 3:

Making Model Object Data Available on the Interface

Although there is no visible difference, the text on the screen is now derived from a mixture of sources.

3.1. Preview

3.2. ./index.html The line of code with the strikethrough should be deleted! ...SNIP... <script> // -----------------------------------------------------------------------// Attach an anonymous function to the SAPUI5 'init' event sap.ui.getCore().attachInit(function () { // Create a new JSON model object var oModel = new sap.ui.model.json.JSONModel({ greetingText : "Hi, my name is Harry Hawk" firstName : "Harry", lastName : "Hawk" }); // Assign the model object to the SAPUI5 core sap.ui.getCore().setModel(oModel); new sap.m.Text({ text : "Hi, my name is {/firstName} {/lastName}" }). addStyleClass("sapUiSmallMargin"). placeAt("content"); }); ...SNIP...

Notice now that the value of the sap.m.Text UI control's text property is composed from both model data and static text.

July 2015

9

SAPUI5 Tutorial – Data Binding

3.3. Explanation First, we created a JSON model object using the following code:

However, once created, the data in a model object is not yet of any use to UI Controls. Therefore, we must perform a second step that makes the data in a model object accessible to UI controls. This process is known as "data binding" and it handles the automatic transport of data between the model object and the properties of UI Controls. Therefore, the second line of code shown below is needed. The creation of a data binding instance makes the data in a model object accessible to UI controls.

The data binding model instance provides UI Controls with a common interface to all model objects irrespective of their underlying implementation type (JSON, XML, OData etc.) The diagram above shows the simple case of a model having a single data binding instance; however, it is possible for one model object to have multiple data binding instances. Now that we have a means of transporting data between a model object and UI controls, we are able to combine the data from the model with data derived from other sources; for instance, hardcoded into the UI control's definition.

Important For simplicity, we have set the model to the SAPUI5 core without specifying a name for the model binding instance. This has two specific consequences: 1. By omitting a name parameter for the model binding instance, this particular model becomes the default model. When subsequently accessing the properties in this model, there is no need to identify the model explicitly. 2. The data in the default model is accessible by all other coding running within this instance of the SAPUI5 core. Generally speaking, you should not use the default model object within the SAPUI5 core for holding business data. Instead, you should confine access to model data to only those units of coding that actually need it. Later on in this tutorial, we will correct this situation.

July 2015

10

SAPUI5 Tutorial – Data Binding

Step 4: Two-Way Data Binding In the examples used so far, we have used a read-only field to display the value of a model property. We will now change the interface so that firstly, the first and last name fields are open for input using sap.m.Input fields, and secondly, an additional check box control is used to enable or disable both of these input fields. This arrangement illustrates a feature known as "two-way data binding".

4.1. Preview

July 2015

11

SAPUI5 Tutorial – Data Binding

4.2. ./views/App.view.xml (New file in new folder) Now that the view needs to contain more UI controls, we will move the view definition out of the index.html file and into an XML file. Under the DataBinding folder, create a new folder called views. Within the new views folder, create a file called App.view.xml. Paste in the following code: <mvc:View xmlns="sap.m" xmlns:mvc="sap.ui.core.mvc"> < headerText="{/HeaderText}" class="sapUiResponsiveMargin" width="auto">

This XML view will be identified by its resource name sap.ui.demo.db.view.App.

4.3. ./index.html The lines of code with the strikethrough should be deleted! ...SNIP... <script id="sap-ui-bootstrap" src="../resources/sap-ui-core.js" data-sap-ui-theme="sap_bluecrystal" data-sap-ui-libs="sap.m" data-sap-ui-compatVersion="edge" data-sap-ui-preload="async" data-sap-ui-resourceroots='{ "sap.ui.demo.db": "./" }' > <script> // -----------------------------------------------------------------------// Attach an anonymous function to the SAPUI5 'init' event sap.ui.getCore().attachInit(function () { var oModel = new sap.ui.model.json.JSONModel({ firstName : "Harry", lastName : "Hawk", enabled : true, HeaderText : "Data Binding Basics" }); // Assign the model object to the SAPUI5 core sap.ui.getCore().setModel(oModel); // Display a text element whose text is derived // from the model object new sap.m.Text({ text : "Hi, my name is {/firstName} {/lastName}" }). addStyleClass("sapUiSmallMargin"). placeAt("content"); // Display the XML view called "App" new sap.ui.core.mvc.XMLView({ viewName : "sap.ui.demo.db.views.App" }). placeAt("content"); }); ...SNIP...

July 2015

12

SAPUI5 Tutorial – Data Binding

The previous coding to assign a sap.m.Text field to the UI has been deleted, as it is no longer needed. The SAPUI5 bootstrap has a new parameter called data-sap-ui-resourceroots. This is where we can associate a Java-style namespace with an actual directory in the file system. Although JavaScript does not have any direct concept of namespaces, SAPUI5 treats the resource id in the same way that the Java class loader identifies files by their Java namespace. Once this association has been made, files can be identified by their resource name, rather than a path name. In this case, we want all resources located in the same directory as index.html ("./") to be identified by the namespace "sap.ui.demo.db". Now, when the XML view is created, we can identify the file using the namespace "sap.ui.demo.db.views.App". The "sap.ui.demo.db" part of the name is translated into "./", then after that, the dots are translated into slashes to form a relative path name: "sap.ui.demo.db.views.App"  ./views/App.view.xml Since we are explicitly creating an XML view, the file name given simply as "App" can be assumed to end with ".view.xml".

4.4. Behaviour Refresh your Application Preview tab and switch the checkbox on and off. You will see that the input fields are automatically enabled or disabled in response to the state of the checkbox.

It is clear that we have not written any coding to transfer data between the interface and the model, yet the Input UI Controls are enabled or disabled according to the state of the checkbox. This behaviour is the result of the fact that all SAPUI5 models (except a Resource Model) implement two-way data binding, and for JSON Models, two-data binding is the default behaviour.

Explanation Three things are happening here: 1. Data binding allows the property of a UI control to derive its value from any suitable property in a model object. 2. The purpose of a Data Binding Instance is to create an API that makes all model objects look the same – irrespective of how they have been implemented internally. 3. SAPUI5 automatically handles the transport of data both from the model to the UI control(s), and back from the UI control(s) the model. This is called two-way data binding.

July 2015

13

SAPUI5 Tutorial – Data Binding

Important By default, the data binding mode (one-way or two-way) is a feature of the Model object, and is unrelated to whether the bound UI Control property permits input or not. Therefore, in the diagram below, the use of single- or double-headed arrows indicates nothing more than the direction of data flow between the model and the specific UI control. Since a sap.m.Label control is read-only, in practice, data will only flow from the model to the control; however, since a can change the state of a sap.m.CheckBox control or a sap.m.Input control, double-headed arrows are used to indicate that data entered by the flows in both directions between the model and the UI. For simplicity, the following diagram shows only the data binding for the "Last name" label and input field.

sap.m. sap.m.CheckBox selected:%"{/enabled}"

sap.m.Label text:%"Last%Name"

sap.m.Input value:%"{/lastName}" enabled:%"{/enabled}"

Data Binding Model Instance

JSON Model

July 2015

14

SAPUI5 Tutorial – Data Binding

If you now switch off the sap.m.CheckBox control, two-way data binding ensures that the model is updated. Then, by virtue of the fact that both of the sap.m.Input controls are bound to the model's enabled property, these UI controls are immediately disabled.

sap.m. sap.m.CheckBox selected:%"{/enabled}"

sap.m.Label text:%"Last%Name"

sap.m.Input value:%"{/lastName}" enabled:%"{/enabled}"

Data Binding Model Instance

JSON Model

July 2015

15

SAPUI5 Tutorial – Data Binding

Step 5:

One-way Data Binding

In contrast to the two-way data binding behaviour shown above, one-way data binding is also possible. Here, data is transported in one direction only: from the model, through the data binding instance to the consumer (usually the property of a UI control), but never in the other direction. In this example, we will change the previous example to use one-way data binding. This will then illustrate how the flow of data from the interface back to the model can be switched off if required.

5.1. Preview

5.2. ./index.html Insert the single highlighted line immediately after the creation of the model object in index.html. ...SNIP... <script> // -----------------------------------------------------------------------// Attach an anonymous function to the SAPUI5 'init' event sap.ui.getCore().attachInit(function () { var oModel = new sap.ui.model.json.JSONModel({ firstName : "Harry", lastName : "Hawk", enabled : true, HeaderText : "Data Binding Basics" }); oModel.setDefaultBindingMode(sap.ui.model.BindingMode.OneWay); // Assign the model object to the SAPUI5 core sap.ui.getCore().setModel(oModel); ...SNIP...

July 2015

16

SAPUI5 Tutorial – Data Binding

Now, no matter what state the checkbox is in, the input fields remain open for input because one-way data binding ensures that data flows only from the model to the UI, but never back again.

5.3. Data Binding With Other Model Types JSON and XML models use two-way data binding as their default behaviour (or binding mode). However, by default, OData and Resource models use one-way data binding as the default. Due to the fact that Resource models are designed to deliver static, language specific text to the interface, one-way data binding is the only possible behaviour for this model type. OData models also two-way data binding, but since an OData model is a server-side model and not a client-side model, any change to the model data requires a server round trip before that update can be considered complete. Therefore, two-way data binding for OData models must be switched as required.

5.4. Background The data binding mode (one-way or two-way) is a property of the model object itself. Therefore, unless you specifically alter it, a data binding model instance will always be created using the model object's default data binding mode. Should you wish to alter the data binding mode, then there are two particular ways of doing this: 1. Alter the model's default data binding mode. This is the approach used above. 2. Alter the data binding mode at the time the data binding instance is created. This change applies only to the data binding instance being created. Any other data binding instances created at a later point in time will continue to use the model object's default data binding mode.

Important! There are two important points to understand about alterations to a model object's data binding mode: 1. If you alter the default data binding mode of a model object (as in the example above), then unless you explicitly say otherwise, all data binding instances created after that point in time will use the altered data binding mode. 2. Altering a model object's default data binding mode has no effect on existing data binding model instances. In other words, the alteration of a model object's data binding mode does not alter the JavaScript prototype upon which the model object is defined.

July 2015

17

SAPUI5 Tutorial – Data Binding

Step 6:

Resource Models

As was mentioned in "Creating a Model Object" above, model objects can be defined in various different formats such as JSON, XML or OData. These model formats are most often used to hold either: 

The data needed in order to do business (master data)



The data generated as a result of doing business (transactional data)

However, business applications also require a third type of data; namely, the language specific (translatable) texts used as labels and descriptions on the interface. The example we used at the start of this tutorial was overly simplistic in that we stored language specific text directly in a JSON model object. Generally speaking, unless language specific text is derived directly from a backend system, then it is not good practice to place translatable text directly into a model object. So let's correct this situation by placing all translatable text (such as field labels) into a resource bundle.

6.1. Preview

July 2015

18

SAPUI5 Tutorial – Data Binding

6.2. ./index.html ... SNIP ... <script> // -----------------------------------------------------------------------// Attach an anonymous function to the SAPUI5 'init' event sap.ui.getCore().attachInit(function () { var oModel = new sap.ui.model.json.JSONModel({ firstName : "Harry", lastName : "Hawk", enabled : true, HeaderText : "Data Binding Basics" }); oModel.setDefaultBindingMode(sap.ui.model.BindingMode.OneWay); // Assign the model object to the SAPUI5 core sap.ui.getCore().setModel(oModel); // Create a resource bundle for language specific texts var oResourceBundle = new sap.ui.model.resource.ResourceModel({ bundleName : "sap.ui.demo.db.i18n" }); // Assign the model object to the SAPUI5 core using the name "i18n" sap.ui.getCore().setModel(oResourceBundle, "i18n"); // Display the XML view called "App" new sap.ui.core.mvc.XMLView({ viewName : "sap.ui.demo.db.views.App" }). placeAt("content"); }); ...SNIP...

In the same way that the path to the XML view can be derived using the fully qualified namespace "sap.ui.demo.db.views.App", so the path to the i18n file can be derived from the namespace "sap.ui.demo.i18n.i18n". Since we are creating a resource model, the file name is assumed to have the extension ".properties"; therefore this does not need to be stated. The resource model is then attached to the SAPUI5 core using the model name "i18n".

July 2015

19

SAPUI5 Tutorial – Data Binding

6.3. ./i18n/i18n.properties (New file in new folder) Within your DataBinding folder, create a new folder called i18n. Within the new i18n folder, create a New file called i18n.properties and paste into it the following text: # Field labels firstName=First Name lastName=Last Name enabled=Enabled # Screen titles HeaderText=Data Binding Basics

The HeaderText property has been moved from the model object into the i18n resource bundle, and also the field labels are no longer hard coded in the XML View. This is because all of these text fields need to be translated. Language specific text is stored in Resource Models and is formatted according to the Java convention for resource bundle files.

6.4. ./views/App.view.xml <mvc:View xmlns="sap.m" xmlns:mvc="sap.ui.core.mvc"> < headerText="{i18n>HeaderText}" class="sapUiResponsiveMargin" width="auto">

Modify the data binding for the header and the labels in App.view.xml to include the model name. Notice that a "greater than" character separates the model name and the property name, and that i18n property names must not start with a slash character!

Important All binding paths are case-sensitive!

July 2015

20

SAPUI5 Tutorial – Data Binding

Explanation The diagram seen above in Step 0 can now be extended to include the Resource Model. For simplicity, only the data binding for one Label UI Control is shown.

sap.m. sap.m.CheckBox

sap.m.Label

sap.m.Input

selected:%"{/enabled}"

text:%"{i18n>lastName}"

value:%"{/lastName}" enabled:%"{/enabled}"

Data Binding Model Instance “i18n”

Resource Model

Data Binding Model Instance

JSON Model

i18n.properties

July 2015

21

SAPUI5 Tutorial – Data Binding

Step 7:

(Optional) Resource Bundles and Multiple Languages

The reason we have resource bundles is to allow an app to run in multiple languages without the need to change any coding. To demonstrate this feature, we will create a German version of the above app – in fact all we need to do is create a German version of the resource bundle file. No coding changes are needed.

7.1.

Preview

7.2. ./i18n/i18n_de.properties (New file) In the i18n folder, take a copy of the file i18n.properties and call it i18n_de.properties. Change the English text to the following German text. # Field labels firstName=Vorname lastName=Nachname enabled=Aktiviert # Screen titles HeaderText=Data Binding Grundlagen

7.3. Behaviour If it is not set already, change the default language of your browser to German. Now press refresh in the Application Preview screen and the German text will be used automatically. This works because SAPUI5 takes into the language setting of your browser when calculating which resource bundle file to open. Assuming that your browser has been configured to use "Queen's English" (that is, en-GB, the English spoken in England), then SAPUI5 will make an HTTP request for exactly this resource bundle.

July 2015

22

SAPUI5 Tutorial – Data Binding

However, if the request returns an HTTP 404 (File not found), then SAPUI5 requests a less specific version of the resource bundle. The following search order is used: 1. Request an exact match of both language and region

 i18n_en_GB.properties

2. Request the exact language, but ignore the region

 i18n_en.properties

3. Request the default (non-language specific) resource bundle

 i18n.properties

Since English is the default language for most business applications, it is typical for the non-language specific resource bundle i18n.properties to contain English text. When you've finished this step, don't forget to change your browser back to its normal default language!

Be Careful With Language Determination! In this code sample, we have assumed that the language information defined in the browser can be used to determine the language in which the particular business application should be run. This assumption might prove to be false! Particularly in multi-national organisations, it is common to find s that have their browser set to their own local language (say French), but actually run all SAP business applications in the corporate standard language (typically English). Therefore, the determination of the application language cannot necessarily be determined from the browser's default language setting. In a real world (I.E. complex) business scenario however, the language in which a business application should run is usually determined by a process similar to the following:

1. Most corporations implement a single sign-on policy. Therefore, before a business application can be started, the must have first been authenticated by an identity provider such as the corporate LDAP.

2. Once authenticated, the identity provider will typically supply the client with credentials. This information should include the business application language.

3. The browser's default language setting can then be ignored when determining the language in which the SAPUI5 app should be run. Since this tutorial focuses on data binding, it is beyond the scope of this document to deal with such issues in any further detail.

July 2015

23

SAPUI5 Tutorial – Data Binding

Step 8:

Binding Paths – Accessing Properties in Hierarchically Structured Models

In Resource Models, we stated that the fields in a Resource Model are arranged in a flat structure; in other words, there can be no hierarchy of properties; however, this is true only for Resource Models. The properties within JSON and OData models almost always are arranged in a hierarchical structure. Therefore, we should take a look at how to reference fields in a hierarchically structured model object.

8.1. Preview

July 2015

24

SAPUI5 Tutorial – Data Binding

8.2. ./index.html ... SNIP ... <script> // -----------------------------------------------------------------------// Attach an anonymous function to the SAPUI5 'init' event sap.ui.getCore().attachInit(function () { var oModel = new sap.ui.model.json.JSONModel({ firstName : "Harry", lastName : "Hawk", enabled : true, dateOfBirth : { day : 3, month : 8, year : 1987 } }); ... SNIP ...

The JSON model object now contains an additional sub-object called dateOfBirth. Within this object are three properties: day, month and year.

8.3. ./views/App.view.xml <mvc:View xmlns="sap.m" xmlns:mvc="sap.ui.core.mvc"> < headerText="{i18n>1HeaderText}" class="sapUiResponsiveMargin" width="auto"> < headerText="{i18n>2HeaderText}" class="sapUiResponsiveMargin" width="auto">

A new has been added to the XML view in which a new

Explanation The changes to the coding are minimal: 1. The XML view is now created as a named object called oView. 2. The view object oView is ed with the Message Manager in the SAPUI5 core. 3. Once ed, the XML view is then inserted into the DOM as before.

Behaviour Enter a non-numeric value into the "Sales To Date" field and either press enter or tab to move the focus to a different UI control. This action triggers either the onenter or onchange event and the SAPUI5 core then executes the validation function belonging to the sap.ui.model.type.Currency data type. Now that the view has been ed with the Message Manager, any validation error messages will be picked up by the Message Manager, which in turn checks its list of ed objects and es the error message back to the correct view for display. Notice that the field in error will always have a red border: However, the error message itself will only be displayed when that particular field has focus:

July 2015

44

SAPUI5 Tutorial – Data Binding

Step 13: Element Binding Up until now we have used examples in which a single model property is bound to a single UI control. This is fine as far as it goes, but the problem is, it doesn't go very far – particularly when we need to write real-life business applications in which multiple occurrences of the same data structure need to be displayed in UI controls such as lists or tables. So now we will take the next step and look at element binding.

13.1. Preview

July 2015

45

SAPUI5 Tutorial – Data Binding

13.2. ./views/App.view.xml ... SNIP ... < headerText="{i18n>3HeaderText}" class="sapUiResponsiveMargin" width="auto">

A new <> element has been inserted at the end of the XML view. This contains a element in which a list of invoices will be displayed. Within the element of the the number and numberUnit properties are bound to a currency value and currency code exactly as was done in the previous step. An has been created that adds an extra text field to each list item. The status property belonging to each invoice item is translated from the single character "A", "B", or "C" into a meaningful text message using the formatter function getStatusText.

13.3. ./models/model.json ... SNIP ... "salesToDate" : 12345.6789, "currencyCode" : "EUR", "invoices": [{ "ProductName": "Pineapple", "Quantity": 21, "ExtendedPrice": 87.2000, "ShipperName": "Fun Inc.", "ShippedDate": "2015-04-01T00:00:00", "Status": "A" }, { "ProductName": "Milk", "Quantity": 4, "ExtendedPrice": 9.99999, "ShipperName": "ACME", "ShippedDate": "2015-02-18T00:00:00", "Status": "B" }, {

July 2015

46

SAPUI5 Tutorial – Data Binding

"ProductName": "Canned Beans", "Quantity": 3, "ExtendedPrice": 6.85000, "ShipperName": "ACME", "ShippedDate": "2015-03-02T00:00:00", "Status": "B" }, { "ProductName": "Salad", "Quantity": 2, "ExtendedPrice": 8.8000, "ShipperName": "ACME", "ShippedDate": "2015-04-12T00:00:00", "Status": "C" }, { "ProductName": "Bread", "Quantity": 1, "ExtendedPrice": 2.71212, "ShipperName": "Fun Inc.", "ShippedDate": "2015-01-27T00:00:00", "Status": "A" }] }

13.4. ./controllers/formatter.js ... SNIP ... // ------------------------------------------------------------------------var getStatusText = function(sStatus) { // As long as the status code can be found in the array containing the values // "A", "B" and "C" (we don't care where), then we know the status code is valid // and can then be used to derive the i18n key name. // If not, we simply return the status code return (["A","B","C"].indexOf(sStatus) > -1) ? this.getView().getModel("i18n").getProperty("status" + sStatus) : sStatus; }; // ------------------------------------------------------------------------return { dateFormatter : dateFormatter, getCurrencySymbol : getCurrencySymbol, getStatusText : getStatusText }; });

Array.indexOf() tests for hip in an array. Therefore, we can use this as a quick way to test whether the supplied value belongs to a list of known values. Each of our known values (“A”, “B”, or “C”) is listed as an array element, then we test whether indexOf() returns a value greater than minus one. This is a simple test for hip, so as long as indexOf() does not return -1, we don’t care about exactly where in the array this element is found. This is avoids the need to write a bulky switch or nested if statement.

July 2015

47

SAPUI5 Tutorial – Data Binding

13.5. ./i18n/i18n.properties # Screen titles 1HeaderText=Data Binding Basics 2HeaderText=Formatting 3HeaderText=Element Binding # Invoice List invoiceListTitle=Invoices statusA=New statusB=In Progress statusC=Done # Error messages invalidDate=Invalid Date Format

13.6. ./i18n/i18n_de.properties # Screen titles 1HeaderText=Data Binding Grundlagen 2HeaderText=Formatieren 3HeaderText=Element Binding # Invoice List invoiceListTitle=Rechnungen statusA=Neu statusB=Laufen statusC=Abgeschlossen # Error messages invalidDate=Ungültiges Datumsformat

Explanation In contrast to property binding, in which you bind the property of a UI control to a single property in a model, element binding is where you bind a UI control to an entire object within a model (or possibly even the entire model object itself). Once the entire UI control has been bound to an object in the model, all the subordinate model objects can be referenced using a relative binding path name: that is, when binding the property of a UI Control, you only need use a relative binding path address. Within the JSON model, we have a new array called invoices. Every element in the invoices array must necessarily have the same structure. "invoices": [{ "ProductName": "Pineapple", "Quantity": 21, "ExtendedPrice": 87.2000, "ShipperName": "Fun Inc.", "ShippedDate": "2015-04-01T00:00:00", "Status": "A" }, { ... SNIP ... }]

July 2015

48

SAPUI5 Tutorial – Data Binding

In the coding for the XML view, notice that the items parameter of the element is bound to the /invoices object in the JSON model. This means that every item displayed in this list will be drawn from this array. ... SNIP ...

Now, from the perspective of the within the element, all data binding references can assume that their binding path is relative to the /invoices object. This means that none of the data binding references highlighted below need to start with a slash character (because that would indicate an absolute binding reference).

July 2015

49

SAPUI5 Tutorial – Data Binding

Step 14: Expression Binding Expression binding allows you to display a value on the screen that has been calculated from values found in some model object. As long as the computation is neither complex nor expensive, it can be inserted directly into the data binding string. In this example, we will change the colour of the price depending on whether it is above or below some arbitrary threshold. The threshold value is also stored in the JSON model.

14.1. Preview

July 2015

50

SAPUI5 Tutorial – Data Binding

14.2. ./views/App.view.xml ... SNIP ... < headerText="{i18n>3HeaderText}" class="sapUiResponsiveMargin" width="auto">

In the XML view, the element within the has had a new numberState property added. The value of this property is a simple expression that will be evaluated for each item. As a result of binding an expression to the numberState property, the error status (colour) of the price field will change depending on the invoice value.

14.3. ./models/model.json ... SNIP ... "salesToDate" : 12345.6789, "priceThreshold" : 50, "currencyCode" : "EUR", "invoices": [{ "ProductName": "Pineapple", ... SNIP ...

The JSON model has a new property called priceThreshold added against which each invoice value will be checked.

July 2015

51

SAPUI5 Tutorial – Data Binding

Warning! Look at the following two expressions: numberState="{= ${ExtendedPrice} > ${/priceThreshold} ? 'Error' : 'Success' }">

numberState="{= ${ExtendedPrice} <= ${/priceThreshold} ? 'Success' : 'Error' }">

Can you see why one of these expressions will work, and the other will not? Logically, both expressions are identical; yet the first one works, and the second does not: it produces only an empty screen and an "Invalid XML" message in the browser's console… Hmmm, what's going on here?

Understanding Syntax Collisions In order to understand why this situation occurs, you must understand how XML files are parsed. When an XML file is parsed, certain characters have a special (that is, high priority) meaning to the XML parser. When such characters are encountered, they are always interpreted to be part of the XML definition itself and not part of any other content that might exist within the XML document. 1 As soon as the XML parser encounters one of these high-priority characters (in this case, a less-than ("<") character), it will always be interpreted as the start of a new XML tag – irrespective of any other meaning that character might have within the context of the SAPUI5 expression. This is known as a syntax collision. In this case the collision occurs between the syntax of XML and the syntax of the JavaScript-like expression language used by SAPUI5. Therefore, this statement fails because the less-than character is interpreted as the start of an XML tag: numberState="{= ${ExtendedPrice} <= ${/priceThreshold} ? 'Success' : 'Error' }">

This particular problem can be avoided in one of two ways, either: 

Reverse the logic of the condition (use "greater than or equal to" instead of "less than"), or



Use the escaped value for the less-than character:

numberState="{= ${ExtendedPrice} <= ${/priceThreshold} ? 'Success' : 'Error' }">

Since the use of an escaped character is not so easy to read, the preferred approach is (where possible) to reverse the logic of the condition and use a greater-than character instead. The ampersand ("&") character also has a high priority meaning to the XML parser. This character will always be interpreted to mean "The start of an escaped character". So if you wish to use the Boolean AND operator ("&&") in a condition, you must escape both ampersand characters. "&&"  "&&".

1

XML does allow for special characters such as “greater than” and ampersand, but only when contained inside a CDATA section.

July 2015

52

SAPUI5 Tutorial – Data Binding

Step 15: Aggregation Binding Using A Template Conceptually, aggregation binding is very similar to element binding. Both allow a UI control to be bound to some object within the model data, and both create a binding context within the scope of the UI control that in turn, allows relative binding to be used by any and all child controls. The difference is that aggregation binding will automatically create as many child UI controls as are needed to display the data in the model object using one of the following two approaches: 1. Create a template UI control that is then cloned as many times as needed to display the data. 2. Use a factory function to generate the correct UI control based on the data received at runtime.

15.1. Preview

July 2015

53

SAPUI5 Tutorial – Data Binding

15.2. ./views/App.view.xml ... SNIP ...
< headerText="{i18n>4HeaderText}" class="sapUiResponsiveMargin" width="auto">

July 2015

54

SAPUI5 Tutorial – Data Binding

15.3. ./controllers/App.controller.js sap.ui.define(["sap/ui/core/mvc/Controller", "sap/ui/demo/db/controllers/formatter"], function(Controller,Formatter) { "use strict"; // ---------------------------------------------------------------------var initialise = function() { var oModel = new sap.ui.model.json.JSONModel(); oModel.loadData("./models/model.json"); this.getView().setModel(oModel); var oProductModel = new sap.ui.model.json.JSONModel(); oProductModel.loadData("./models/Products.json"); this.getView().setModel(oProductModel,"products"); var oResourceBundle = new sap.ui.model.resource.ResourceModel({ bundleName : "sap.ui.demo.db.i18n.i18n" }); // Assign the resource model to the current view using the name "i18n" this.getView().setModel(oResourceBundle, "i18n"); }; // ------------------------------------------------------------------------return Controller.extend("sap.ui.demo.db.controllers.App", { onInit : initialise, formatter : Formatter }); });

15.4. ./controllers/formatter.js ... SNIP ... var sBrowserLocale var oLocale var oLocaleData var oCurrency

= = = =

sap.ui.getCore().getConfiguration().getLanguage(); new sap.ui.core.Locale(sBrowserLocale); new sap.ui.core.LocaleData(oLocale); new sap.ui.model.type.Currency(oLocaleData.mData.currencyFormat);

... SNIP ... // ------------------------------------------------------------------------var getStockValue = function(fUnitPrice, iStockLevel, sCurrCode) { return oCurrency.formatValue([fUnitPrice * iStockLevel, getCurrencySymbol(sCurrCode)],"string"); }; // ------------------------------------------------------------------------return { dateFormatter : dateFormatter, getCurrencySymbol : getCurrencySymbol, getStatusText : getStatusText, getStockValue : getStockValue }; });

Notice that within function getStockValue, there is a call to another formatter function: getCurrencySymbol. This reference would not be possible if each function within formatter.js were declared directly within the returned object.

July 2015

55

SAPUI5 Tutorial – Data Binding

15.5. ./i18n/i18n.properties ... SNIP ... # Screen titles 1HeaderText=Data Binding Basics 2HeaderText=Formatting 3HeaderText=Element Binding 4HeaderText=Aggregation Binding # Invoice List invoiceListTitle=Invoices statusA=New statusB=In Progress statusC=Done # Error messages invalidDate=Invalid Date Format # Product list productListTitle=Product List stockValue=Current Stock Value

15.6. ./i18n/i18n_de.properties (Optional) ... SNIP ... # Screen titles 1HeaderText=Data Binding Basics 2HeaderText=Formatting 3HeaderText=Element Binding 4HeaderText=Aggregation Binding # Invoice List invoiceListTitle=Rechnungen statusA=Neu statusB=Laufen statusC=Abgeschlossen # Error messages invalidDate=Ungültiges Datumsformat # Product list productListTitle=Artikelliste stockValue=Lagerbestand Wert

July 2015

56

SAPUI5 Tutorial – Data Binding

15.7. ./models/Products.json (New file) { "Products": [ { "ProductID": 1, "ProductName": "Chai", "SupplierID": 1, "CategoryID": 1, "QuantityPerUnit": "10 boxes x 20 bags", "UnitPrice": "18.0000", "UnitsInStock": 39, "UnitsOnOrder": 0, "ReorderLevel": 10, "Discontinued": false }, { "ProductID": 2, "ProductName": "Chang", "SupplierID": 1, "CategoryID": 1, "QuantityPerUnit": "24 - 12 oz bottles", "UnitPrice": "19.0000", "UnitsInStock": 17, "UnitsOnOrder": 40, "ReorderLevel": 25, "Discontinued": false }, { "ProductID": 3, "ProductName": "Aniseed Syrup", "SupplierID": 1, "CategoryID": 2, "QuantityPerUnit": "12 - 550 ml bottles", "UnitPrice": "10.0000", "UnitsInStock": 13, "UnitsOnOrder": 70, "ReorderLevel": 25, "Discontinued": false }, { "ProductID": 4, "ProductName": "Chef Anton's Cajun Seasoning", "SupplierID": 2, "CategoryID": 2, "QuantityPerUnit": "48 - 6 oz jars", "UnitPrice": "22.0000", "UnitsInStock": 53, "UnitsOnOrder": 0, "ReorderLevel": 0, "Discontinued": false }, { "ProductID": 5, "ProductName": "Chef Anton's Gumbo Mix", "SupplierID": 2, "CategoryID": 2, "QuantityPerUnit": "36 boxes", "UnitPrice": "21.3500", "UnitsInStock": 0, "UnitsOnOrder": 0, "ReorderLevel": 0, "Discontinued": true }, { "ProductID": 6, "ProductName": "Grandma's Boysenberry Spread", "SupplierID": 3, "CategoryID": 2, "QuantityPerUnit": "12 - 8 oz jars",

July 2015

57

SAPUI5 Tutorial – Data Binding

"UnitPrice": "25.0000", "UnitsInStock": 120, "UnitsOnOrder": 0, "ReorderLevel": 25, "Discontinued": false }, { "ProductID": 7, "ProductName": "Uncle Bob's Organic Dried Pears", "SupplierID": 3, "CategoryID": 7, "QuantityPerUnit": "12 - 1 lb pkgs.", "UnitPrice": "30.0000", "UnitsInStock": 0, "UnitsOnOrder": 0, "ReorderLevel": 10, "Discontinued": false }, { "ProductID": 8, "ProductName": "Northwoods Cranberry Sauce", "SupplierID": 3, "CategoryID": 2, "QuantityPerUnit": "12 - 12 oz jars", "UnitPrice": "40.0000", "UnitsInStock": 6, "UnitsOnOrder": 0, "ReorderLevel": 0, "Discontinued": false }, { "ProductID": 9, "ProductName": "Mishi Kobe Niku", "SupplierID": 4, "CategoryID": 6, "QuantityPerUnit": "18 - 500 g pkgs.", "UnitPrice": "97.0000", "UnitsInStock": 29, "UnitsOnOrder": 0, "ReorderLevel": 0, "Discontinued": true }, { "ProductID": 10, "ProductName": "Ikura", "SupplierID": 4, "CategoryID": 8, "QuantityPerUnit": "12 - 200 ml jars", "UnitPrice": "31.0000", "UnitsInStock": 31, "UnitsOnOrder": 0, "ReorderLevel": 0, "Discontinued": false }, { "ProductID": 11, "ProductName": "Queso Cabrales", "SupplierID": 5, "CategoryID": 4, "QuantityPerUnit": "1 kg pkg.", "UnitPrice": "21.0000", "UnitsInStock": 22, "UnitsOnOrder": 30, "ReorderLevel": 30, "Discontinued": false }, { "ProductID": 12, "ProductName": "Queso Manchego La Pastora",

July 2015

58

SAPUI5 Tutorial – Data Binding

"SupplierID": 5, "CategoryID": 4, "QuantityPerUnit": "10 - 500 g pkgs.", "UnitPrice": "38.0000", "UnitsInStock": 86, "UnitsOnOrder": 0, "ReorderLevel": 0, "Discontinued": false }, { "ProductID": 13, "ProductName": "Konbu", "SupplierID": 6, "CategoryID": 8, "QuantityPerUnit": "2 kg box", "UnitPrice": "6.0000", "UnitsInStock": 0, "UnitsOnOrder": 0, "ReorderLevel": 5, "Discontinued": false }, { "ProductID": 14, "ProductName": "Tofu", "SupplierID": 6, "CategoryID": 7, "QuantityPerUnit": "40 - 100 g pkgs.", "UnitPrice": "23.2500", "UnitsInStock": 35, "UnitsOnOrder": 0, "ReorderLevel": 0, "Discontinued": false }, { "ProductID": 15, "ProductName": "Genen Shouyu", "SupplierID": 6, "CategoryID": 2, "QuantityPerUnit": "24 - 250 ml bottles", "UnitPrice": "15.5000", "UnitsInStock": 39, "UnitsOnOrder": 0, "ReorderLevel": 5, "Discontinued": false }, { "ProductID": 16, "ProductName": "Pavlova", "SupplierID": 7, "CategoryID": 3, "QuantityPerUnit": "32 - 500 g boxes", "UnitPrice": "17.4500", "UnitsInStock": 29, "UnitsOnOrder": 0, "ReorderLevel": 10, "Discontinued": false }, { "ProductID": 17, "ProductName": "Alice Mutton", "SupplierID": 7, "CategoryID": 6, "QuantityPerUnit": "20 - 1 kg tins", "UnitPrice": "39.0000", "UnitsInStock": 0, "UnitsOnOrder": 0, "ReorderLevel": 0, "Discontinued": true

July 2015

59

SAPUI5 Tutorial – Data Binding

}, { "ProductID": 18, "ProductName": "Carnarvon Tigers", "SupplierID": 7, "CategoryID": 8, "QuantityPerUnit": "16 kg pkg.", "UnitPrice": "62.5000", "UnitsInStock": 42, "UnitsOnOrder": 0, "ReorderLevel": 0, "Discontinued": false }, { "ProductID": 19, "ProductName": "Teatime Chocolate Biscuits", "SupplierID": 8, "CategoryID": 3, "QuantityPerUnit": "10 boxes x 12 pieces", "UnitPrice": "9.2000", "UnitsInStock": 25, "UnitsOnOrder": 0, "ReorderLevel": 5, "Discontinued": false }, { "ProductID": 20, "ProductName": "Sir Rodney's Marmalade", "SupplierID": 8, "CategoryID": 3, "QuantityPerUnit": "30 gift boxes", "UnitPrice": "81.0000", "UnitsInStock": 40, "UnitsOnOrder": 0, "ReorderLevel": 0, "Discontinued": false }] }

July 2015

60

SAPUI5 Tutorial – Data Binding

Step 16: Aggregation Binding Using A Factory Function Now, instead of hardcoding a single template UI control, we will use a factory function to generate different UI controls based on the data received at runtime. This approach is much more flexible and allows complex or heterogeneous data to be displayed.

16.1. Preview

July 2015

61

SAPUI5 Tutorial – Data Binding

16.2. ./views/App.view.xml ... SNIP ...
< headerText="{i18n>4HeaderText}" class="sapUiResponsiveMargin" width="auto">

The XML element that previously held the product list is now reduced simply to a named, but otherwise empty placeholder. Without a factory function to populate it, this would always remain empty.

July 2015

62

SAPUI5 Tutorial – Data Binding

16.3. ./i18n/i18n.properties ... SNIP ... # Error messages invalidDate=Invalid Date Format # Product list productListTitle=Product List stockValue=Current Stock Value outOfStock=Out of Stock discontinued=Product Discontinued unitsInStock=Stock Level

16.4. ./i18n/i18n_de.properties (Optional) ... SNIP ... # Error messages invalidDate=Ungültiges Datumsformat # Product list productListTitle=Artikelliste stockValue=Lagerbestand Wert outOfStock=Nicht Vorrätig discontinued=Produkt Eingestellt unitsInStock=Lagerbestandsverlauf

16.5. ./controllers/App.controller.js sap.ui.define(["sap/ui/core/mvc/Controller", "sap/ui/demo/db/controllers/formatter"], function(Controller, Formatter) { "use strict"; // ------------------------------------------------------------------------var productListFactory = function(sId, oContext) { var oUIControl = null; // Define the item description var sDescription = oContext.getProperty("ProductName") + " (" + oContext.getProperty("QuantityPerUnit") + ")"; // Is this item both out of stock *and* discontinued? if (oContext.getProperty("UnitsInStock") === 0 && oContext.getProperty("Discontinued")) { // Yup, so use a StandardListItem oUIControl = new sap.m.StandardListItem(sId, { icon : "sap-icon://warning", title : sDescription, info : { path: "i18n>discontinued" }, infoState : "Error" }); } else { // Nope, so we will create an ObjectListItem oUIControl = new sap.m.ObjectListItem(sId, { title : sDescription, number : { parts: [{path: "products>UnitPrice"},

July 2015

63

SAPUI5 Tutorial – Data Binding

{path: "/currencyCode"}], type: "sap.ui.model.type.Currency", formatOptions: {showMeasure: false} }, numberUnit : { path: "/currencyCode", formatter: Formatter.getCurrencySymbol } }); // Is this item in stock? if (oContext.getProperty("UnitsInStock") > 0) { // First object attribute displays the current stock level oUIControl.addAttribute(new sap.m.ObjectAttribute({ title : { path: "i18n>unitsInStock" }, text : { path: "products>UnitsInStock" } })); // Second object attribute displays the current stock value oUIControl.addAttribute(new sap.m.ObjectAttribute({ title : { path: "i18n>stockValue" }, text : { parts: [{path: "products>UnitPrice"}, {path: "products>UnitsInStock"}, {path: "/currencyCode"}], formatter: Formatter.getStockValue } })); // Has this product been discontinued? if (oContext.getProperty("Discontinued")) { // Yup, so we're selling off the last remaining stock items // Set the status of the first attribute to "discontinued" oUIControl.setFirstStatus(new sap.m.ObjectStatus({ text: { path: "i18n>discontinued" }, state: "Error" })); } } else { // Nope, so this item is just temporarily out of stock oUIControl.addAttribute(new sap.m.ObjectAttribute({ text : { path: "i18n>outOfStock" } })); } } return oUIControl; }; // ---------------------------------------------------------------------var initialise = function() { var oModel = new sap.ui.model.json.JSONModel(); oModel.loadData("./models/model.json"); this.getView().setModel(oModel); var oProductModel = new sap.ui.model.json.JSONModel(); oProductModel.loadData("./models/Products.json"); this.getView().setModel(oProductModel,"products"); var oResourceBundle = new sap.ui.model.resource.ResourceModel({ bundleName : "sap.ui.demo.db.i18n.i18n" }); // Assign the resource model to the current view using the name "i18n" this.getView().setModel(oResourceBundle, "i18n");

July 2015

64

SAPUI5 Tutorial – Data Binding

// Get a reference to the Product List using the XML element's id var oProductList = this.getView().byId("ProductList"); // In addition to binding the "items" aggregation in the list to the // Products array in the "products" model, the productListFactory function // is also ed as a parameter oProductList.bindAggregation("items", "products>/Products", productListFactory); }; // ------------------------------------------------------------------------return Controller.extend("sap.ui.demo.db.controllers.App", { onInit : initialise, formatter : Formatter }); });

In the App controller, a new function called productListFactory has been created. The types of UI Control returned from this factory function must be limited to those suitable for inclusion in the items aggregation of a sap.m.List object. In this case, we will return either a StandardListItem or an ObjectListItem using the following logic: We decide which type of UI control to return by checking the current stock level and whether or not the product has been discontinued. This creates four possible responses: 1. First, eliminate the minority case. If the stock level is zero and the product has also been discontinued, then use a StandardListItem with a warning icon and a "Product Discontinued" message in the status property. All other possibilities will use an ObjectListItem.

2. Create an ObjectListItem then test for the majority case. The product is in stock and has not been discontinued, so add two ObjectAttributes to the ObjectListItem to display the current stock level and value.

3. The product is in stock but has also been discontinued, so we are simply selling off the last remaining stock items. Therefore, in addition to the two ObjectAttributes added above, use the status property of the first attribute to indicate that this product has been discontinued.

4. The product has not been discontinued but the stock level is zero, therefore we are temporarily out of stock. In this case, add a single ObjectAttribute that displays the "Out of Stock" message.

July 2015

65

www.sap.com/sap www.sdn.sap.com/irj/sdn/howtoguide s

Related Documents 3m3m1z

Data Binding In Sapui5 665g4q
June 2022 0
Data Binding With Tabular Data Control 1t6q29
February 2022 0
Sapui5 Syllabus 566h1k
November 2021 0
Html,dhtml,xml,xml Data Binding Programs 5f1j4k
November 2019 42
Sapui5 Codejam V2 (1) 4n5zh
November 2022 0
Coptic Binding 5r2l1j
December 2019 43

More Documents from "Praveen Kumar" 5q232y

Ferrocrete 67l5q
October 2019 58
Vhdl 3k6g2o
October 2020 0
Hyphenated Techniques 453q40
July 2021 0
Guide To Fmge 3t3g48
January 2022 0
Netweaver Gateway T Code Summary 493p4l
August 2022 0
Data Binding In Sapui5 665g4q
June 2022 0