UNPKG

@openui5/sap.ui.core

Version:

OpenUI5 Core Library sap.ui.core

983 lines (891 loc) 41 kB
/*! * OpenUI5 * (c) Copyright 2026 SAP SE or an SAP affiliate company. * Licensed under the Apache License, Version 2.0 - see LICENSE.txt. */ sap.ui.define([ "sap/base/util/isPlainObject", "sap/base/Log", "sap/ui/base/ManagedObject", "sap/ui/base/ManagedObjectMetadata", "sap/ui/core/util/XMLPreprocessor", "sap/ui/core/XMLTemplateProcessor", "sap/ui/util/XMLHelper" ], function( isPlainObject, Log, ManagedObject, ManagedObjectMetadata, XMLPreprocessor, XMLTemplateProcessor, XMLHelper ) { "use strict"; function requireClass(sClassName) { return new Promise(function(fnResolve, fnReject) { sap.ui.require([sClassName], function(oClassObject) { fnResolve(oClassObject); }, function() { fnReject(new Error("Required control '" + sClassName + "' couldn't be created asynchronously")); } ); }); } /** * Abstract static utility class to access <code>ManagedObjects</code> and <code>XMLNodes</code> that represent * <code>ManagedObjects</code> in a harmonized way. * * The class mirrors the <code>ManagedObject</code> API so that code that needs to work with <code>ManagedObjects</code> * in several representations can be written in a harmonized way. The slight differences are handled * by specifying a super set of parameters that might not be needed in all use cases. * For example <code>sap.ui.fl</code> uses this class and its subtypes for change handlers that can be * applied on <code>XMLViews</code> and normal <code>ManagedObject</code> instances. * * @namespace sap.ui.core.util.reflection.BaseTreeModifier * @private * @ui5-restricted sap.ui.fl, sap.ui.rta, sap.ui.model.meta, implementations of sap.ui.fl.interfaces.Delegate, control change handler and provider * @since 1.56.0 */ return /** @lends sap.ui.core.util.reflection.BaseTreeModifier */{ /** * Function determining the control targeted by the change. It is also possible to pass an extension point selector. * In this case an extension point is referenced in the selector but the parent control of the extension point will be returned. * * @param {object} oSelector - Target of a flexibility change * @param {string} [oSelector.id] - ID of the control targeted by the change. (name or id property is mandatory for selector) * @param {boolean} [oSelector.isLocalId] - <code>true</code> if the ID within the selector is a local ID or a global ID * @param {string} [oSelector.name] - Name of the extension point targeted by the change. (name or id property is mandatory for selector) * @param {sap.ui.core.UIComponent} oAppComponent - Application component * @param {Element} oView - For XML processing only: XML node of the view * @returns {Promise<sap.ui.base.ManagedObject|Element>} Control representation targeted within the selector, wrapped in a Promise * @throws {Error} In case no control could be determined, an error is thrown * @public */ bySelectorExtensionPointEnabled: function(oSelector, oAppComponent, oView) { return Promise.resolve(this.bySelector(oSelector, oAppComponent, oView)); }, /** * Function determining the control targeted by the change. * * @param {object} oSelector - Target of a flexibility change * @param {string} [oSelector.id] - ID of the control targeted by the change. (name or id property is mandatory for selector) * @param {boolean} [oSelector.isLocalId] - <code>true</code> if the ID within the selector is a local ID or a global ID * @param {string} [oSelector.name] - Name of the extension point targeted by the change. (name or id property is mandatory for selector) * @param {sap.ui.core.UIComponent} oAppComponent - Application component * @param {Element} oView - For XML processing only: XML node of the view * @returns {Promise<sap.ui.base.ManagedObject|Element>} Control representation targeted within the selector, wrapped in a Promise * @throws {Error} In case no control could be determined, an error is thrown * @public */ bySelectorTypeIndependent: async function(oSelector, oAppComponent, oView) { if (oSelector?.name) { oView ||= this.bySelector(oSelector.viewSelector, oAppComponent); const oExtensionPointInfo = await this.getExtensionPointInfo(oSelector.name, oView); return oExtensionPointInfo ? oExtensionPointInfo.parent : undefined; } const sControlId = this.getControlIdBySelector(oSelector, oAppComponent); return this._byId(sControlId, oView); }, /** * Function determining the control targeted by the change. * * @param {object} oSelector - Target of a flexibility change * @param {string} [oSelector.id] - ID of the control targeted by the change. (name or id property is mandatory for selector) * @param {boolean} [oSelector.isLocalId] - <code>true</code> if the ID within the selector is a local ID or a global ID * @param {sap.ui.core.UIComponent} oAppComponent - Application component * @param {Element} oView - For XML processing only: XML node of the view * @returns {sap.ui.base.ManagedObject|Element} Control representation targeted within the selector * @throws {Error} In case no control could be determined, an error is thrown * @public */ bySelector: function(oSelector, oAppComponent, oView) { const sControlId = this.getControlIdBySelector(oSelector, oAppComponent); return this._byId(sControlId, oView); }, /** * Function determining the control ID from the selector. * * @param {object} oSelector - Target of a flexibility change * @param {string} oSelector.id - ID of the control targeted by the change * @param {boolean} oSelector.isLocalId - <code>true</code> if the ID within the selector is a local ID or a global ID * @param {sap.ui.core.UIComponent|string} vAppComponent - Application component instance or ID * @returns {string} ID of the control * @throws {Error} In case no control could be determined, an error is thrown * @protected */ getControlIdBySelector: function(oSelector, vAppComponent) { if (!oSelector){ return undefined; } if (typeof oSelector === "string") { oSelector = { id: oSelector }; } let sControlId = oSelector.id; if (oSelector.idIsLocal) { if (vAppComponent) { if (typeof vAppComponent === "string") { sControlId = `${vAppComponent}---${sControlId}`; } else { sControlId = vAppComponent.createId(sControlId); } } else { throw new Error("App Component instance needed to get a control's ID from selector"); } } return sControlId; }, /** * Function for determining the selector that is used later to apply a change for a given control. * * @param {sap.ui.base.ManagedObject|Element|string} vControl - Control or ID string for which the selector should be determined * @param {sap.ui.core.Component} oAppComponent - Application component, needed only if <code>vControl</code> is a string or XML node * @param {object} [mAdditionalSelectorInformation] - Additional mapped data which is added to the selector * @returns {object} oSelector * @returns {string} oSelector.id - ID used to determine the flexibility target * @returns {boolean} oSelector.idIsLocal - <code>true</code> if the <code>selector.id</code> has to be concatenated with the application component ID while applying the change * @throws {Error} In case no control could be determined, an error is thrown * @public */ getSelector: function(vControl, oAppComponent, mAdditionalSelectorInformation) { let sControlId = vControl; if (typeof sControlId !== "string") { sControlId = (vControl) ? this.getId(vControl) : undefined; } else if (!oAppComponent) { throw new Error("App Component instance needed to get a selector from string ID"); } if (mAdditionalSelectorInformation && (mAdditionalSelectorInformation.id || mAdditionalSelectorInformation.idIsLocal)) { throw new Error("A selector of control with the ID '" + sControlId + "' was requested, " + "but core properties were overwritten by the additionally passed information."); } const bValidId = this.checkControlId(sControlId, oAppComponent); if (!bValidId) { throw new Error("Generated ID attribute found - to offer flexibility a stable control ID is needed to assign the changes to, but for this control the ID was generated by SAPUI5 " + sControlId); } const oSelector = Object.assign({}, mAdditionalSelectorInformation, { id: "", idIsLocal: false }); if (this.hasLocalIdSuffix(sControlId, oAppComponent)) { // get local Id for control at root component and use it as selector ID const sLocalId = oAppComponent.getLocalId(sControlId); oSelector.id = sLocalId; oSelector.idIsLocal = true; } else { oSelector.id = sControlId; } return oSelector; }, /** * Checks if the control ID is generated or maintained by the application. * * @param {sap.ui.core.Control|string} vControl - Control instance or ID * @param {sap.ui.core.Component} oAppComponent - <code>oAppComponent</code> application component, needed only if vControl is a string (ID) * @returns {boolean} <code>true</code> if the ID is maintained by the application * @protected */ checkControlId: function(vControl, oAppComponent) { const sControlId = vControl instanceof ManagedObject ? vControl.getId() : vControl; const bIsGenerated = ManagedObjectMetadata.isGeneratedId(sControlId); return !bIsGenerated || this.hasLocalIdSuffix(vControl, oAppComponent); }, /** * Checks if a control ID has a prefix matching the application component. * If this prefix exists, the suffix after the component ID is called the local ID. * * @param {sap.ui.core.Control|string} vControl - Control or ID to be checked if it is within the generic application * @param {sap.ui.core.UIComponent} oAppComponent - Application component, needed only if <code>vControl</code> is a string (ID) * @returns {boolean} <code>true</code> if the control has a local ID * @protected */ hasLocalIdSuffix: function(vControl, oAppComponent) { const sControlId = (vControl instanceof ManagedObject) ? vControl.getId() : vControl; if (!oAppComponent) { return false; } return !!oAppComponent.getLocalId(sControlId); }, /** * This function takes the fragment, goes through all the children and adds a prefix to the control's ID. * Can also handle <code>FragmentDefinition</code> as root node, then all the children's IDs are prefixed. * Adds a '.' at the end of the prefix to separate it from the original ID. * Throws an error if any one of the controls in the fragment have no ID specified. * Aggregations will be ignored and don't need an ID. * * @param {Element} oFragment - Fragment in XML * @param {string} sIdPrefix - String that will be used to prefix the IDs * @returns {Element} Original fragment in XML with updated IDs */ _checkAndPrefixIdsInFragment: function(oFragment, sIdPrefix) { const oParseError = XMLHelper.getParseError(oFragment); if (oParseError.errorCode !== 0) { return Promise.reject(new Error(oFragment.parseError.reason)); } const oControlNodes = oFragment.documentElement; let aRootChildren = []; let aChildren = []; if (oControlNodes.localName === "FragmentDefinition") { aRootChildren = this._getElementNodeChildren(oControlNodes); } else { aRootChildren = [oControlNodes]; } aChildren = [].concat(aRootChildren); // get all children and their children function oCallback(oChild) { aChildren.push(oChild); } let oPromiseChain = Promise.resolve(); for (let i = 0, n = aRootChildren.length; i < n; i++) { oPromiseChain = oPromiseChain.then(this._traverseXmlTree.bind(this, oCallback, aRootChildren[i])); } return oPromiseChain.then(function() { for (let j = 0, m = aChildren.length; j < m; j++) { // aChildren[j].id is not available in IE11, therefore using .getAttribute/.setAttribute if (aChildren[j].getAttribute("id")) { aChildren[j].setAttribute("id", sIdPrefix + "." + aChildren[j].getAttribute("id")); } else { throw new Error("At least one control does not have a stable ID"); } } return oControlNodes; }); }, /** * Gets all the children of an XML Node that are element nodes. * * @param {Element} oNode - XML node * @returns {Element[]} Array with the children of the node */ _getElementNodeChildren: function(oNode) { const aChildren = []; const aNodes = oNode.childNodes; for (let i = 0, n = aNodes.length; i < n; i++) { if (aNodes[i].nodeType === 1) { aChildren.push(aNodes[i]); } } return aChildren; }, /** * Gets the metadata of an XML control. * * @param {Element} oControl - Control in XML * @returns {Promise<sap.ui.base.Metadata>} Resolves with the metadata of the control */ _getControlMetadataInXml: async function(oControl) { const sControlType = this._getControlTypeInXml(oControl).replace(/\./g, "/"); const oControlType = sap.ui.require(sControlType) || await requireClass(sControlType); if (oControlType?.getMetadata) { return oControlType.getMetadata(); } else { throw new Error("getMetadata function is not available on control type"); } }, /** * Gets the metadata of a control. * * @abstract * @param {sap.ui.base.ManagedObject|Element} vControl - Control representation * @returns {Promise<sap.ui.base.Metadata>} Metadata of the control wrapped in a Promise */ getControlMetadata: function(vControl) {}, /** * Gets the library name for a control * * @param {sap.ui.base.ManagedObject|Element} vControl - Control representation * @returns {Promise<string>} library name wrapped in a promise */ getLibraryName: async function(vControl) { const oMetadata = await this.getControlMetadata(vControl); return oMetadata.getLibraryName(); }, /** * Gets the <code>ControlType</code> of an XML control. * * @param {Element} oControl - Control in XML * @returns {string} Control type as a string, e.g. <code>sap.m.Button</code> */ _getControlTypeInXml: function(oControl) { let sControlType = oControl.namespaceURI; sControlType = sControlType ? sControlType + "." : ""; // add a dot if there is already a prefix sControlType += oControl.localName; return sControlType; }, /** * Recursively goes through an XML tree and calls a callback function for every control inside. * Does not call the callback function for aggregations. * * @param {function} fnCallback - Function that will be called for every control with the following arguments: <code>fnCallback(&lt;Element>)</code> * @param {Element} oRootNode - Root node from which we start traversing the tree * @returns {Promise} resolves when async processing is done */ _traverseXmlTree: function(fnCallback, oRootNode) { async function fnRecurse(oCurrentNode, bIsAggregation) { let oMetadata; if (!bIsAggregation) { oMetadata = await this._getControlMetadataInXml(oCurrentNode, true); } const aAggregations = oMetadata && await oMetadata.getAllAggregations(); const aChildren = this._getElementNodeChildren(oCurrentNode); let oPromiseChain = Promise.resolve(); aChildren.forEach(function(oChild) { const bIsCurrentNodeAggregation = aAggregations && aAggregations[oChild.localName]; oPromiseChain = oPromiseChain.then(function() { return fnRecurse.call(this, oChild, bIsCurrentNodeAggregation) .then(function() { // if it's an aggregation, we don't call the callback function if (!bIsCurrentNodeAggregation) { fnCallback(oChild); } }); }.bind(this)); }.bind(this)); return oPromiseChain; } return fnRecurse.call(this, oRootNode, false); }, _getSerializedValue: function(vPropertyValue) { if (this._isSerializable(vPropertyValue) && typeof vPropertyValue !== "string") { //not a property like aggregation //type object can be json objects //should not be already stringified return JSON.stringify(vPropertyValue); } return vPropertyValue; }, _isSerializable: function(vPropertyValue) { // check for plain object, array, primitives return isPlainObject(vPropertyValue) || Array.isArray(vPropertyValue) || Object(vPropertyValue) !== vPropertyValue; }, _escapeSpecialCharactersInString: function(vPropertyValue) { return typeof vPropertyValue === "string" ? vPropertyValue.replace(/([\\\{\}])/g, "\\$1") : vPropertyValue; }, _templateFragment: async function(sFragmentName, mPreprocessorSettings) { const oRootElement = await XMLTemplateProcessor.loadTemplatePromise(sFragmentName, "fragment"); return XMLPreprocessor.process( oRootElement, { name: sFragmentName }, mPreprocessorSettings ); }, /** * Checks if there is a property binding and returns it if available, otherwise returns the value of the property. * * @param {sap.ui.base.ManagedObject|Element} vControl - Control representation * @param {string} sPropertyName - Property name * @returns {Promise<any>} Binding info object or value of the property * @public */ getPropertyBindingOrProperty: function(vControl, sPropertyName) { const oPropertyBinding = this.getPropertyBinding(vControl, sPropertyName); if (oPropertyBinding) { return Promise.resolve(oPropertyBinding); } return this.getProperty(vControl, sPropertyName); }, /** * Calls {@link sap.ui.core.util.reflection.BaseTreeModifier.setPropertyBinding} if the passed value is a * binding info object or binding string, * otherwise calls {@link sap.ui.core.util.reflection.BaseTreeModifier.setProperty}. * * @param {sap.ui.base.ManagedObject|Element} vControl - Control representation * @param {string} sPropertyName - Property name * @param {any} vBindingOrValue - Property binding or property value * @public */ setPropertyBindingOrProperty: function(vControl, sPropertyName, vBindingOrValue) { const bIsBindingObject = vBindingOrValue && (vBindingOrValue.path || vBindingOrValue.parts); const bIsBindingString = vBindingOrValue && typeof vBindingOrValue === "string" && vBindingOrValue.substring(0, 1) === "{" && vBindingOrValue.slice(-1) === "}"; const sOperation = bIsBindingObject || bIsBindingString ? "setPropertyBinding" : "setProperty"; this[sOperation](vControl, sPropertyName, vBindingOrValue); }, /** * See {@link sap.ui.core.Control#setVisible} method. * * @abstract * @param {sap.ui.base.ManagedObject|Element} vControl - Control representation * @param {boolean} bVisible - New value for <code>visible</code> property * @public */ setVisible: function(vControl, bVisible) {}, /** * See {@link sap.ui.core.Control#getVisible} method. * * @abstract * @param {sap.ui.base.ManagedObject|Element} vControl - Control representation * @returns {Promise<boolean>} <code>true</code> if the control's <code>visible</code> property is set wrapped in promise * @public */ getVisible: function(vControl) {}, /** * Sets the new value for stashed and visible. * * @abstract * @param {sap.ui.base.ManagedObject|Element} vControl - Control representation * @param {boolean} bStashed - New value for <code>stashed</code> property * @public */ setStashed: function(vControl, bStashed) {}, /** * Retrieves the current value of the stashed property. * * @abstract * @param {sap.ui.base.ManagedObject|Element} vControl - Control representation * @returns {boolean} <code>true</code> if the control is stashed * @public */ getStashed: function(vControl) {}, /** * See {@link sap.ui.base.ManagedObject#bindProperty} method. * * @abstract * @param {sap.ui.base.ManagedObject|Element} vControl - Control representation * @param {string} sPropertyName - Property name * @param {object} vBindingInfos - Binding info * @public */ bindProperty: function(vControl, sPropertyName, vBindingInfos) {}, /** * See {@link sap.ui.base.ManagedObject#unbindProperty} method. * * @abstract * @param {sap.ui.base.ManagedObject|Element} vControl - Control representation * @param {string} sPropertyName - Property name to be unbound * @public */ unbindProperty: function(vControl, sPropertyName) {}, /** * See {@link sap.ui.base.ManagedObject#bindAggregation} method. * * @abstract * @param {sap.ui.base.ManagedObject|Element} vControl - Control representation * @param {string} sAggregationName - Aggregation name * @param {object} vBindingInfos - Binding info * @returns {Promise} resolves when async processing is done * @public */ bindAggregation: function(vControl, sAggregationName, vBindingInfos) {}, /** * See {@link sap.ui.base.ManagedObject#unbindAggregation} method. * * @abstract * @param {sap.ui.base.ManagedObject|Element} vControl - Control representation * @param {string} sAggregationName - Aggregation name to be unbound * @returns {Promise} resolves when async processing is done * @public */ unbindAggregation: function(vControl, sAggregationName) {}, /** * See {@link sap.ui.base.ManagedObject#setProperty} method. * * @abstract * @param {sap.ui.base.ManagedObject|Element} vControl - Control representation * @param {string} sPropertyName - Property name * @param {*} vPropertyValue - New value for the property * @public */ setProperty: function(vControl, sPropertyName, vPropertyValue) {}, /** * See {@link sap.ui.base.ManagedObject#getProperty} method. * * @abstract * @param {sap.ui.base.ManagedObject|Element} vControl - Control representation * @param {string} sPropertyName - Property name * @returns {Promise<any>} Value of the property wrapped in a Promise * @public */ getProperty: function(vControl, sPropertyName) {}, /** * See {@link sap.ui.base.ManagedObject#isPropertyInitial} method. * * @abstract * @param {sap.ui.base.ManagedObject|Element} oControl - Control representation * @param {string} sPropertyName - Property name * @returns {boolean} <code>true</code> if the property is initial * @public */ isPropertyInitial: function(oControl, sPropertyName) {}, /** * Similar as {@link #bindProperty}, but allows to specify binding like in control constructor. * * @abstract * @param {sap.ui.base.ManagedObject|Element} vControl - Control representation * @param {string} sPropertyName - Property name * @param {any} vPropertyBinding - See source of <code>sap.ui.base.ManagedObject#extractBindingInfo</code> method * @public */ setPropertyBinding: function(vControl, sPropertyName, vPropertyBinding) {}, /** * See {@link sap.ui.base.ManagedObject#getBindingInfo} method. * * @abstract * @param {sap.ui.base.ManagedObject|Element} vControl - Control representation * @param {string} sPropertyName - Property name * @returns {*} Binding info * @public */ getPropertyBinding: function(vControl, sPropertyName) {}, /** * Creates and add a Custom Data object to the control. * * @abstract * @param {sap.ui.base.ManagedObject} oControl - Control representation * @param {string} sCustomDataKey - Key for the Custom Data * @param {string} sValue - Value for the Custom Data * @param {sap.ui.core.Component} oAppComponent - App Component Instance * @param {Promise} resolves when async processing is done */ createAndAddCustomData: function(oControl, sCustomDataKey, sValue, oAppComponent) {}, /** * Checks the custom data created via the {@link sap.ui.core.util.reflection.BaseTreeModifier.js#createAndAddCustomData}. * If there is a custom data with the given key, an object with the following two properties is returned: * customData: CustomData attribute / object * customDataValue: Value of the CustomData * * @abstract * @param {sap.ui.base.ManagedObject|Element} vControl - Control representation * @param {string} sCustomDataKey - Key for the Custom Data * @returns {object} Information about the custom data or an empty object */ getCustomDataInfo: function(vControl, sCustomDataKey) {}, /** * Creates the control in the corresponding representation. * * @abstract * @param {string} sClassName - Class name for the control (for example, <code>sap.m.Button</code>), ensures that the class is loaded (no synchronous requests are called) * @param {sap.ui.core.UIComponent} [oAppComponent] - Needed to calculate the correct ID in case you provide an ID * @param {Element} [oView] - XML node of the view, required for XML case to create nodes and to find elements * @param {object} [oSelector] - Selector to calculate the ID for the control that is created * @param {string} [oSelector.id] - Control ID targeted by the change * @param {boolean} [oSelector.isLocalId] - <code>true</code> if the ID within the selector is a local ID or a global ID * @param {object} [mSettings] - Further settings or properties for the control that is created * @returns {Promise<Element>} Promise with Element of the control that is created * @public */ createControl: function(sClassName, oAppComponent, oView, oSelector, mSettings) {}, /** * See {@link sap.ui.base.ManagedObject#applySettings} method. * * @abstract * @param {sap.ui.base.ManagedObject|Element} vControl - Control representation * @param {object} mSettings - Further settings or properties for the control * @returns {Promise<Element>} XML node of the control being created wrapped into promise * @public */ applySettings: function(vControl, mSettings) {}, /** * Returns the control for the given ID. Consider using {@link sap.ui.core.util.reflection.BaseTreeModifier.js#bySelector} instead if possible. * * @abstract * @param {string} sId - Control ID * @param {Element} oView - View that the control belongs to * @returns {sap.ui.core.Element|Element} - Control instance or element node or <code>undefined</code> if control cannot be found * @private */ _byId: function(sId, oView) {}, /** * See {@link sap.ui.base.ManagedObject#getId} method. * * @abstract * @param {sap.ui.base.ManagedObject|Element} vControl - Control representation * @returns {string} ID * @public */ getId: function(vControl) {}, /** * See {@link sap.ui.base.ManagedObject#getParent} method. * * @abstract * @param {sap.ui.base.ManagedObject|Element} vControl - Control representation * @returns {sap.ui.base.ManagedObject|Element} Parent control in its representation * @public */ getParent: function(vControl) {}, /** * See {@link sap.ui.base.Metadata#getName} method. * * @abstract * @param {sap.ui.base.ManagedObject|Element} vControl - Control representation * @returns {string} Control type * @public */ getControlType: function(vControl) {}, /** * See {@link sap.ui.base.ManagedObject#setAssociation} method. * * @abstract * @param {sap.ui.base.ManagedObject|Element} vParent - Control which has the association * @param {string} sName - Association name * @param {string|sap.ui.base.ManagedObject|Element} sId - ID of the managed object that is set as an association, or the managed object or XML node itself or <code>null</code> * @public */ setAssociation: function(vParent, sName, sId) {}, /** * See {@link sap.ui.base.ManagedObject#getAssociation} method. * * @abstract * @param {sap.ui.base.ManagedObject|Element} vParent - Control which has the association * @param {string} sName - Association name * @returns {string|string[]|null} ID of the associated managed object or an array of such IDs; may be <code>null</code> if the association has not been populated * @public */ getAssociation: function(vParent, sName) {}, /** * See {@link sap.ui.base.ManagedObjectMetadata#getAllAggregations} method. * * @abstract * @param {sap.ui.base.ManagedObject|Element} vControl - Control representation * @return {Promise<Object>} Map of aggregation info objects keyed by aggregation names wrapped in a Promise * @public */ getAllAggregations: function(vControl) {}, /** * See {@link sap.ui.base.ManagedObject#getAggregation} method. * * @abstract * @param {sap.ui.base.ManagedObject|Element} vParent - Control which has the aggregation * @param {string} sName - Aggregation name * @returns {Promise<sap.ui.base.ManagedObject[]|Element[]>} Aggregation content * @public */ getAggregation: function(vParent, sName) {}, /** * See {@link sap.ui.base.ManagedObject#insertAggregation} method. * * @abstract * @param {sap.ui.base.ManagedObject|Element} vParent - Control which has the aggregation * @param {string} sAggregationName - Aggregation name * @param {sap.ui.base.ManagedObject|Element} oObject - XML node or element of the control that will be inserted * @param {int} iIndex - Index for <code>oObject</code> in the aggregation * @param {Element} [oView] - XML node of the view, needed in XML case to potentially create (aggregation) nodes * @param {boolean} [bSkipAdjustIndex] - true in case of inserting an XML node or element at an extension point, needed only in XML case * @returns {Promise} resolves when async processing is done * @public */ insertAggregation: function(vParent, sAggregationName, oObject, iIndex, oView, bSkipAdjustIndex) {}, /** * Removes the object from the aggregation of the given control. * See {@link sap.ui.base.ManagedObject#removeAggregation} method. * * @abstract * @param {sap.ui.base.ManagedObject|Element} vParent - Control representation * @param {string} sAggregationName - Aggregation name * @param {sap.ui.base.ManagedObject|Element} oObject - Aggregated object to be set * @returns {Promise} resolves when async processing is done * @public */ removeAggregation: function(vParent, sAggregationName, oObject) {}, /** * Removes the object from an aggregation of the source control and places it into an aggregation of the target control. * This method is basically a removeAggregation followed by an insertAggregation, but the execution of both steps is * done synchronously, avoiding issues with having elements without parents in asynchronous processes. The entire process * is however asynchronous like other modifier actions. * * @abstract * @param {sap.ui.base.ManagedObject|Element} vSourceParent - Control representation of the source parent * @param {string} sSourceAggregationName - Source aggregation name * @param {sap.ui.base.ManagedObject|Element} vTargetParent - Control representation of the target parent * @param {string} sTargetAggregationName - Target aggregation name * @param {sap.ui.base.ManagedObject|Element} oObject - Aggregated object to be moved * @param {int} iIndex - Index for <code>oObject</code> in the target aggregation * @param {Element} [oView] - XML node of the view, needed in XML case to potentially create (aggregation) nodes * @param {boolean} [bSkipAdjustIndex] - true in case of inserting an XML node or element at an extension point, needed only in XML case * @returns {Promise} resolves when async processing is done * @public */ moveAggregation: function(vSourceParent, sSourceAggregationName, vTargetParent, sTargetAggregationName, oObject, iIndex, oView, bSkipAdjustIndex) {}, /** * Replaces the whole content of an (multiple) aggregation and adds the passed content to it. * Elements can lose their binding info if a 'removeAggregation' is followed by an 'insertAggregation' * (both asynchronous in the modifiers) as they are temporarily left without a parent. * This method calls the 'remove' and 'insert' operations synchronously and sequentially, ensuring that the elements always have a parent * * @abstract * @param {sap.ui.base.ManagedObject|Element} vControl - Control representation * @param {string} sAggregationName - Aggregation name * @param {sap.ui.base.ManagedObject|Element[]} aNewControls - Objects that will replace the current aggregation content * @returns {Promise<undefined>} Resolves when async processing is done * @public */ replaceAllAggregation: function(vControl, sAggregationName, aNewControls) {}, /** * Removes all objects from the aggregation of the given control. * See {@link sap.ui.base.ManagedObject#removeAllAggregation} method. * * @abstract * @param {sap.ui.base.ManagedObject|Element} vParent - Control representation * @param {string} sAggregationName - Aggregation name * @returns {Promise} resolves when async processing is done * @public */ removeAllAggregation: function(vParent, sAggregationName) {}, /** * Gets the binding template from an aggregation. * See {@link sap.ui.base.ManagedObject#getBindingInfo} method. * * @abstract * @param {sap.ui.base.ManagedObject|Element} vControl - Control representation * @param {string} sAggregationName - Aggregation name * @returns {Promise} resolves when async processing is done * @public */ getBindingTemplate: function(vControl, sAggregationName) {}, /** * See {@link sap.ui.base.ManagedObject#updateAggregation} method. * * @abstract * @param {sap.ui.base.ManagedObject|Element} vParent - Control representation * @param {string} sAggregationName - Aggregation name * @returns {Promise} resolves when async processing is done * @public */ updateAggregation: function(vParent, sAggregationName) {}, /** * Finds the index of the control in its parent aggregation. * * @abstract * @param {sap.ui.base.ManagedObject|Element} vControl - Control representation * @returns {Promise<int>} Index of the control wrapped in a Promise * @public */ findIndexInParentAggregation: function(vControl) {}, /** * Removes all objects from the aggregation of the given control. * * @abstract * @param {sap.ui.base.ManagedObject|Element} vControl - Control representation * @param {sap.ui.base.ManagedObject|Element} [vParent] - Control representation of the parent only needed in XML case * @returns {Promise<string>} Parent aggregation name wrapped in a Promise * @public */ getParentAggregationName: function(vControl, vParent) {}, /** * Finds the aggregation by the given aggregation name. * * @abstract * @param {sap.ui.base.ManagedObject|Element} oControl - Control representation * @param {string} sAggregationName - Aggregation name to be found * @returns {Promise} Aggregation object */ findAggregation: function(oControl, sAggregationName) {}, /** * Validates if the control has the correct type for the aggregation. * * @abstract * @param {sap.ui.base.ManagedObject|Element} vControl - Control whose type is to be checked * @param {object} mAggregationMetadata - Aggregation info object * @param {sap.ui.base.ManagedObject|Element} vParent - Parent of the control * @param {string} sFragment - Path to the fragment that contains the control whose type is to be checked * @param {int} iIndex - Index of the current control in the parent aggregation * @returns {Promise<boolean>} <code>true</code> if the type matches wrapped in a Promise * @public */ validateType: function(vControl, mAggregationMetadata, vParent, sFragment, iIndex) {}, /** * Loads a fragment and turns the result into an array of nodes; also prefixes all the controls with a given namespace; * throws an error if there is at least one control in the fragment without a stable ID or has a duplicate ID in the given view. * * @abstract * @param {string} sFragment - XML fragment as string * @param {string} sNamespace - Namespace of the app * @param {sap.ui.core.mvc.View} oView - View for the fragment * @returns {Element[]|sap.ui.core.Element[]} Array with the nodes/instances of the controls of the fragment * @public */ instantiateFragment: function(sFragment, sNamespace, oView) {}, /** * Loads a fragment, processes the XML templating and turns the result into an array of nodes or controls. * See {@link sap.ui.core.util.XMLPreprocessor.process} * * @abstract * @param {string} sFragmentName - XML fragment name (e.g. some.path.fragmentName) * @param {object} [mPreprocessorSettings={}] - Map/JSON object with initial property values, etc. * @param {object} mPreprocessorSettings.bindingContexts - Binding contexts relevant for template pre-processing * @param {object} mPreprocessorSettings.models - Models relevant for template pre-processing * @param {sap.ui.core.mvc.View} oView - View for the fragment, only needed on JS side * @returns {Promise.<Element[]|sap.ui.core.Element[]>} Array with the nodes/instances of the controls of the fragment * @public */ templateControlFragment: function(sFragmentName, mPreprocessorSettings, oView) {}, /** * Cleans up the resources associated with this object and all its aggregated children. * See {@link sap.ui.base.ManagedObject#destroy} method. * * After an object has been destroyed, it can no longer be used! * Applications should call this method if they don't need the object any longer. * * @abstract * @param {sap.ui.base.ManagedObject|Element} vControl - Control representation * @param {boolean} [bSuppressInvalidate] if true, this ManagedObject is not marked as changed * @public */ destroy: function(vControl) {}, /** * Returns the module path of an instance specific change handler. * * @param {sap.ui.base.ManagedObject|Element} vControl - Control representation * @returns {string} Module path * @public */ getChangeHandlerModulePath: function(vControl) { return this._getFlexCustomData(vControl, "flexibility"); }, /** * Gets the "sap.ui.fl" namespaced special settings in the custom data. * * The method is not to be used directly, but to be implemented by modifiers * * @param {sap.ui.base.ManagedObject|Element} vControl - Control representation * @protected * @abstract */ _getFlexCustomData : function(vControl) {}, /** * Object containing delegate information. * * @typedef {object} sap.ui.core.util.reflection.FlexDelegateInfo * @property {string[]} names Module names of the delegates * @property {string} modelType Module type of the delegate * @property {string} [delegateType] Delegate type ("readonly", "writeonly" or "complete") * @property {object} payload Additional information for the delegate * @property {string} [payload.path] Relative/absolute path to a node in a UI5 model, optional if it can be derived by the delegate, e.g. from binding context * @property {string} [payload.modelName] Runtime model name, optional if default model is used (allows to support named models) * @property {any} [payload.something] Payload can contain additional delegate-specific keys and values (not just "something" as a key, the key can be defined as well as the values) * @private * @ui5-restricted sap.ui.fl, sap.ui.rta, sap.ui.model.meta, implementations of sap.ui.fl.interfaces.Delegate, control change handler and provider */ /** * Gets the flexibility delegate information placed at a control. * * @param {sap.ui.base.ManagedObject|Element} vControl - Control representation * @returns {sap.ui.core.util.reflection.FlexDelegateInfo} Delegate information * @public */ getFlexDelegate: function(vControl) { let mDelegateInfo; const sDelegate = this._getFlexCustomData(vControl, "delegate"); if (typeof sDelegate === "string") { try { mDelegateInfo = JSON.parse(sDelegate); if (mDelegateInfo.payload === undefined){ mDelegateInfo.payload = {}; } } catch (oError) { Log.error("Flex Delegate for control " + this.getId(vControl) + " is malformed", oError.message); } } return mDelegateInfo; }, /** * Returns an object containing parent control, aggregation name and index for controls to be added of the given extension point. * * @abstract * @param {string} sExtensionPointName - Name of the extension point * @param {sap.ui.core.mvc.View|Element} oView - View control or XML node of the view * @returns {Promise<{parent: object, aggregation: string, index: number, defaultContent: array}>} - Object containing parent control, aggregation name, index and the defaultContent of the extension point if exists. It is wrapped in a Promise */ getExtensionPointInfo: function(sExtensionPointName, oView) {} }; });