UNPKG

@openui5/sap.ui.core

Version:

OpenUI5 Core Library sap.ui.core

395 lines (366 loc) 11.6 kB
/*! * OpenUI5 * (c) Copyright 2009-2023 SAP SE or an SAP affiliate company. * Licensed under the Apache License, Version 2.0 - see LICENSE.txt. */ /*eslint-disable max-len */ // Provides an abstract property binding. sap.ui.define([ './Binding', "sap/ui/base/SyncPromise", "sap/base/Log", "sap/base/assert", './SimpleType', // convenience dependency for legacy code that uses global names './DataState' // convenience dependency for legacy code that uses global names ], function(Binding, SyncPromise, Log, assert) { "use strict"; /** * Constructor for PropertyBinding * * @abstract * @class * The PropertyBinding is used to access single data values in the data model. * * @param {sap.ui.model.Model} oModel * @param {string} sPath * @param {sap.ui.model.Context} oContext * @param {object} [mParameters] * * @public * @alias sap.ui.model.PropertyBinding * @extends sap.ui.model.Binding */ var PropertyBinding = Binding.extend("sap.ui.model.PropertyBinding", /** @lends sap.ui.model.PropertyBinding.prototype */ { constructor : function (oModel, sPath, oContext, mParameters) { Binding.apply(this, arguments); }, metadata : { "abstract" : true, publicMethods : [ "getValue", "setValue", "setType", "getType", "setFormatter", "getFormatter", "getExternalValue", "setExternalValue", "getBindingMode" ] } }); // the 'abstract methods' to be implemented by child classes /** * Returns the current value of the bound target * * @function * @name sap.ui.model.PropertyBinding.prototype.getValue * @return {any} the current value of the bound target * * @public */ /** * Sets the value for this binding. A model implementation should check if the current default * binding mode permits setting the binding value, and if so, set the new value in the model, * too. * * @function * @name sap.ui.model.PropertyBinding.prototype.setValue * @param {any} vValue the value to set for this binding * * @public */ /** * Returns a value formatted using the given function. * * @param {function} fnFormat The function to format the value * @returns {any} The formatted value * * @private */ PropertyBinding.prototype._getBoundValue = function(fnFormat) { var vValue = this.getValue(); return fnFormat(vValue); }; /** * Sets a value, after it has been parsed and validated using the given function * * @param {any} vValue * The value to set for this binding * @param {function} fnParse * The function to parse the value * * @returns {Promise|undefined} * A promise to set the value; <code>undefined</code> if the binding has no type * * @throws sap.ui.model.ParseException * @throws sap.ui.model.ValidateException * * @private */ PropertyBinding.prototype._setBoundValue = function(vValue, fnParse) { var oDataState = this.getDataState(), that = this; if (this.oType) { return SyncPromise.resolve(vValue).then(function(vValue) { return fnParse(vValue); }).then(function(vValue) { return SyncPromise.all([vValue, that.oType.validateValue(vValue)]); }).then(function(aResult) { return aResult[0]; }).then(function(vValue) { oDataState.setInvalidValue(undefined); that.setValue(vValue); }).catch(function(oException) { oDataState.setInvalidValue(vValue); that.checkDataState(); //data ui state is dirty inform the control throw oException; }).unwrap(); } else { oDataState.setInvalidValue(undefined); that.setValue(vValue); return undefined; } }; /** * Convert raw to external representation. * * @param {any} vValue Raw value * @return {any} External value * @private */ PropertyBinding.prototype._rawToExternal = function(vValue) { if (this.oType) { vValue = this.oType.formatValue(vValue, this.sInternalType); } if (this.fnFormatter) { vValue = this.fnFormatter(vValue); } return vValue; }; /** * Convert external to raw representation. * * @param {any} vValue External value * @return {any} Raw value * @private */ PropertyBinding.prototype._externalToRaw = function(vValue) { // formatter doesn't support two way binding if (this.oType) { vValue = this.oType.parseValue(vValue, this.sInternalType); } return vValue; }; /** * Convert raw to internal representation. * * @param {any} vValue Raw value * @return {any} Internal value * @private */ PropertyBinding.prototype._rawToInternal = function(vValue) { var oFormat; if (this.oType && vValue !== null && vValue !== undefined) { oFormat = this.oType.getModelFormat(); assert(oFormat && typeof oFormat.parse === "function", "The input format of " + this.oType + " should be an object with the 'parse' method"); vValue = oFormat.parse(vValue); } return vValue; }; /** * Convert internal to raw representation * @param {any} vValue Internal value * @return {any} Raw value * @private */ PropertyBinding.prototype._internalToRaw = function(vValue) { var oFormat; if (vValue !== null && vValue !== undefined) { oFormat = this.oType.getModelFormat(); assert(oFormat && typeof oFormat.format === "function", "The model format of " + this.oType + " should be an object with the 'format' method"); vValue = oFormat.format(vValue); } return vValue; }; /** * Returns the current external value of the bound target which is formatted via a type or * formatter function. * * @throws sap.ui.model.FormatException * * @return {any} the current value of the bound target * * @public */ PropertyBinding.prototype.getExternalValue = function() { switch (this.sInternalType) { case "raw": return this.getRawValue(); case "internal": return this.getInternalValue(); default: return this._getBoundValue(this._rawToExternal.bind(this)); } }; /** * Sets the value for this binding. The value is parsed and validated against its type and then * set to the binding. A model implementation should check if the current default binding mode * permits setting the binding value, and if so, set the new value in the model, too. * * @param {any} vValue The value to set for this binding * @return {undefined|Promise} A promise in case of asynchronous type parsing or validation * @throws sap.ui.model.ParseException * @throws sap.ui.model.ValidateException * * @public */ PropertyBinding.prototype.setExternalValue = function(vValue) { switch (this.sInternalType) { case "raw": return this.setRawValue(vValue); case "internal": return this.setInternalValue(vValue); default: if (this.fnFormatter) { Log.warning("Tried to use twoway binding, but a formatter function is used"); return undefined; } return this._setBoundValue(vValue, this._externalToRaw.bind(this)); } }; /** * Returns the related JavaScript primitive value of the bound target which is parsed by the * {@link sap.ui.model.SimpleType#getModelFormat model format} of this binding's type. If this * binding doesn't have a type, the original value which is stored in the model is returned. * * This method will be used when targetType is set to "internal" or when it's included in a * {@link sap.ui.model.CompositeBinding CompositeBinding} and the CompositeBinding needs to have * the related JavaScript primitive values for its type or formatter. * * @return {any} * The value which is parsed by the model format of the bound target, or the original value in * case of no type. * * @public */ PropertyBinding.prototype.getInternalValue = function() { return this._getBoundValue(this._rawToInternal.bind(this)); }; /** * Sets the value for this binding with the related JavaScript primitive type. The value is * formatted with the {@link sap.ui.model.SimpleType#getModelFormat model format} and validated * against its type and then set to the model. * * @param {any} vValue * The value to set for this binding * @returns {Promise|undefined} * A promise to set the value; <code>undefined</code> if the binding has no type * * @throws sap.ui.model.ValidateException * * @public */ PropertyBinding.prototype.setInternalValue = function(vValue) { return this._setBoundValue(vValue, this._internalToRaw.bind(this)); }; /** * Returns the raw model value, as it exists in the model dataset. * * This method will be used when targetType of a binding is set to "raw" or when it's include * in a {@link sap.ui.model.CompositeBinding CompositeBinding} and the CompositeBinding needs to * have the related JavaScript primitive values for its type or formatter. * * @return {any} * The value which is parsed by the model format of the bound target, or the original value in * case of no type. * * @public */ PropertyBinding.prototype.getRawValue = function() { return this._getBoundValue(function(vValue) { return vValue; }); }; /** * Sets the value for this binding with the raw model value. This setter will perform type * validation, in case a type is defined on the binding. * * @param {any} vValue * The value to set for this binding * @returns {Promise|undefined} * A promise to set the value; <code>undefined</code> if the binding has no type * * @throws sap.ui.model.ValidateException * * @public */ PropertyBinding.prototype.setRawValue = function(vValue) { return this._setBoundValue(vValue, function(vValue) { return vValue; }); }; /** * Sets the optional type and internal type for the binding. The type and internal type are used * to do the parsing/formatting correctly. The internal type is the property type of the element * which the value is formatted to. * * @param {sap.ui.model.Type} oType * The type for the binding * @param {string} sInternalType * The internal type of the element property which this binding is bound against. * * @public */ PropertyBinding.prototype.setType = function(oType, sInternalType) { this.oType = oType; this.sInternalType = sInternalType; }; /** * Returns the type (if any) for the binding. * @returns {sap.ui.model.Type} The binding type * @public */ PropertyBinding.prototype.getType = function() { return this.oType; }; /** * Sets the optional formatter function for the binding. * * @param {function} fnFormatter The formatter function for the binding * * @public */ PropertyBinding.prototype.setFormatter = function(fnFormatter) { this.fnFormatter = fnFormatter; }; /** * Returns the formatter function. * @returns {Function} The formatter function * @public */ PropertyBinding.prototype.getFormatter = function() { return this.fnFormatter; }; /** * Returns the binding mode. * @returns {sap.ui.model.BindingMode} The binding mode * @public */ PropertyBinding.prototype.getBindingMode = function() { return this.sMode; }; /** * Sets the binding mode. * @param {sap.ui.model.BindingMode} sBindingMode The binding mode * @protected */ PropertyBinding.prototype.setBindingMode = function(sBindingMode) { this.sMode = sBindingMode; }; /** * Resumes the binding update. Change events will be fired again. * * When the binding is resumed and the control value was changed in the meantime, the control * value will be set to the current value from the model and a change event will be fired. * @public */ PropertyBinding.prototype.resume = function() { this.bSuspended = false; this.checkUpdate(true); }; return PropertyBinding; });