UNPKG

@openui5/sap.ui.core

Version:

OpenUI5 Core Library sap.ui.core

841 lines (799 loc) 224 kB
/*! * OpenUI5 * (c) Copyright 2026 SAP SE or an SAP affiliate company. * Licensed under the Apache License, Version 2.0 - see LICENSE.txt. */ // Provides the base class for all objects with managed properties and aggregations. sap.ui.define([ "./BindingInfo", "./DataType", "./EventProvider", "./ManagedObjectMetadata", "./Object", "./OwnStatics", "sap/ui/util/ActivityDetection", "sap/ui/util/_enforceNoReturnValue", "sap/base/future", "sap/base/util/ObjectPath", "sap/base/Log", "sap/base/assert", "sap/base/util/deepClone", "sap/base/util/deepEqual", "sap/base/util/uid", "sap/base/util/extend", "sap/base/util/isEmptyObject" ], function( BindingInfo, DataType, EventProvider, ManagedObjectMetadata, BaseObject, OwnStatics, ActivityDetection, _enforceNoReturnValue, future, ObjectPath, Log, assert, deepClone, deepEqual, uid, extend, isEmptyObject ) { "use strict"; // shortcut for the sap.ui.core.ID type const IDType = DataType.getType("sap.ui.core.ID"); // Binding info factory symbol const BINDING_INFO_FACTORY_SYMBOL = Symbol("bindingInfoFactory"); /** * Constructs and initializes a managed object with the given <code>sId</code> and settings. * * If the optional <code>mSettings</code> are given, they must be a simple object * that defines values for properties, aggregations, associations or events keyed by their name. * * <b>Valid Names and Value Ranges:</b> * * The property (key) names supported in the object literal are exactly the (case sensitive) * names documented in the JSDoc for the properties, aggregations, associations and events * of the current class and its base classes. Note that for 0..n aggregations and associations this * name usually is the plural name, whereas it is the singular name in case of 0..1 relations. * * The possible values for a setting depend on its kind: * <ul> * <li>for simple properties, the value has to match the documented type of the property (no type conversion occurs)</li> * <li>for 0..1 aggregations, the value has to be an instance of the aggregated type, or an object literal from which, * the default class of the aggregation (or the corresponding aggregation type as fallback) will be instantiated.</li> * <li>for 0..n aggregations, the value has to be an array of instances of the aggregated type, a single instance or * an object literal from which the default class will be instantiated.</li> * <li>for 0..1 associations, an instance of the associated type or an id (string) is accepted</li> * <li>for 0..n associations, an array of instances of the associated type or of IDs is accepted</li> * <li>for events, either a function (event handler) is accepted or an array of length 2 * where the first element is a function and the 2nd element is an object to invoke the method on; * or an array of length 3, where the first element is an arbitrary payload object, the * second one is a function and the 3rd one is an object to invoke the method on; * or an array of arrays where each nested array has the 2 or 3 element structure * described before (multiple listeners).</li> * </ul> * * Each subclass should document the name and type of its supported settings in its constructor documentation. * * Example usage: * <pre> * new Dialog({ * title: "Some title text", // property of type "string" * showHeader: true, // property of type "boolean" * endButton: new Button(...), // 0..1 aggregation * content: [ // 0..n aggregation * new Input(...), * new Input(...) * ], * afterClose: function(oEvent) { ... } // event handler function * }); * </pre> * * Instead of static values and object instances, data binding expressions can be used, either embedded in * a string or as a binding info object as described in {@link #bindProperty} or {@link #bindAggregation}. * * Example usage: * <pre> * new Dialog({ * title: "{/title}", // embedded binding expression, points to a string property in the data model * ... * content: { // binding info object * path : "/inputItems", // points to a collection in the data model * template : new Input(...) * } * }); * </pre> * * Note that when setting string values, any curly braces and backslashes in those values need to be escaped, so they are not * interpreted as binding expressions. Use {@link #escapeSettingsValue} to do so. * * <b>Note:</b> * As of version 1.120, providing aggregation content via an object literal is deprecated, * in case the object's type is given via the property 'Type' as a string, or is derived via the defined type of the aggregation. * Additionally, as of version 1.120, a ManagedObject subclass can specify a <code>defaultClass</code>, e.g. for cases where only a single class is valid. * Please refer to the {@link sap.ui.base.ManagedObject.MetadataOptions.Aggregation Aggregation} documentation for more details on the * <code>defaultClass</code>. * * Besides the settings documented below, ManagedObject itself supports the following special settings: * <ul> * <li><code>id : <i>sap.ui.core.ID</i></code> an ID for the new instance. Some subclasses (Element, Component) require the id * to be unique in a specific scope (e.g. an Element Id must be unique across all Elements, a Component id must * be unique across all Components). * <li><code>models : <i>object</i></code> a map of {@link sap.ui.model.Model} instances keyed by their model name (alias). * Each entry with key <i>k</i> in this object has the same effect as a call <code>this.setModel(models[k], k);</code>.</li> * <li><code>bindingContexts : <i>object</i></code> a map of {@link sap.ui.model.Context} instances keyed by their model name. * Each entry with key <i>k</i> in this object has the same effect as a call <code>this.setBindingContext(bindingContexts[k], k);</code></li> * <li><code>objectBindings : <i>object</i></code> a map of binding paths keyed by the corresponding model name. * Each entry with key <i>k</i> in this object has the same effect as a call <code>this.bindObject(objectBindings[k], k);</code></li> * <li><code>metadataContexts : <i>object</i></code> an array of single binding contexts keyed by the corresponding model or context name. * The purpose of the <code>metadataContexts</code> special setting is to deduce as much information as possible from the binding context of the control in order * to be able to predefine certain standard properties like e.g. <i>visible, enabled, tooltip,...</i> * * The structure is an array of single contexts, where a single context is a map containing the following keys: * <ul> * <li><code>path: <i>string (mandatory)</i></code> The path to the corresponding model property or object, e.g. '/Customers/Name'. A path can also be relative, e.g. 'Name'</li> * <li><code>model: <i>string (optional)</i></code> The name of the model, in case there is no name then the undefined model is taken</li> * <li><code>name: <i>string (optional)</i></code> A name for the context to used in templating phase</li> * <li><code>kind: <i>string (optional)</i></code> The kind of the adapter, either <code>field</code> for single properties or <code>object</code> for structured contexts. * <li><code>adapter: <i>string (optional)</i></code> The path to an interpretion class that dilivers control relevant data depending on the context, e.g. enabled, visible. * If not supplied the OData meta data is interpreted.</li> * </ul> * The syntax for providing the <code>metadataContexts</code> is as follows: * <code>{SINGLE_CONTEXT1},...,{SINGLE_CONTEXTn}</code> or for simplicity in case there is only one context <code>{SINGLE_CONTEXT}</code>. * * Examples for such metadataContexts are: * <ul> * <li><code>{/Customers/Name}</code> a single part with an absolute path to the property <i>Name</i> of the <i>Customers</i> entity set in the default model</li> * <li><code>{path: 'Customers/Name', model:'json'}</code> a single part with an absolute path to the property <i>Name</i> of the <i>Customers</i> entity set in a named model</li> * <li><code>{parts: [{path: 'Customers/Name'},{path: 'editable', model: 'viewModel'}]}</code> a combination of single binding contexts, one context from the default model and one from the viewModel</li> * </ul></li> * </ul> * * @param {string} [sId] ID for the new managed object; generated automatically if no non-empty ID is given * <b>Note:</b> this can be omitted, no matter whether <code>mSettings</code> will be given or not! * @param {object} [mSettings] Optional map/JSON-object with initial property values, aggregated objects etc. for the new object * @param {object} [oScope] Scope object for resolving string based type and formatter references in bindings. * When a scope object is given, <code>mSettings</code> cannot be omitted, at least <code>null</code> or an empty object literal must be given. * * * @abstract * @class Base Class that introduces some basic concepts, such as, state management and data binding. * * New subclasses of ManagedObject are created with a call to {@link #.extend ManagedObject.extend} and can make use * of the following managed features: * * * <h3>Properties</h3> * Managed properties represent the state of a ManagedObject. They can store a single value of a simple data type * (like 'string' or 'int'). They have a <i>name</i> (e.g. 'size') and methods to get the current value (<code>getSize</code>), * or to set a new value (<code>setSize</code>). When a property is modified by calling the setter, the ManagedObject is marked as invalidated. * A managed property can be bound against a property in a {@link sap.ui.model.Model} by using the {@link #bindProperty} method. * Updates to the model property will be automatically reflected in the managed property and - if TwoWay databinding is active, * changes to the managed property will be reflected in the model. An existing binding can be removed by calling {@link #unbindProperty}. * * If a ManagedObject is cloned, the clone will have the same values for its managed properties as the source of the * clone - if the property wasn't bound. If it is bound, the property in the clone will be bound to the same * model property as in the source. * * Details about the declaration of a managed property, the metadata that describes it and the set of methods that are automatically * generated to access it, can be found in the documentation of the {@link sap.ui.base.ManagedObject.extend extend } method. * * * <h3>Aggregations</h3> * Managed aggregations can store one or more references to other ManagedObjects. They are a mean to control the lifecycle * of the aggregated objects: one ManagedObject can be aggregated by at most one parent ManagedObject at any time. * When a ManagedObject is destroyed, all aggregated objects are destroyed as well and the object itself is removed from * its parent. That is, aggregations won't contain destroyed objects or null/undefined. * * Aggregations have a <i>name</i> ('e.g 'header' or 'items'), a <i>cardinality</i> ('0..1' or '0..n') and are of a specific * <i>type</i> (which must be a subclass of ManagedObject as well or a UI5 interface). A ManagedObject will provide methods to * set or get the aggregated object for a specific aggregation of cardinality 0..1 (e.g. <code>setHeader</code>, <code>getHeader</code> * for an aggregation named 'header'). For an aggregation of cardinality 0..n, there are methods to get all aggregated objects * (<code>getItems</code>), to locate an object in the aggregation (e.g. <code>indexOfItem</code>), to add, insert or remove * a single aggregated object (<code>addItem</code>, <code>insertItem</code>, <code>removeItem</code>) or to remove or destroy * all objects from an aggregation (<code>removeAllItems</code>, <code>destroyItems</code>). * * Details about the declaration of a managed aggregation, the metadata that describes the aggregation, and the set of methods that are automatically * generated to access it, can be found in the documentation of the {@link sap.ui.base.ManagedObject.extend extend} method. * * Aggregations of cardinality 0..n can be bound to a collection in a model by using {@link #bindAggregation} (and unbound again * using {@link #unbindAggregation}). For each context in the model collection, a corresponding object will be created in the * managed aggregation, either by cloning a template object or by calling a factory function. * * Aggregations also control the databinding context of bound objects: by default, aggregated objects inherit all models * and binding contexts from their parent object. * * When a ManagedObject is cloned, all aggregated objects will be cloned as well - but only if they haven't been added by * databinding. In that case, the aggregation in the clone will be bound to the same model collection. * * * <h3>Associations</h3> * Managed associations also form a relationship between objects, but they don't define a lifecycle for the * associated objects. They even can 'break' in the sense that an associated object might have been destroyed already * although it is still referenced in an association. For the same reason, the internal storage for associations * are not direct object references but only the IDs of the associated target objects. * * Associations have a <i>name</i> ('e.g 'initialFocus'), a <i>cardinality</i> ('0..1' or '0..n') and are of a specific <i>type</i> * (which must be a subclass of ManagedObject as well or a UI5 interface). A ManagedObject will provide methods to set or get * the associated object for a specific association of cardinality 0..1 (e.g. <code>setInitialFocus</code>, <code>getInitialFocus</code>). * For an association of cardinality 0..n, there are methods to get all associated objects (<code>getRefItems</code>), * to add, insert or remove a single associated object (<code>addRefItem</code>, * <code>insertRefItem</code>, <code>removeRefItem</code>) or to remove all objects from an association * (<code>removeAllRefItems</code>). * * Details about the declaration of a managed association, the metadata that describes it and the set of methods that are automatically * generated to access it, can be found in the documentation of the {@link sap.ui.base.ManagedObject.extend extend} method. * * Associations can't be bound to the model. * * When a ManagedObject is cloned, the result for an association depends on the relationship between the associated target * object and the root of the clone operation. If the associated object is part of the to-be-cloned object tree (reachable * via aggregations from the root of the clone operation), then the cloned association will reference the clone of the * associated object. Otherwise the association will reference the same object as in the original tree. * When a ManagedObject is destroyed, other objects that are only associated, are not affected by the destroy operation. * * * <h3>Events</h3> * Managed events provide a mean for communicating important state changes to an arbitrary number of 'interested' listeners. * Events have a <i>name</i> and (optionally) a set of <i>parameters</i>. For each event there will be methods to add or remove an event * listener as well as a method to fire the event. (e.g. <code>attachChange</code>, <code>detachChange</code>, <code>fireChange</code> * for an event named 'change'). * * Details about the declaration of managed events, the metadata that describes the event, and the set of methods that are automatically * generated to access it, can be found in the documentation of the {@link sap.ui.base.ManagedObject.extend extend} method. * * When a ManagedObject is cloned, all listeners registered for any event in the clone source are also registered to the * clone. Later changes are not reflected in any direction (neither from source to clone, nor vice versa). * * * <a name="lowlevelapi"><h3>Low Level APIs:</h3></a> * The prototype of ManagedObject provides several generic, low level APIs to manage properties, aggregations, associations, * and events. These generic methods are solely intended for implementing higher level, non-generic methods that manage * a single managed property etc. (e.g. a function <code>setSize(value)</code> that sets a new value for property 'size'). * {@link sap.ui.base.ManagedObject.extend} creates default implementations of those higher level APIs for all managed aspects. * The implementation of a subclass then can override those default implementations with a more specific implementation, * e.g. to implement a side effect when a specific property is set or retrieved. * It is therefore important to understand that the generic low-level methods ARE NOT SUITABLE FOR GENERIC ACCESS to the * state of a managed object, as that would bypass the overriding higher level methods and their side effects. * * @extends sap.ui.base.EventProvider * @author SAP SE * @version 1.147.0 * @public * @alias sap.ui.base.ManagedObject */ var ManagedObject = EventProvider.extend("sap.ui.base.ManagedObject", { metadata : { "abstract" : true, publicMethods : [ "getId", "getMetadata", "getModel", "setModel", "hasModel", "bindProperty", "unbindProperty", "bindAggregation", "unbindAggregation", "bindObject", "unbindObject", "getObjectBinding"], library : "sap.ui.core", // UI Library that contains this class properties : { }, aggregations : { }, associations : {}, events : { /** * Fired after a new value for a bound property has been propagated to the model. * Only fired, when the binding uses a data type. */ "validationSuccess" : { enableEventBubbling : true, parameters : { /** * ManagedObject instance whose property initiated the model update. */ element : { type : 'sap.ui.base.ManagedObject' }, /** * Name of the property for which the bound model property has been updated. */ property : { type : 'string' }, /** * Data type used in the binding. */ type : { type : 'sap.ui.model.Type' }, /** * New value (external representation) as propagated to the model. * * <b>Note: </b>the model might modify (normalize) the value again and this modification * will be stored in the ManagedObject. The 'newValue' parameter of this event contains * the value <b>before</b> such a normalization. */ newValue : { type : 'any' }, /** * Old value (external representation) as previously stored in the ManagedObject. */ oldValue : { type : 'any' } } }, /** * Fired when a new value for a bound property should have been propagated to the model, * but validating the value failed with an exception. */ "validationError" : { enableEventBubbling : true, parameters : { /** * ManagedObject instance whose property initiated the model update. */ element : { type : 'sap.ui.base.ManagedObject' }, /** * Name of the property for which the bound model property should have been been updated. */ property : { type : 'string' }, /** * Data type used in the binding. */ type : { type : 'sap.ui.model.Type' }, /** * New value (external representation) as parsed and validated by the binding. */ newValue : { type : 'any' }, /** * Old value (external representation) as previously stored in the ManagedObject. */ oldValue : { type : 'any' }, /** * Localized message describing the validation issues */ message: { type : 'string' } } }, /** * Fired when a new value for a bound property should have been propagated to the model, * but parsing the value failed with an exception. */ "parseError" : { enableEventBubbling : true, parameters : { /** * ManagedObject instance whose property initiated the model update. */ element : { type : 'sap.ui.base.ManagedObject' }, /** * Name of the property for which the bound model property should have been been updated. */ property : { type : 'string' }, /** * Data type used in the binding. */ type : { type : 'sap.ui.model.Type' }, /** * New value (external representation) as parsed by the binding. */ newValue : { type : 'any' }, /** * Old value (external representation) as previously stored in the ManagedObject. */ oldValue : { type : 'any' }, /** * Localized message describing the parse error */ message: { type : 'string' } } }, /** * Fired when a new value for a bound property should have been propagated from the model, * but formatting the value failed with an exception. */ "formatError" : { enableEventBubbling : true, parameters : { /** * ManagedObject instance whose property should have received the model update. */ element : { type : 'sap.ui.base.ManagedObject' }, /** * Name of the property for which the binding should have been updated. */ property : { type : 'string' }, /** * Data type used in the binding (if any). */ type : { type : 'sap.ui.model.Type' }, /** * New value (model representation) as propagated from the model. */ newValue : { type : 'any' }, /** * Old value (external representation) as previously stored in the ManagedObject. */ oldValue : { type : 'any' } } }, /** * Fired when models or contexts are changed on this object (either by calling setModel/setBindingContext or due to propagation) */ "modelContextChange" : {} }, specialSettings : { /** * Unique ID of this instance. * If not given, a so called autoID will be generated by the framework. * AutoIDs use a unique prefix that must not be used for Ids that the application (or other code) creates. * It can be configured option 'autoIDPrefix', see {@link topic:91f2d03b6f4d1014b6dd926db0e91070 Configuration Options and URL Parameters}. */ id : 'sap.ui.core.ID', /** * A map of model instances to which the object should be attached. * The models are keyed by their model name. For the default model, String(undefined) is expected. */ models : 'object', /** * A map of model instances to which the object should be attached. * The models are keyed by their model name. For the default model, String(undefined) is expected. */ bindingContexts : 'object', /** * A map of model instances to which the object should be attached. * The models are keyed by their model name. For the default model, String(undefined) is expected. */ objectBindings : 'object', /** * A map of model instances to which the object should be attached. * The models are keyed by their model name. For the default model, String(undefined) is expected. * The special setting is only for internal use. */ metadataContexts: 'object', /** * Used by ManagedObject.create. */ Type : { type: 'string', visibility: 'hidden' } } }, constructor : function(sId, mSettings, oScope) { EventProvider.call(this); // no use to pass our arguments const that = this; if ( typeof sId !== 'string' && sId !== undefined ) { // shift arguments in case sId was missing, but mSettings was given oScope = mSettings; mSettings = sId; sId = mSettings && mSettings.id; } if (!sId) { sId = this.getMetadata().uid(); } else { sId = (fnCurrentIdPreprocessor ? fnCurrentIdPreprocessor.call(this, sId) : sId); if (!IDType.isValid(sId)) { throw new Error(`"${sId}" is not a valid ID.`); } } this.sId = sId; // managed object interface // create an empty property bag that uses a map of defaultValues as its prototype this.mProperties = this.getMetadata().createPropertyBag(); this.mAggregations = {}; this.mAssociations = {}; // private properties this.oParent = null; this.aDelegates = []; this.aBeforeDelegates = []; this.iSuppressInvalidate = 0; this.oPropagatedProperties = defaultPropagatedProperties; this.mSkipPropagation = {}; this._bIsOwnerActive = true; // data binding this.oModels = {}; this.aPropagationListeners = []; this.oBindingContexts = {}; this.mElementBindingContexts = {}; this.mBindingInfos = {}; this.mObjectBindingInfos = {}; // contextual settings this._oContextualSettings = defaultContextualSettings; // apply the owner id if defined this._sOwnerId = sOwnerId; // make sure that the object is registered before initializing // and to deregister the object in case of errors (function() { var bCreated = false; // registers the object in the Core // If registration fails (e.g. due to a duplicate ID), the finally block must not be executed. // Otherwise, the already existing object would be deregistered mistakenly if (that.register) { that.register(); } try { // TODO: generic concept for init hooks? if ( that._initCompositeSupport ) { that._initCompositeSupport(mSettings); } // Call init method here instead of specific Controls constructor. if (that.init) { _enforceNoReturnValue(that.init(), /*mLogInfo=*/{ name: "init", component: that.getId()}); // 'init' hook isn't allowed to return any values. } // apply the settings that.applySettings(mSettings, oScope); bCreated = true; // use try finally here since catch leads to the console pointing to the wrong location of the error // (not the original error's location but to this constructor) } finally { // unregisters the object in the Core // the assumption is that the object was successfully registered if (!bCreated && that.deregister) { that.deregister(); } } }()); } }, /* Metadata constructor */ ManagedObjectMetadata); function assertModelName(sModelName) { assert(sModelName === undefined || (typeof sModelName === "string" && !/^(undefined|null)?$/.test(sModelName)), "sModelName must be a string or omitted"); } // Binding support Marker var _bHasBindingSupport = false; /** * Checks if the <code>ManagedObjectBindingSupport</code> mixin is introduced * via a model instance. * If so, it is applied to the <code>ManagedObject.prototype</code> once. * * @param {Object<string, sap.ui.model.Model>} mModels a map of models, keyed by the model name. */ function checkForBindingSupport(mModels) { if (!_bHasBindingSupport ) { var oModel = Object.values(mModels)[0]; // In theory an application could pass an object that does not extend from sap.ui.model.Model if (oModel && oModel.mixinBindingSupport) { oModel.mixinBindingSupport(ManagedObject.prototype); _bHasBindingSupport = true; } } } /** * Returns the metadata for the ManagedObject class. * * @return {sap.ui.base.ManagedObjectMetadata} Metadata for the ManagedObject class. * @static * @public * @name sap.ui.base.ManagedObject.getMetadata * @function */ /** * Returns the metadata for the class that this object belongs to. * * @return {sap.ui.base.ManagedObjectMetadata} Metadata for the class of the object * @public * @name sap.ui.base.ManagedObject#getMetadata * @function */ /** * @typedef {sap.ui.base.Object.MetadataOptions} sap.ui.base.ManagedObject.MetadataOptions * * The structure of the "metadata" object which is passed when inheriting from sap.ui.base.ManagedObject using its static "extend" method. * See {@link sap.ui.base.ManagedObject.extend} for details on its usage. * * @property {string} [library] * Name of the library that the new subclass should belong to. If the subclass is a control or element, it will * automatically register with that library so that authoring tools can discover it. * By convention, the name of the subclass should have the library name as a prefix, but subfolders are allowed, * e.g. <code>sap.ui.layout.form.Form</code> belongs to library <code>sap.ui.layout</code>. * * @property {Object<string, string | sap.ui.base.ManagedObject.MetadataOptions.Property>} [properties] * An object literal whose properties each define a new managed property in the ManagedObject subclass. * The value can either be a simple string which then will be assumed to be the type of the new property or it can be * an object literal with the following properties (see {@link sap.ui.base.ManagedObject.MetadataOptions.Property Property} for details): * type, visibility, byValue, group, defaultValue, bindable, selector * Property names should use camelCase notation, start with a lowercase letter and only use characters from the set [a-zA-Z0-9_$]. * If an aggregation in the literal is preceded by a JSDoc comment (doclet) and if the UI5 plugin and template are used for JSDoc3 generation, the doclet will * be used as generic documentation of the aggregation. * * For each public property 'foo', the following methods will be created by the "extend" method and will be added to the * prototype of the subclass: * <ul> * <li>getFoo() - returns the current value of property 'foo'. Internally calls {@link #getProperty}</li> * <li>setFoo(v) - sets 'v' as the new value of property 'foo'. Internally calls {@link #setProperty}</li> * <li>bindFoo(c) - (only if property was defined to be 'bindable'): convenience function that wraps {@link #bindProperty}</li> * <li>unbindFoo() - (only if property was defined to be 'bindable'): convenience function that wraps {@link #unbindProperty}</li> * </ul> * For hidden properties, no methods are generated. * * @property {string} [defaultProperty] * When specified, the default property must match the name of one of the properties defined for the new subclass (either own or inherited). * The named property can be used to identify the main property to be used for bound data. E.g. the value property of a field control. * * @property {Object<string, string | sap.ui.base.ManagedObject.MetadataOptions.Aggregation>} [aggregations] * An object literal whose properties each define a new aggregation in the ManagedObject subclass. * The value can either be a simple string which then will be assumed to be the type of the new aggregation or it can be * an object literal with the following properties (see {@link sap.ui.base.ManagedObject.MetadataOptions.Aggregation Aggregation} for details): * type, multiple, singularName, visibility, bindable, forwarding, selector. * Aggregation names should use camelCase notation, start with a lowercase letter and only use characters from the set [a-zA-Z0-9_$]. * The name for a hidden aggregations might start with an underscore. * If an aggregation in the literal is preceded by a JSDoc comment (doclet) and if the UI5 plugin and template are used for JSDoc3 generation, the doclet will * be used as generic documentation of the aggregation. * * For each public aggregation 'item' of cardinality 0..1, the following methods will be created by the "extend" method and will be added to the * prototype of the subclass: * <ul> * <li>getItem() - returns the current value of aggregation 'item'. Internally calls {@link #getAggregation} with a default value of <code>undefined</code></li> * <li>setItem(o) - sets 'o' as the new aggregated object in aggregation 'item'. Internally calls {@link #setAggregation}</li> * <li>destroyItem(o) - destroy a currently aggregated object in aggregation 'item' and clears the aggregation. Internally calls {@link #destroyAggregation}</li> * <li>bindItem(c) - (only if aggregation was defined to be 'bindable'): convenience function that wraps {@link #bindAggregation}</li> * <li>unbindItem() - (only if aggregation was defined to be 'bindable'): convenience function that wraps {@link #unbindAggregation}</li> * </ul> * For a public aggregation 'items' of cardinality 0..n, the following methods will be created: * <ul> * <li>getItems() - returns an array with the objects contained in aggregation 'items'. Internally calls {@link #getAggregation} with a default value of <code>[]</code></li> * <li>addItem(o) - adds an object as last element in the aggregation 'items'. Internally calls {@link #addAggregation}</li> * <li>insertItem(o,p) - inserts an object into the aggregation 'items'. Internally calls {@link #insertAggregation}</li> * <li>indexOfItem(o) - returns the position of the given object within the aggregation 'items'. Internally calls {@link #indexOfAggregation}</li> * <li>removeItem(v) - removes an object from the aggregation 'items'. Internally calls {@link #removeAggregation}</li> * <li>removeAllItems() - removes all objects from the aggregation 'items'. Internally calls {@link #removeAllAggregation}</li> * <li>destroyItems() - destroy all currently aggregated objects in aggregation 'items' and clears the aggregation. Internally calls {@link #destroyAggregation}</li> * <li>bindItems(c) - (only if aggregation was defined to be 'bindable'): convenience function that wraps {@link #bindAggregation}</li> * <li>unbindItems() - (only if aggregation was defined to be 'bindable'): convenience function that wraps {@link #unbindAggregation}</li> * </ul> * For hidden aggregations, no methods are generated. * * @property {string} [defaultAggregation] * When specified, the default aggregation must match the name of one of the aggregations defined for the new subclass (either own or inherited). * The named aggregation will be used in contexts where no aggregation is specified. E,g. when an object in an XMLView embeds other objects without * naming an aggregation, as in the following example: * <pre> * &lt;!-- assuming the defaultAggregation for Dialog is 'content' --> * &lt;Dialog> * &lt;Text/> * &lt;Button/> * &lt;/Dialog> * </pre> * * @property {Object<string, string | sap.ui.base.ManagedObject.MetadataOptions.Association>} [associations] * An object literal whose properties each define a new association of the ManagedObject subclass. * The value can either be a simple string which then will be assumed to be the type of the new association or it can be * an object literal with the following properties (see {@link sap.ui.base.ManagedObject.MetadataOptions.Association Association} for details): type, multiple, singularName, visibility * Association names should use camelCase notation, start with a lowercase letter and only use characters from the set [a-zA-Z0-9_$]. * If an association in the literal is preceded by a JSDoc comment (doclet) and if the UI5 plugin and template are used for JSDoc3 generation, the doclet will * be used as generic documentation of the association. * * For each association 'ref' of cardinality 0..1, the following methods will be created by the "extend" method and will be added to the * prototype of the subclass: * <ul> * <li>getRef() - returns the current value of association 'item'. Internally calls {@link #getAssociation} with a default value of <code>undefined</code></li> * <li>setRef(o) - sets 'o' as the new associated object in association 'item'. Internally calls {@link #setAssociation}</li> * </ul> * For a public association 'refs' of cardinality 0..n, the following methods will be created: * <ul> * <li>getRefs() - returns an array with the objects contained in association 'items'. Internally calls {@link #getAssociation} with a default value of <code>[]</code></li> * <li>addRef(o) - adds an object as last element in the association 'items'. Internally calls {@link #addAssociation}</li> * <li>removeRef(v) - removes an object from the association 'items'. Internally calls {@link #removeAssociation}</li> * <li>removeAllRefs() - removes all objects from the association 'items'. Internally calls {@link #removeAllAssociation}</li> * </ul> * For hidden associations, no methods are generated. * * @property {Object<string, string | sap.ui.base.ManagedObject.MetadataOptions.Event>} [events] * An object literal whose properties each define a new event of the ManagedObject subclass. * In this literal, the property names are used as event names and the values are object literals describing the respective event which can have the * following properties (see {@link sap.ui.base.ManagedObject.MetadataOptions.Event Event} for details): allowPreventDefault, parameters * Event names should use camelCase notation, start with a lower-case letter and only use characters from the set [a-zA-Z0-9_$]. * If an event in the literal is preceded by a JSDoc comment (doclet) and if the UI5 plugin and template are used for JSDoc3 generation, the doclet will be used * as generic documentation of the event. * * For each event 'Some' the following methods will be created by the "extend" method and will be added to the * prototype of the subclass: * <ul> * <li>attachSome(fn,o) - registers a listener for the event. Internally calls {@link #attachEvent}</li> * <li>detachSome(fn,o) - deregisters a listener for the event. Internally calls {@link #detachEvent}</li> * <li>fireSome() - fire the event. Internally calls {@link #fireEvent}</li> * </ul> * * @property {string | boolean} [designtime] * Name of a module that implements the designtime part. Alternatively <code>true</code> to indicate that the module's file is named *.designtime.js with * the same base name as the class itself. * * @property {Object<string,any>} [specialSettings] Special settings are an experimental feature and MUST NOT BE DEFINED in controls or applications outside of the <code>sap.ui.core</code> library. * There's no generic or general way how to set or get the values for special settings. For the same reason, they cannot be bound against a model. * If there's a way for consumers to define a value for a special setting, it must be documented in the class that introduces the setting. * * @public */ /** * @typedef {object} sap.ui.base.ManagedObject.MetadataOptions.Property * * An object literal describing a property of a class derived from <code>sap.ui.base.ManagedObject</code>. * See {@link sap.ui.base.ManagedObject.MetadataOptions MetadataOptions} for details on its usage. * * @property {string} type Type of the new property. Must either be one of the built-in types * 'string', 'boolean', 'int', 'float', 'object', 'function' or 'any', or a type created and registered with * {@link sap.ui.base.DataType.createType} or an array type based on one of the previous types (e.g. 'int[]' * or 'string[]', but not just 'array'). * @property {"hidden" | "public"} [visibility="public"] Either 'hidden' or 'public', defaults to 'public'. Properties that * belong to the API of a class must be 'public' whereas 'hidden' properties can only be used internally. * Only public properties are accepted by the constructor or by <code>applySettings</code> or in declarative * representations like an <code>XMLView</code>. Equally, only public properties are cloned. * @property {boolean} [byValue=false] * If set to <code>true</code>, the property value will be {@link module:sap/base/util/deepClone deep cloned} * on write and read operations to ensure that the internal value can't be modified by the outside. The property * <code>byValue</code> is currently restricted to a <code>boolean</code> value. Other types are reserved for future * use. Class definitions must only use boolean values for the flag (or omit it), but readers of ManagedObject * metadata should handle any truthy value as <code>true</code> to be future safe. * Note that using <code>byValue:true</code> has a performance impact on property access and therefore should be * used carefully. It also doesn't make sense to set this option for properties with a primitive type (they have * value semantic anyhow) or for properties with arrays of primitive types (they are already cloned * with a less expensive implementation). Defaults to 'false'. * @property {"Accessibility" | "Appearance" | "Behavior" | "Data" | "Designtime" | "Dimension" | "Identification" | "Misc"} [group] * A semantic grouping of the properties, intended to be used in design time tools. * Allowed values are (case sensitive): Accessibility, Appearance, Behavior, Data, Designtime, Dimension, Identification, Misc * @property {any} [defaultValue] The default value for the property or null if there is no specific * default value defined (the data type's default becomes the default value in this case, e.g. <code>false</code> for boolean and * the empty string for type string). Omitting this property means the default value is <code>undefined</code>. * @property {boolean | "bindable"} [bindable=false] (Either can be omitted or set to the boolean value <code>true</code> or the magic string 'bindable'.) * If set to <code>true</code> or 'bindable', additional named methods <code>bind<i>Name</i></code> and <code>unbind<i>Name</i></code> are generated as convenience. * Despite its name, setting this flag is not mandatory to make the managed property bindable. The generic methods {@link #bindProperty} and * {@link #unbindProperty} can always be used. * @property {string} [selector] Can be set to a valid CSS selector (as accepted by the * {@link https://developer.mozilla.org/en-US/docs/Web/API/Element/querySelector Element.prototype.querySelector} * method). When set, it locates the DOM element that represents this property's value. It should only be set * for properties that have a visual text representation in the DOM. * * The purpose of the selector is to allow other framework parts or design time tooling to identify the DOM parts * of a control or element that represent a specific property without knowing the control or element implementation * in detail. * * As an extension to the standard CSS selector syntax, the selector string can contain the placeholder <code>{id}</code> * (multiple times). Before evaluating the selector in the context of an element or control, all occurrences of the * placeholder have to be replaced by the (potentially escaped) ID of that element or control. * In fact, any selector should start with <code>#{id}</code> to ensure that the query result is limited to the * desired element or control. * * <b>Note</b>: there is a convenience method {@link sap.ui.core.Element#getDomRefForSetting} that evaluates the * selector in the context of a concrete element or control instance. It also handles the placeholder <code>{id}</code>. * Only selected framework features may use that private method, it is not yet a public API and might be changed * or removed in future versions of UI5. However, instead of maintaining the <code>selector</code> in the metadata, * element and control classes can overwrite <code>getDomRefForSetting</code> and determine the DOM element * dynamically. * @property {boolean} [deprecated=false] Flag that marks the property as deprecated (defaults to false). May lead to an additional warning * log message at runtime when the property is still used. For the documentation, also add a <code>@deprecated</code> tag in the JSDoc, * describing since when it is deprecated and what any alternatives are. * * @public */ /** * @typedef {object} sap.ui.base.ManagedObject.MetadataOptions.Aggregation * * An object literal describing an aggregation of a class derived from <code>sap.ui.base.ManagedObject</code>. * See {@link sap.ui.base.ManagedObject.MetadataOptions MetadataOptions} for details on its usage. * * @property {string} [type='sap.ui.core.Control'] Type of the new aggregation. Must be the full global name of a ManagedObject subclass * or a UI5 interface (in dot notation, e.g. 'sap.m.Button'). * @property {function} [defaultClass] The default class for the aggregation. If aggregation content is created from a plain object * and no explicit 'Type' is given (capital 'T'), the default class will be instantiated. * @property {boolean} [multiple=true] Whether the aggregation is a 0..1 (false) or a 0..n aggregation (true), defaults to true * @property {string} [singularName] Singular name for 0..n aggregations. For 0..n aggregations the name by convention should be the plural name. * Methods affecting multiple objects in an aggregation will use the plural name (e.g. getItems(), whereas methods that deal with a single object will use * the singular name (e.g. addItem). The framework knows a set of common rules for building the plural form of English nouns and uses these rules to determine * a singular name on its own. If that name is wrong, a singluarName can be specified with this property. * @property {"hidden" | "public"} [visibility="public"] Either 'hidden' or 'public', defaults to 'public'. Aggregations that * belong to the API of a class must be 'public' whereas 'hidden' aggregations typically are used for the * implementation of composite classes (e.g. composite controls). Only public aggregations are accepted by * the constructor or by <code>applySettings</code> or in declarative representations like an <code>XMLView</code>. * Equally, only public aggregations are cloned. * @property {boolean | "bindable"} [bindable=false] (Either can be omitted or set to the boolean value <code>true</code> or the magic string 'bindable'.) * If set to <code>true</code> or 'bindable', additional named methods <code>bind<i>Name</i></code> and <code>unbind<i>Name</i></code> are generated as convenience. * Despite its name, setting this flag is not mandatory to make the managed aggregation bindable. The generic methods {@link #bindAggregation} and * {@link #unbindAggregation} can always be used. * @property {object} [forwarding] * If set, this defines a forwarding of objects added to this aggregation into an aggregation of another ManagedObject - typically to an inner control * within a composite control. * This means that all adding, removal, or other operations happening on the source aggregation are actually called on the target instance. * All elements added to the source aggregation will be located at the target aggregation (this means the target instance is their parent). * Both, source and target element will return the added elements when asked for the content of the respective aggregation. * If present, the named (non-generic) aggregation methods will be called for the target aggregation. * Aggregations can only be forwarded to non-hidden aggregations of the same or higher multiplicity (i.e. an aggregation with multiplicity "0..n" cannot be * forwarded to an aggregation with multiplicity "0..1"). * The target aggregation must also be "compatible" to the source aggregation in the sense that any items given to the source aggregation * must also be valid in the target aggregation (otherwise the target element will throw a validation error). * If the forwarded elements use data binding, the target element must be properly aggregated by the source element to make sure all models are available there * as well. * The aggregation target must remain the same instance across the entire lifetime of the source control. * Aggregation forwarding will behave unexpectedly when the content in the target aggregation is modified by other actors (e.g. by the target element or by * another forwarding from a different source aggregation). Hence, this is not allowed. * @property {string} forwarding.aggregation The name of the aggregation on the target into which the objects shall be forwarded. The multiplicity of the target * aggregation must be the same as the one of the source aggregation for which forwarding is defined. * @property {string} [forwarding.idSuffix] A string which is appended to the ID of <i>this</i> ManagedObject to construct the ID of the target ManagedObject. This is * one of the two options to specify the target. This option requires the target instance to be created in the init() method of this ManagedObject and to be * always available. * @property {string} [forwarding.getter] The name of the function on instances of this ManagedObject which returns the target instance. This second option * to specify the target can be used for lazy instantiation of the target. Note that either idSuffix or getter must be given. Also note that the target * instance returned by the gette