Show TOC

Step 2: ComponentLocate this document in the navigation structure

The component encapsulates all of our sample application. That doesn't mean that all the view definitions and application logic is to be found here, rather, it represents an independent unit which can be instantiated either inside a container or elsewhere. From this unit, the child artifacts, such as views, are brought into play.

Components do not need to be complete applications; they can also be smaller clusters of functionality. Here we are using an sap.ui.core.UIComponent to define our "application unit".

We can view our sample application's Component as having three main sections, and we'll cover them one by one. For that we create a new JavaScript file in the same location as our index.html and call it Component.js.

Metadata

After the initial declaration of the component itself, with the fully qualified name sap.ui.demo.tdg.Component, and the loading of our custom router module, we start with a definition of the component as an sap.ui.core.UIComponent.

jQuery.sap.declare("sap.ui.demo.tdg.Component");
jQuery.sap.require("sap.ui.demo.tdg.MyRouter");

sap.ui.core.UIComponent.extend("sap.ui.demo.tdg.Component", {

As is typical with components, the first thing we see is the component's settings configuration, in the form of the metadata. We'll tackle the configuration in three arbitrary sections: general, config and routing.

General
 metadata : {
        name : "TDG Demo App",
        version : "1.0",
        includes : [],
        dependencies : {
            libs : ["sap.m", "sap.ui.layout"],
            components : []
        },
 rootView : "sap.ui.demo.tdg.view.App",

In this general section we specify the name of the app and its version. We also specify the library dependencies, which, when the component is instantiated, will be loaded directly. In this case it is the sap.m and sap.ui.layout libraries that we need (the latter being for the sap.ui.layout.form.SimpleForm controls that we use to display supplier and category information in the Detail view. This application component doesn't rely on any other components or other files, so the rest of this section is empty.

Ultimately the component, being visual (sap.ui.core.component.UIComponent) needs to return something for the user to see. In this case it's the App view (in App.view.xml in the view folder). You can do this by specifying a createContent function in the component and returning the view there. This is a similar pattern to JavaScript-based view and fragment definitions. However, if you don't need to enhance your view (with additional data, for example) and you would just be returning a fresh instantiation, then you should avoid using the createContent function, and instead, specify the view as shown here, using the rootView metadata parameter. The component itself will then take care of the instantiation.

Config
config : {
            resourceBundle : "i18n/messageBundle.properties",
            serviceConfig : {
                name : "Northwind",
                serviceUrl : "http://services.odata.org/V2/(S(sapuidemotdg))/OData/OData.svc/"
            }
        },
Note For the above config settings to work, you need to disable the web security of your browser. To do this, start your Chrome browser with the arguments --disable-web-security. This is vital, as the service you are trying to consume here lies on a different server. Another way of overcoming this problem is to configure a proxy URL on your server that redirects requests to the Northwind service. You can use a grunt task to configure a proxy such as this.

The sample application is fairly simple and does not require much configuration. Here we have the name of the resource bundle we'll be using for our internationalization, and the URL of the OData service we'll be using for our main, or "domain" model.

Routing
  routing: {
            //...
        }
    },

The routing configuration is not shown here; please refer to the separate section on Navigation and Routing for detailed information.

Initialization

Now that we have the configuration out of the way, it's time to initialize the component.

  init : function() {

        sap.ui.core.UIComponent.prototype.init.apply(this, arguments);

        var mConfig = this.getMetadata().getConfig();

        // always use absolute paths relative to our own component
        // (relative paths will fail if running in the Fiori Launchpad)
        var rootPath = jQuery.sap.getModulePath("sap.ui.demo.tdg");

        // set i18n model
        var i18nModel = new sap.ui.model.resource.ResourceModel({
            bundleUrl : [rootPath, mConfig.resourceBundle].join("/")
        });
        this.setModel(i18nModel, "i18n");
        
        // Create and set domain model to the component
        var sServiceUrl = mConfig.serviceConfig.serviceUrl;
        var oModel = new sap.ui.model.odata.ODataModel(sServiceUrl, true);
        this.setModel(oModel);

        // set device model
        var deviceModel = new sap.ui.model.json.JSONModel({
            isTouch : sap.ui.Device.support.touch,
            isNoTouch : !sap.ui.Device.support.touch,
            isPhone : sap.ui.Device.system.phone,
            isNoPhone : !sap.ui.Device.system.phone,
            listMode : sap.ui.Device.system.phone ? "None" : "SingleSelectMaster",
            listItemType : sap.ui.Device.system.phone ? "Active" : "Inactive"
        });
        deviceModel.setDefaultBindingMode("OneWay");
        this.setModel(deviceModel, "device");
        
        this.getRouter().initialize();

            
    },
});

In the component initialization, we perform various setup activities. First, we retrieve the component configuration from the metadata section shown earlier. We're particularly interested in the service URL as that is going to be used when we create our domain model.

There are actually three models that are created here, and they're all set on the component, meaning they're available to the views within. After setting the models on the component, we initialize the router.

Internationalization Model

This is for application texts that can be translated. See the section on Internationalization for more details.

Domain Model

The domain model is also created based upon the service URL specified in the configuration. This is usually an OData service.

Device Model

Building a responsive app means ensuring that the controls behave appropriately on different devices and screen sizes. Some responsiveness within controls is implicit, where as other aspects must be determined explicitly, based on the device on which it is running. For these latter cases we need to detect the device and use the information to determine how to configure the control's behavior.

Detecting the device is done using the sap.ui.Device support, and the information obtained is stored in a model. See the Device Model section for more details.

Progress Check

We've added Component.js, so our app folder content looks like this:

tdg/
  |
  +-- Component.js
  +-- index.html

But we're still getting a Blue Crystal styled empty screen:

This time, we see an error in the console:

Uncaught Error: failed to load 'sap/ui/demo/tdg/Component.js' from ./Component.js: Error:
        failed to load 'sap/ui/demo/tdg/MyRouter.js' from ./MyRouter.js: 404 - Not Found

This is also not unexpected. We've said we need the sap.ui.demo.tdg.MyRouter via the call to jQuery.sap.require, but we don't have it yet.