UI5 File Templates for WebStorm

ui5_144
WebStorm is one of the best IDE for web development (at least JetBRAINS is able to charge for it).

With some dedicated UI5 file templates it is quite handy to start with UI5 development. I will also introduce AMD module definition concept which has found his way in OpenUI5/SAPUI5.

AMD concept in UI5

With version 1.28 of OpenUI5 a new module concept is propagated. In the core classes of UI5 it is already used much longer. The code templates which will be introduced below will already be based in this concept.

AMD stands for Asynchronous Module Definition and is designed to allow asynchronous loading of JavaScript modules (not very surprisingly). It is also the API which is supported by RequireJS. So SAP is following a well-established and accepted standard in the web, good!

In UI5 this is realised with sap.ui.define to define new modules and with sap.ui.require to resolve module dependencies. To understand usage, let’s have a look at some file template examples:

WebStorm UI5 File Template

File templates can be created in WebStorm via Preferences->Editor->File and Code Templates (in WebStorm 10 with a open project):

UI5FileTemplate1

Via + (Plus sign) you can create a new Template. Specifiy a name and a extension and use placeholders with ${} syntax. As placeholder we will use ${UI5_Namespace} for the UI5 component namespace and ${NAME} for file name.

Let’s start with controller file:

UI5 Controller Template

use extension: controller.js

sap.ui.define([
    "sap/ui/core/mvc/Controller"
], function (Controller) {
    "use strict";

    return Controller.extend("${UI5_Namespace}.controller.${NAME}", {
        onInit: function () {
            this.component = this.getOwnerComponent();
            this.bus = this.component.getEventBus();
        }
    });
});

So what structure do we see, when using new AMD concept:

  • The first parameter of sap.ui.define is an array of strings. Each string represents a dependency. In the example we need sap.ui.core.mvc.Controller class to define our own controller by extending this class. We have to replace all dots with forward slashes. So instead of sap.ui.core.mvc.Controller you need to use „sap/ui/core/mvc/Controller“.
  • Second parameter is the factory function, which get each dependency as parameter (here Controller) . This parameter can then be used within the factory function.

UI5 XML View Template

use extension: view.xml

<mvc:View
        controllerName="${UI5_Namespace}.controller.${NAME}"
        xmlns="sap.m"
        xmlns:l="sap.ui.layout"
        xmlns:core="sap.ui.core"
        xmlns:mvc="sap.ui.core.mvc">
    <Page title="${NAME}"
          navButtonPress="onNavBack"
          showNavButton="true">
        <content>
        </content>
        <footer>
            <Bar>
            </Bar>
        </footer>
    </Page>
</mvc:View>

UI5 Component Template

use extension: js

sap.ui.define([
    "sap/ui/core/UIComponent",
    "sap/ui/model/resource/ResourceModel"
], function (UIComponent, ResourceModel) {
    "use strict";

    return UIComponent.extend("${UI5_Namespace}.Component", {

        metadata: {
            "rootView": "${UI5_Namespace}.view.App",
            "dependencies": {
                "minUI5Version": "1.28.0",
                "libs": ["sap.ui.core", "sap.m", "sap.ui.layout"]
            },

            "config": {
                "i18nBundle": "${UI5_Namespace}.i18n.i18n",
                "serviceUrl": "here/goes/your/serviceUrl/"
            },

            "routing": {
                "config": {
                    "routerClass": "sap.m.routing.Router",
                    "viewType": "XML",
                    "viewPath": "${UI5_Namespace}.view",
                    "controlId": "idAppControl",
                    "controlAggregation": "detailPages",
                    "bypassed": {
                        "target": ["master", "notFound"]
                    }
                },
                "routes": [
                    {
                        "pattern": "",
                        "name": "master",
                        "target": ["detail", "master"]
                    },
                    {
                        "pattern": "detail/{detailId}",
                        "name": "detail",
                        "target": ["master", "detail"]
                    }
                ],
                "targets": {
                    "master": {
                        "viewName": "Master",
                        "viewLevel": 1,
                        "viewId": "master",
                        "controlAggregation": "masterPages"
                    },
                    "detail": {
                        "viewName": "Detail",
                        "viewId": "detail",
                        "viewLevel": 2
                    },
                    "notFound": {
                        "viewName": "NotFound",
                        "viewId": "notFound",
                        "viewLevel": 3
                    }
                }
            }
        },

        init: function () {

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

            // set the internationalization model
            this.setModel(new ResourceModel({
                bundleName: mConfig.i18nBundle
            }), "i18n");

            // call the base component's init function and create the App view
            UIComponent.prototype.init.apply(this, arguments);

            // create the views based on the url/hash
            this.getRouter().initialize();
        },

        destroy: function () {
            // call the base component's destroy function
            UIComponent.prototype.destroy.apply(this, arguments);
        }

    });

});

The is a component file template for a master-detail application.

In the Component the App View is referenced as rootView. For master-detail application the SplitApp is used, let’s create another File Template „UI5 SplitApp“ (extension: view.xml) for this:

<mvc:View
 controllerName="${UI5_Namespace}.controller.${NAME}"
 xmlns="sap.m"
 xmlns:mvc="sap.ui.core.mvc">
 <SplitApp id="idAppControl" displayBlock="true" />
</mvc:View>

And finally we create a index.html file for local testing:

UI5 index.html Template

use extension: html

<html>
<head>
    <meta http-equiv="X-UA-Compatible" content="IE=edge"/>
    <meta charset="UTF-8">

    <title>UI5 App</title>

    <script id="sap-ui-bootstrap"
            src="https://openui5.hana.ondemand.com/resources/sap-ui-core.js"
            data-sap-ui-libs="sap.m"
            data-sap-ui-theme="sap_bluecrystal"
            data-sap-ui-preload="async"
            data-sap-ui-compatVersion="edge"
            data-sap-ui-resourceroots='{"${UI5_Namespace}": "./"}'
            data-sap-ui-frameOptions='allow'>    // NON-SECURE setting for testing environment
    </script>

    <script>
        sap.ui.getCore().attachInit(function () {
            sap.ui.require([
                "sap/ui/core/ComponentContainer",
                "${UI5_Namespace}/Component"
            ], function (ComponentContainer, Component) {
                new sap.ui.core.ComponentContainer({
                    name: "${UI5_Namespace}"
                }).placeAt('root');
            });
        });
    </script>
</head>
<body class="sapUiBody" id="root">
</body>
</html>

This is an example how to use sap.ui.require and load necessary dependencies. The structure is somehow identically to the sap.ui.require usage. In the first parameter (array of strings) the necessary dependencies are listed, which are passed as parameters to the callback function.

And Action – Create App with Templates

Now we want to use the new file templates within WebStorm (of course you can use these templates also without WebStorm)

Create an empty project and two folders (the given templates assume this kind of directory structure):

  • controller – for controller files
  • view – for view files

UI5FileTemplate2

We want to create a master view and a detail view.

Therefore select the view folder and right-click and select New and select the UI5 XML View template:

UI5FileTemplate3

Enter as File name „Master“ and as UI5 namespace „ui5v128“ (you can also use your own namespace):

UI5FileTemplate4

For the controller select controller folder and and right-click and select New and select the UI5 Controller template. Enter again as File name „Master“ and as UI5 namespace „ui5v128“:

UI5FileTemplate4b

repeat this for the Detail view/controller (File Name „Detail“,UI5 namespace „ui5v128“).

Additionally we will need the SplitApp View. Please name it „App“ and select the „UI5 SplitApp“ Template (again UI5 namespace „ui5v128“).

UI5FileTemplate5

If you follow this convention the given UI5 Component template will fit, this is is our last step.

Create a UI5 Component (file name: Component) and index.html file (file name index) in the project root folder, both with the same UI5 namespace „ui5v128“. The result should look like this:

UI5FileTemplate6

Within WebStorm you can directly run the App via the index.html file. Right-click the index.html and select Run ‚index.html‘:

UI5FileTemplate7UI5FileTemplate8

The working app is more or less empty, but uses the new module structure. So you prepared for the future (v1.30) and now it is up to you to fill it with more content.

Have fun with UI5 and AMD concept.

Kommentare

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.