@openui5/sap.ui.core
Version:
OpenUI5 Core Library sap.ui.core
238 lines (225 loc) • 8.98 kB
JavaScript
/*!
* OpenUI5
* (c) Copyright 2026 SAP SE or an SAP affiliate company.
* Licensed under the Apache License, Version 2.0 - see LICENSE.txt.
*/
// Provides controller extension class (part of MVC concept)
sap.ui.define([
'sap/ui/base/Object',
'sap/ui/base/Metadata',
'sap/ui/core/mvc/ControllerMetadata',
'sap/ui/core/mvc/OverrideExecution',
'sap/base/util/uid',
"sap/base/future",
"sap/base/Log"
],
function(BaseObject, Metadata, ControllerMetadata, OverrideExecution, uid, future, Log) {
"use strict";
/**
* @class Base class for controller extensions.
*
* All controller extensions must {@link #.extend extend} from this base class.
* It provides access to the {@link #getView view} of the extended controller as well as
* to the view's {@link #byId controls}.
*
* For a more detailed description how to develop controller extensions, see section
* {@link topic:21515f09c0324218bb705b27407f5d61 Using Controller Extension} in the documentation.
*
* @hideconstructor
* @alias sap.ui.core.mvc.ControllerExtension
* @public
* @extends sap.ui.base.Object
*/
var ControllerExtension = BaseObject.extend("sap.ui.core.mvc.ControllerExtension",
/** @lends sap.ui.core.mvc.ControllerExtension.prototype */ {
metadata: {
stereotype: "controllerextension",
methods: {
"byId": {"public": true, "final": true},
"getInterface" : {"public": false, "final": true},
"getMetadata" : {"public": true, "final": true},
"getView" : {"public": true, "final": true},
"isA" : {"public": true, "final": true}
}
},
/**
* Sets the controller for this extension. Accessible by the base member.
*
* @param {sap.ui.core.mvc.Controller} oController The controller
* @private
*/
_setController: function(oController) {
this.base = oController;
},
/**
* Returns an Element of the connected view with the given local ID.
*
* Views automatically prepend their own ID as a prefix to created Elements
* to make the IDs unique even in the case of multiple view instances.
* For a controller extension, the namespace of the control ID gets also
* prefixed with the namespace of the extension.
* This method helps to find an element by its local ID only.
*
* If no view is connected or if the view doesn't contain an element with
* the given local ID, <code>undefined</code> is returned.
*
* @param {string} sId View-local ID
* @return {sap.ui.core.Element} Element by its (view local) ID
* @public
*/
byId: function(sId) {
var sNamespace = this.getMetadata().getNamespace();
sId = sNamespace + "." + sId;
return this.base ? this.base.byId(sId) : undefined;
},
/**
* Returns the View from the corresponding controller.
*
* @return {sap.ui.core.mvc.View} oView The corresponding view instance
* @public
*/
getView: function() {
return this.base.getView();
},
/**
* Returns the public interface for this extension.
*
* @returns {object} oInterface The public interface for this extension
* @private
*/
getInterface: function() {
var mMethods = {};
var oMetadata = this.getMetadata();
var aPublicMethods = oMetadata._aAllPublicMethods;
aPublicMethods.forEach(function(sMethod) {
var fnFunction = this[sMethod];
if (typeof fnFunction === 'function') {
mMethods[sMethod] = function() {
var tmp = fnFunction.apply(this, arguments);
return (tmp instanceof ControllerExtension) ? tmp.getInterface() : tmp;
}.bind(this);
}
//}
}.bind(this));
this.getInterface = function() {
return mMethods;
};
return mMethods;
}
}, ControllerMetadata);
/**
* Override the ControllerExtension class with the given custom extension definition.
*
* Only public methods that are not final could be overridden. The lifecycle methods
* <code>onInit</code>, <code>onExit</code>, <code>onBeforeRendering</code> and
* <code>onAfterRendering</code> are added before or after the lifecycle functions
* of the original extension.
*
* Example for <code>oExtension</code>:
* <pre>
* {
* onInit: function() {
* ...
* },
* ...
* }
* </pre>
*
* <b>Note:</b> This static method is automatically propagated to subclasses of
* <code>ControllerExtension</code>.
*
* @param {Object<string, function>} oExtension The custom extension definition
* @return {function} A controller extension class
* @public
*/
ControllerExtension.override = function(oExtension) {
// create an anonymous subclass in each call to keep metadata (and static overrides)
// separated even when override() is called multiple times on the same extension class
var oClass = Metadata.createClass(this, "anonymousExtension~" + uid(), {}, ControllerMetadata);
oClass.getMetadata()._staticOverride = oExtension;
oClass.getMetadata()._override = this.getMetadata()._override;
return oClass;
};
/**
* A placeholder for the dummy function in the TypeScript types. Correct calls in TypeScript code will be removed and should not happen at runtime.
* Do not implement, override or remove!
*
* @param {function} oExtensionClass The controller extension class
* @return {sap.ui.core.mvc.ControllerExtension} A controller extension instance
* @private
*/
ControllerExtension.use = function(oExtensionClass) {
throw new Error("ControllerExtension.use() is not a function that may be called at runtime. It is not contained in the public API."
+ "It is only used in TypeScript as a dummy function to convert a ControllerExtension class to an instance, but is supposed "
+ "to be removed by the class transformation. If you see this error, the call has not been removed as expected. Make sure to a) "
+ "only call this method on the base class 'ControllerExtension', not a derived class, and to b) only call it when defining class "
+ "member properties in an ES6-style class, and to c) use an up-to-date version of the 'transform-modules-ui5' Babel plugin or "
+ "the 'ui5-tooling-transpile' task/middleware for the UI5 build tooling. Only when used like this, the call is properly recognized and removed.");
};
/**
* Override a method depending on the overrideExecution strategy
*
* @param {string} sMemberName The name of the function/member
* @param {sap.ui.core.mvc.Controller|sap.ui.core.mvc.ControllerExtension} oOrigDef The controller/extension to extend
* @param {sap.ui.core.mvc.ControllerExtension|object} oCustomDef The controller extension
* @param {object} oContext Used as context for the extended function
* @param {sap.ui.core.mvc.OverrideExecution} sOverrideExecution The override strategy
* @private
*/
ControllerExtension.overrideMethod = function(sMemberName, oOrigDef, oCustomDef, oContext, sOverrideExecution) {
var fnOri = oOrigDef[sMemberName];
var fnCust = oCustomDef[sMemberName];
sOverrideExecution = sOverrideExecution || OverrideExecution.Instead;
function wrapMethod(bBefore) {
(function(fnCust, fnOri, oContext, bBefore){
oOrigDef[sMemberName] = function() {
if (bBefore) {
fnCust.apply(oContext, arguments);
return fnOri.apply(oOrigDef, arguments);
} else {
fnOri.apply(oOrigDef, arguments);
return fnCust.apply(oContext, arguments);
}
};
})(fnCust, fnOri, oContext, bBefore);
}
if (typeof fnCust === 'function' && oContext) {
fnCust = fnCust.bind(oContext);
}
switch (sOverrideExecution) {
case OverrideExecution.Before:
if (fnOri && typeof fnOri === "function") {
wrapMethod(true);
} else if (typeof fnCust === "function") {
oOrigDef[sMemberName] = fnCust;
} else {
future.errorThrows("Controller extension failed: lifecycleMethod '" + sMemberName + "', is not a function");
}
break;
case OverrideExecution.After:
if (fnOri && typeof fnOri === "function") {
wrapMethod(false);
} else if (typeof fnCust === "function") {
oOrigDef[sMemberName] = fnCust;
} else {
future.errorThrows("Controller extension failed: lifecycleMethod '" + sMemberName + "', is not a function");
}
break;
case OverrideExecution.Instead:
default:
if (sMemberName in oOrigDef) {
Log.debug("Overriding member '" + sMemberName + "' of extension " + this.getMetadata().getName());
if (!this.getMetadata().isMethodFinal(sMemberName)) {
oOrigDef[sMemberName] = fnCust;
} else {
future.errorThrows("Error in ControllerExtension.override: Method '" + sMemberName + "' of extension '" + this.getMetadata().getName() + "' is flagged final and cannot be overridden!");
}
} else {
oOrigDef[sMemberName] = fnCust;
}
break;
}
};
return ControllerExtension;
}
);