Using models.js in SAP UI5 (to maintain all Global Models)

by | Dec 27, 2022 | SAP, UI5, UI5 Programs

Preface – This post is part of the UI5 Programs series.

What is model.js file in SAP UI5?

A model in terms of UI5 is a set of data (mostly in JSON format) that can be binded with elements of UI5. For different properties of different elements, the type of model data differs, for example:

  • For the property “visible” of a button, the required model (Data within the model) should be either true or false
  • For the property “text” of a button, the required model (Data within the model) should be a string
  • For the data of the table, the required model should be a JSON data
  • For the data of Drop down, the required model should be JSON data [where one field should act as a key and another as value]
  • For the data of Table count that is shown next to the table name [Example User(90)], the required model (Data within the model) should be a numeric
  • For the data of a Form, the required model should be an Object [with multiple keys and values, where each key will be an element of the form]
  • In case you need to transfer login details to multiple pages, the required model should be an Object [where the key-value pair will save ID and hashed session password/data]

The model.js in SAP UI5 is a dedicated file to save multiple global variables that can hold data (commonly known as a model) as per requirement.

The model data refreshes to initial values every time the browser is refreshed; hence it is recommended not to save any data that is required not to be lost during browser refresh.

The layout of the model.js looks something like this in the folder structure:

model.js file

Setting up a Global Model using model.js file in SAP UI5

There are three steps to using a Global Model.

1. Create a model object in Model.js file

The first step is to create a model in model.js file. The model.js file is already created within the model folder of webapp. In case their is no such file, create a file, name it “model.js” with given content:

sap.ui.define([
    "sap/ui/model/json/JSONModel",
    "sap/ui/Device"
], function (JSONModel, Device) {
    "use strict";
    return {
        createDeviceModel: function () {
            var oModel = new JSONModel(Device);
            oModel.setDefaultBindingMode("OneWay");
            return oModel;
        }
    };
});

Now, we will add our own code within this file. Let us call it “createAppConfigModel” with given data:

//app Congiguration model
createAppConfigModel: function () {
    var appData = {
        "editable": false,
        "count": 0,
        "formData": {},
        "tableData": []
    };
    var oModel = new JSONModel(appData);
    return oModel;
}

Now, your Model.js will look like this:

sap.ui.define([
    "sap/ui/model/json/JSONModel",
    "sap/ui/Device"
], function (JSONModel, Device) {
    "use strict";
    return {
        createDeviceModel: function () {
            var oModel = new JSONModel(Device);
            oModel.setDefaultBindingMode("OneWay");
            return oModel;
        },
        //app Congiguration model
        createAppConfigModel: function () {
            var appData = {
                "editable": false,
                "count": 0,
                "formData": {},
                "tableData": []
            };
            var oModel = new JSONModel(appData);
            return oModel;
        }
    };
});

 

2. Configure the Component.js file for the Global Model Object

In the Component.js file, in case your Model.js file was already there, the model configuration is added like this:

sap.ui.define([
    "sap/ui/core/UIComponent",
    "sap/ui/Device",
    "YRR/YRR/model/models"
], function (UIComponent, Device, models) {
    "use strict";
    return UIComponent.extend("YRR.YRR.Component", {
        metadata: {
            manifest: "json"
        },
        /**
         * The component is initialized by UI5 automatically during the startup of the app and calls the init method once.
         * @public
         * @override
         */
        init: function () {
            // call the base component's init function
            UIComponent.prototype.init.apply(this, arguments);
            // enable routing
            this.getRouter().initialize();
            // set the device model
            this.setModel(models.createDeviceModel(), "device");

        }
    });
});

Here, the model file location is added at the top as “YRR/YRR/model/models” and thereafter in the end the default model is configured using this ” this.setModel(models.createDeviceModel(), “device”);”

We need to add one more configuration, for our model with this code: “this.setModel(models.createAppConfigModel(), “AppConfig”);”

Now, the code will look like this:

sap.ui.define([
    "sap/ui/core/UIComponent",
    "sap/ui/Device",
    "YRR/YRR/model/models"
], function (UIComponent, Device, models) {
    "use strict";
    return UIComponent.extend("YRR.YRR.Component", {
        metadata: {
            manifest: "json"
        },
        /**
         * The component is initialized by UI5 automatically during the startup of the app and calls the init method once.
         * @public
         * @override
         */
        init: function () {
            // call the base component's init function
            UIComponent.prototype.init.apply(this, arguments);
            // enable routing
            this.getRouter().initialize();
            // set the device model
            this.setModel(models.createDeviceModel(), "device");
            // set the app Config model
            this.setModel(models.createAppConfigModel(), "AppConfig");
        }
    });
});

That’s it, and we have a global model now.

3. Using the model in view or Controller

Now, we can easily access the model in view and controller. Also, we can manipulate the model from the controller.

How to fetch and change values of a Global Model in SAP UI5?

To fetch a global model, we need to call the model configuration with the model name we want to access or modify. Let’s assume you need to access the model “count” whose initial value is set as 0.

var localCount = this.getOwnerComponent().getModel("AppConfig").getProperty("/count");

The variable “localCount” will now have the value of 0.

To change the value, we need to call the model configuration with the model name we want to modify. Let’s assume you need to modify the model “count” with a new value as 90.

this.getOwnerComponent().getModel("AppConfig").setProperty("/count", 90);

In the above step, we have updated the value of the count in the global model.

How to use Global Model to send values from one page to another?

To send values from one page to another, you need to perform these steps:

1. Create a field in the global model that will be used to transfer data

2. Update the value of the model on the first page, then navigate to the second page

3. On the second page, get the value of the model

All these steps are already discussed above in different sections.

How to bind the global model directly to View?

To bind a global model directly to the view, you need to perform the following as per the given use cases:

1. Bind Global Model to a Button Text

<Button icon="sap-icon://accept" visible="true" text="{AppConfig>/ButtonText}" 
type="Accept" class="sapUiTinyMarginEnd" press="onAccept"/>

In this example, we have assumed that the ButtonText is a field in the model having the text value of Button.

2. Bind Global Model to the visibility of a button

<Button visible="{=${AppConfig>/OrderType} === 'PO Release' ? true : false}" text="Okay" press="onReleasePO"/>
<Button visible="{=${AppConfig>/OrderType} === 'Cancel PO Release' ? true : false}" text="Okay" press="onCancelReleasePO"/>

In this example, Button 1 gets visible if the OrderType has the value ‘PO Release’, else becomes invisible.
And Button 2 gets visible if the OrderType has the value ‘Cancel PO Release’, else becomes invisible.
In this way, we can control the visibility of a button based on OrderType with the help of the Global Model.

3. Bind Global Model to a table [if Model is JSON]

It is important to have the Model that is being planned to bind with a table to have a format as below:

{results: [{<JSON Data>}]};

It means if your model has just an array of data in this form: [{<JSON Data>}] or {“results”: {JSON Data}}
in both cases, the model binding will fail.

Controller Code:

sap.ui.define([
    "sap/ui/core/mvc/Controller"
], function (Controller) {
    "use strict";
    return Controller.extend("Test.Test.controller.Main", {
        onInit: function () {
        },
        onBeforeRendering: function () {
            var that = this;
            var val = {
                country_code: 1,
                country_text: "India"
            };
            var aData = [];
            aData.push(val);
            that.getOwnerComponent().getModel("AppConfig").setProperty("/tableData", {
                "results": aData
            });
        }
    });
});

View Code:

<mvc:View controllerName="Test.Test.controller.Main" xmlns:mvc="sap.ui.core.mvc" displayBlock="true" xmlns="sap.m" xmlns:core="sap.ui.core"
    xmlns:html="http://www.w3.org/1999/xhtml">
    <Shell id="shell">
        <App id="app">
            <pages>
                <Page id="page" title="Table Binding">
                    <content>
                        <Table id="idTable" items="{AppConfig>/tableData/results}">
                            <columns>
                                <Column><Text text="Country Code"/></Column>
                                <Column><Text text="Country Text"/></Column>
                            </columns>
                            <items>
                                <ColumnListItem>
                                    <cells>
                                        <Text text="{AppConfig>country_code}"/>
                                        <Text text="{AppConfig>country_text}"/>
                                    </cells>
                                </ColumnListItem>
                            </items>
                        </Table>
                    </content>
                </Page>
            </pages>
        </App>
    </Shell>
</mvc:View>

Output:

Bind Global Model to a table

4. Bind Global Model to a drop-down [if Model is JSON]

This process is very much similar to the table code (in the above step). We will use the same controller code but change the view code.

Controller Code:

sap.ui.define([
    "sap/ui/core/mvc/Controller"
], function (Controller) {
    "use strict";
    return Controller.extend("Test.Test.controller.Main", {
        onInit: function () {
        },
        onBeforeRendering: function () {
            var that = this;
            var val1 = {
                country_code: 1,
                country_text: "India"
            };
            var val2 = {
                country_code: 2,
                country_text: "Germany"
            };
            var aData = [];
            aData.push(val1);
            aData.push(val2);
            that.getOwnerComponent().getModel("AppConfig").setProperty("/tableData", {
                "results": aData
            });
        }
    });
});

 

View Code:

<mvc:View controllerName="Test.Test.controller.Main" xmlns:mvc="sap.ui.core.mvc" displayBlock="true" xmlns="sap.m" xmlns:core="sap.ui.core"
    xmlns:html="http://www.w3.org/1999/xhtml">
    <Shell id="shell">
        <App id="app">
            <pages>
                <Page id="page" title="Select a Drop Down">
                    <content>
                        <Select id="idCountrySelect" width="90%" showSecondaryValues="true" items="{AppConfig>/tableData/results}">
                            <core:ListItem key="{AppConfig>country_code}" text="{AppConfig>country_text}"/>
                        </Select>
                    </content>
                </Page>
            </pages>
        </App>
    </Shell>
</mvc:View>

Output:

Bind Global Model to a drop-down [if Model is JSON]

5. Bind Global Model to a form [if Model is an Object]

The right way to bind a model to a form should be JSON Model binding with the form with the help of form ID. In this example, we will be binding directly with the global model.

Controller:

sap.ui.define([
    "sap/ui/core/mvc/Controller"
], function (Controller) {
    "use strict";
    return Controller.extend("Test.Test.controller.Main", {
        onInit: function () {
        },
        onBeforeRendering: function () {
            var val = {
                fname: "Rudramani",
                lname: "Pandey",
                country: "India",
                phone: "+91-9999099099"
            };
            this.getOwnerComponent().getModel("AppConfig").setProperty("/formData", val);
        }
    });
});

 

View:

<mvc:View controllerName="Test.Test.controller.Main" xmlns:mvc="sap.ui.core.mvc" displayBlock="true" xmlns="sap.m" xmlns:core="sap.ui.core"
    xmlns:html="http://www.w3.org/1999/xhtml" xmlns:l="sap.ui.layout" xmlns:f="sap.ui.layout.form">
    <Shell id="shell">
        <App id="app">
            <pages>
                <Page id="page" title="Form Binding">
                    <content>
                        <f:SimpleForm id="idSFormPlatesOvp" editable="false" layout="ResponsiveGridLayout" labelSpanXL="4" labelSpanL="4" labelSpanM="4"
                            labelSpanS="12" adjustLabelSpan="false" emptySpanXL="0" emptySpanL="0" emptySpanM="0" emptySpanS="0" columnsXL="3" columnsL="1" columnsM="1"
                            singleContainerFullSize="false">
                            <f:content>
                                <core:Title text="Basic Info"/>
                                <Label text="First Name"/>
                                <Text text="{AppConfig>/formData/fname}"/>
                                <Label text="Last Name"/>
                                <Text text="{AppConfig>/formData/lname}"/>
                                <Label text="Country"/>
                                <Text text="{AppConfig>/formData/country}"/>
                                <Label text="Mobile"/>
                                <Text text="{AppConfig>/formData/phone}"/>
                            </f:content>
                        </f:SimpleForm>
                    </content>
                </Page>
            </pages>
        </App>
    </Shell>
</mvc:View>

 

Output:

Bind Global Model to a form [if Model is an Object]

6. Bind Global Model to a text [if Model is an Object]

It will be exactly like the above. In case you are binding directly with a field then binding will be like:

<Text text="{AppConfig>/phone}"/>

In case you are binding the text with an object, and then you need to reach up to your field using ‘/’, like:

<Text text="{AppConfig>/formData/phone}"/>

 

7. Changing the Visibility of fields using the Global Model

In this example, you can use Global Model to change the visibility of multiple fields. This example is exactly similar to Example 2.

We will just add a condition to the above form, within the view:

<mvc:View controllerName="Test.Test.controller.Main" xmlns:mvc="sap.ui.core.mvc" displayBlock="true" xmlns="sap.m" xmlns:core="sap.ui.core"
    xmlns:html="http://www.w3.org/1999/xhtml" xmlns:l="sap.ui.layout" xmlns:f="sap.ui.layout.form">
    <Shell id="shell">
        <App id="app">
            <pages>
                <Page id="page" title="Form Binding">
                    <content>
                        <f:SimpleForm id="idSFormPlatesOvp" editable="false" layout="ResponsiveGridLayout" labelSpanXL="4" labelSpanL="4" labelSpanM="4"
                            labelSpanS="12" adjustLabelSpan="false" emptySpanXL="0" emptySpanL="0" emptySpanM="0" emptySpanS="0" columnsXL="3" columnsL="1" columnsM="1"
                            singleContainerFullSize="false">
                            <f:content>
                                <core:Title text="Basic Info"/>
                                <Label text="First Name"/>
                                <Text text="{AppConfig>/formData/fname}"/>
                                <Label text="Last Name"/>
                                <Text text="{AppConfig>/formData/lname}"/>
                                <Label text="Country"/>
                                <Text visible="{=${AppConfig>/visible} === true ? true : false}" text="{AppConfig>/formData/country}"/>
                                <Label text="Mobile"/>
                                <Text visible="{=${AppConfig>/visible} === true ? true : false}" text="{AppConfig>/formData/phone}"/>
                            </f:content>
                        </f:SimpleForm>
                    </content>
                </Page>
            </pages>
        </App>
    </Shell>
</mvc:View>

In case we make the global model field “visible” as true, then the form will load as usual:

Bind Global Model to a form [if Model is an Object]

In case, we will make it false, as shown below:

sap.ui.define([
    "sap/ui/model/json/JSONModel",
    "sap/ui/Device"
], function (JSONModel, Device) {
    "use strict";
    return {
        createDeviceModel: function () {
            var oModel = new JSONModel(Device);
            oModel.setDefaultBindingMode("OneWay");
            return oModel;
        }, //app Congiguration model 
        createAppConfigModel: function () {
            var AppConfig = {
                "editable": false,
                "count": 0,
                "formData": {},
                "tableData": {},
                "visible": false
            };
            var oModel = new JSONModel(AppConfig);
            return oModel;
        }
    };
});

Then the visibility of these two fields will be turned off:

Changing the Visibility of fields using the Global Model

In order to change the value of the global field “visible”, we will write the following code in the controller:

this.getOwnerComponent().getModel("AppConfig").setProperty("/vsible", false);

 

8. Making a form Editable and Non-Editable using the Global Model

To toggle the form Editable and Non-editable, we add a field “editable” in the model, then change the same in the controller based upon the current state [if true, then change it to false and vice-versa] and thereafter bind the same in the editable field.

Model File:

sap.ui.define([
    "sap/ui/model/json/JSONModel",
    "sap/ui/Device"
], function (JSONModel, Device) {
    "use strict";
    return {
        createDeviceModel: function () {
            var oModel = new JSONModel(Device);
            oModel.setDefaultBindingMode("OneWay");
            return oModel;
        }, //app Congiguration model 
        createAppConfigModel: function () {
            var AppConfig = {
                "editable": false,
                "count": 0,
                "formData": {},
                "tableData": {},
                "visible": false
            };
            var oModel = new JSONModel(AppConfig);
            return oModel;
        }
    };
});

Controller File:

sap.ui.define([
    "sap/ui/core/mvc/Controller"
], function (Controller) {
    "use strict";
    return Controller.extend("Test.Test.controller.Main", {
        onInit: function () {
        },
        onPressToggle: function () {
            var editable = this.getOwnerComponent().getModel("AppConfig").getProperty("/editable");
            if (editable) {
                this.getOwnerComponent().getModel("AppConfig").setProperty("/editable", false);
            } else {
                this.getOwnerComponent().getModel("AppConfig").setProperty("/editable", true);
            }
        }
    });
});

View File:

<mvc:View controllerName="Test.Test.controller.Main" xmlns:mvc="sap.ui.core.mvc" displayBlock="true" xmlns="sap.m" xmlns:core="sap.ui.core"
    xmlns:html="http://www.w3.org/1999/xhtml" xmlns:l="sap.ui.layout" xmlns:f="sap.ui.layout.form">
    <Shell id="shell">
        <App id="app">
            <pages>
                <Page id="page" title="Form Binding">
                    <content>
                        <VBox>
                            <Button text="Toggle Visibilty" press="onPressToggle"/>
                        <f:SimpleForm id="idSFormPlatesOvp" editable="false" layout="ResponsiveGridLayout" labelSpanXL="4" labelSpanL="4" labelSpanM="4"
                            labelSpanS="12" adjustLabelSpan="false" emptySpanXL="0" emptySpanL="0" emptySpanM="0" emptySpanS="0" columnsXL="3" columnsL="1" columnsM="1"
                            singleContainerFullSize="false">
                            <f:content>
                                <core:Title text="Basic Info"/>
                                <Label text="First Name"/>
                                <Input editable="{=${AppConfig>/editable} === true ? true : false}" value="{AppConfig>/formData/fname}"/>
                                <Label text="Last Name"/>
                                <Input editable="{=${AppConfig>/editable} === true ? true : false}" value="{AppConfig>/formData/lname}"/>
                                <Label text="Country"/>
                                <Input editable="{=${AppConfig>/editable} === true ? true : false}" value="{AppConfig>/formData/country}"/>
                                <Label text="Mobile"/>
                                <Input editable="{=${AppConfig>/editable} === true ? true : false}" value="{AppConfig>/formData/phone}"/>
                            </f:content>
                        </f:SimpleForm>
                        </VBox>
                    </content>
                </Page>
            </pages>
        </App>
    </Shell>
</mvc:View>

 

0 Comments

Submit a Comment

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.