Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

UI5 extension of controller and lifecycle methods

I'm trying to create a base controller that has common methods and common onInit logic.

Using the extend method adds the methods from the base controller to the child controller, but the lifecycle methods get overwritten completely.

  • I tried using the override.onInit approach shown on this documentation page but it did not work.
  • I also tried with sap.ui.component like this but I couldn't get it to work at all.
    I'm not sure if it should work with the AMD syntax.

As far as I understood, the extension feature should replace common methods that have been overridden, but it should execute the lifecycle methods from both the base and extension controller on this respective order.

So my question are the following:

  1. Is this behavior possible to achieve? If so, what am I doing wrong?
  2. Is there a better way to implement it?

Example code:

Parent controller

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

  return Controller.extend("my.namespace.controller.App", {
    onInit: function () {
      console.log("reusable init");
    },

    // ...
  });
});

Child controller

sap.ui.define([
  "my/namespace/controller/App.controller"
], function (Controller) {
  "use strict";

  return Controller.extend("my.namespace.child.controller.App", {
    onInit: function () {
      console.log("extend init");
    },

    // ...
  });
});

This example logs only "extend init" when I run the application. I expected it to log both "reusable init" and "extend init" in this order.

I've omitted some code, but the main idea is represented on these two controllers. The only relevant metadata is that the base controller is abstract.

like image 292
Leonardo Meinerz Ramos Avatar asked Oct 28 '25 14:10

Leonardo Meinerz Ramos


2 Answers

In many cases, when developing applications from scratch, the BaseController approach is sufficient as Benedikt explained, or you could try composition with many tiny modules, depending on your project.

The topic controller extension is lesser-known, yet worth to get to know what it's about and how extensions can also help us in application development. The documentation does hint that the extension concepts usually target developers who want to extend existing applications with additional features. However, extensions can also be used:

[...] as a reusable part that is added to the original application. (Source)

Currently, there are two main approaches:

  1. The older concept Component Configuration
    Extensions are declared in manifest.json (or formerly in Component.js) and return a plain object {}.

    • Supported by older UI5 versions.
    • Lifecycle methods are called in addition to the original ones. (See table below)
    • Non-lifecycle methods with the same name are fully overwritten by the extension.
    • Simple and declarative but lacks a clear interface for extension authors.
    • Extending extensions with this approach is not allowed.

      [...] Only one level of controller extension is allowed; nested controller extension is not supported. (Source)


    Example: embed.plnkr.co/7jnWdezkHueq3esS



  2. The newer concept Controller Extension
    Defines methods metadata and the extension returns a sap.ui.core.mvc.ControllerExtension with overrides.

    • Extensions can be either declared in manifest.json (same as above) or added as dependency to your own application development as reusable parts.
    • Lifecycle methods are called in addition to the original ones same as above. (See table)
    • Allows defining a clear interface on all methods for extension authors:
      • public: true | false (default: true)
      • final: true | false (default: false)
      • overrideExecution: "After" | "Before" | "Instead" (default: "Instead")
    • Supports overriding even extension methods.
    • Supported by SAP Fiori elements apps.
    • Can access the base controller via this.base from the extension (Extensions of SAP Fiori elements apps should call this.base.getExtensionAPI()).

    Example: embed.plnkr.co/xnVMDtx8f2IgI91A



Lifecycle execution order

In either case, UI5 executes the lifecycle methods in the following order by default:

Execution order Original controller code Extension code
1. onInit
2. onInit
3. onBeforeRendering
4. onBeforeRendering
5. onAfterRendering
6. onAfterRendering
7. onExit
8. onExit
like image 83
Boghyon Hoffmann Avatar answered Oct 31 '25 10:10

Boghyon Hoffmann


I didn't know there is an override mechanise in UI5 and it looks over-engineered... My guess is you are on an older version without proper support.

Anyhow, js-inheritance works out of the box. You need to call "super".

sap.ui.define([
        "example/BaseController"
    ], function (BaseController) {
        "use strict";
    
        return BaseController.extend("example.BaseController2", {
            onInit: function () {
                // this is the "super" call
                // same happens if you call super() on es6 classes
                BaseController.prototype.onInit.apply(this, arguments);
         }
    });
});

For more information have a look here: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Inheritance_and_the_prototype_chain

like image 20
Benedikt Kromer Avatar answered Oct 31 '25 12:10

Benedikt Kromer