Skip to content

UI5 Instantiation

Marco Beier edited this page May 26, 2020 · 3 revisions

Overview of App Initialization

When a user starts an app (in the SAP Fiori launchpad ( FLP ) or using an HTML page), several steps will be performed in the background.

  • Find the official documentation here.
  • Basic files of an app here.

  • Note: When a user closes the app, the destroy function of the component is called. All models and the router are destroyed. The router will take care of destroying the views.

Instantiating the App

Some might remember the classic way of instantiating a UI5 application within the index.html, like this:

<script>
    sap.ui.getCore().attachInit(function () {
        sap.ui.require([
            "sap/ui/core/mvc/XMLView"
        ], function (XMLView) {
            XMLView.create({viewName: "nameSpace.testapp"}).then(function (oView) {
                oView.placeAt("content");
            });
        });
    });
</script>

It would be placed into the body of the your index.html file (via it's id) like so:

<body class="sapUiBody" id="content"></body>

But where did that go? I just generated my application with it's basic scaffolding via the Easy UI5 Generator and I can't seem to find this instantiation.

Thats where the 'bootstrap' in our index.html and the 'Component.js' file comes into play. The application was generated as a component. Imagine that each UI5 application, even standalone applications, are components themselves. Why is that? - Every UI5 application is a component. Because we always extend sap.ui.core.UIComponent in our 'Component.js' file, which extends sap.ui.core.Component.

Bootstrap Example #1 - Component declared in onInit

<script 
    id="sap-ui-bootstrap"
    src="/resources/sap-ui-core.js"
    data-sap-ui-async="true"
    data-sap-ui-onInit="module:namespace/projectname/Main"
    data-sap-ui-resourceRoots='{
        "namespace.projectname": "./"
    }'>
</script>

Bootstrap Example #2 - Component declared in HTML

<head>
    <script 
        id="sap-ui-bootstrap"
        src="/resources/sap-ui-core.js"
		data-sap-ui-async="true"
        data-sap-ui-oninit="module:sap/ui/core/ComponentSupport"
        data-sap-ui-resourceroots='{
            "namespace.projectname": "./"
        }'>
    </script>
</head>
<body class="sapUiBody">
    <div data-sap-ui-component 
         data-name="namespace.testapp" 
         data-id="container" 
         data-settings='{"id" : "testapp"}'>
    </div>
</body>

What we see here (example #2) is a (on startup of the application instantiated) component which was directly declared within the div-Tag of our HTML (with custom attributes 'data-*'). The bootstrap attribute data-sap-ui-oninit="module:sap/ui/core/ComponentSupport" is used to enable this feature called "declarative component support" which allows us to place our component directly into HTML.

Click here or here for more information about the bootstrap attributes.

Our div here is quite similar to the ones in the respective UI5 Documentation:

<div data-sap-ui-component data-name="my.component" data-id="container"></div>
<div data-sap-ui-component data-name="my.component2" data-id="container"></div>

But where does the actual instantiation come from? By now we only know where and roughly why our website is placed into the body of our HTML.

Lets look into a simplified Component.js file:

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

	return UIComponent.extend("namespace.testapp.Component", {
		metadata: {
			manifest: "json"
		},

		init: function() {
			// call the base component's init function
			UIComponent.prototype.init.apply(this, arguments);
			// enable routing
			this.getRouter().initialize();
		}
	});
});

As you can see here, within our Component.js we inherit from UIComponent and even call it's constructor at the very beginning (init.apply(this, args)). Now our application configuration file, the manifest.json, comes into play. As you can see at the very start of our own Component, we declared our component metadata to be our manifest and as the official UI5 Documentation already describes it:

"By default, the UI component creates the sap.ui5/rootView declared in the manifest as the root control."

Let's have a look into our manifest.json now:

"sap.ui5": {
    "rootView": {
        "viewName": "namespace.testapp.view.Main",
        "type": "XML",
        "async": true,
        "id": "app"
    }

You could overwrite this behavior by implementing the createContent method within your own component or by overwriting the default behavior of the parents (UIComponent) createContent method within the init method of your component.

Like so:

init: function() {
    UIComponent.prototype.createContent = function(){
        return new sap.m.Label("someID", { text:"Overwriting parent behavior within init" });
    };

// or

createContent : function(){
    return new sap.m.Label("someID", { text:"Overwriting parent behavior with our behavior" });
}

Now, instead of seeing our empty base application with it's title and theme, we would just have a label displaying some text.

Additional Information for the oninit-attribute

The data-sap-ui-oninit-attribute can also be used to invoke custom .js-files before executing the actual component instantiation. To do that, replace the the sap/ui/core/ComponentSupport with the namespace and the name of the project (to make sure we get the right file) and then add the desired javascript file.

<script
data-sap-ui-oninit="module:someNamespace/ProjectName/JavaScriptFile">
</script>

To ensure that the application will initiate itself as before (with the ComponentSupport) we just have to require the ComponentSupport from within our custom .js-file.

//require the ComponentSupport
sap.ui.require(["sap/ui/core/ComponentSupport"]);

Credits

Clone this wiki locally