UNPKG

@openui5/sap.ui.core

Version:

OpenUI5 Core Library sap.ui.core

355 lines (320 loc) 10.5 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 */ sap.ui.define(['./DataState', "sap/base/util/deepEqual", "sap/base/util/each"], function(DataState, deepEqual, each) { "use strict"; /** * @class * Holds the status data of a composite binding. * * @extends sap.ui.model.DataState * * @author SAP SE * @version 1.111.5 * * @public * @alias sap.ui.model.CompositeDataState */ var CompositeDataState = DataState.extend("sap.ui.model.CompositeDataState", /** @lends sap.ui.model.CompositeDataState.prototype */ { metadata : {}, constructor : function(aDataStates) { DataState.apply(this, arguments); this.mProperties.originalValue = []; this.mProperties.originalInternalValue = []; this.mProperties.value = []; this.mProperties.invalidValue = undefined; this.mProperties.internalValue = []; this.mChangedProperties = Object.assign({},this.mProperties); this.aDataStates = aDataStates; } }); /** * Returns true if there are invalid values set on at least one of the inner datastates. * * @returns {boolean} Whether one of the inner datastates has an invalid value * * @private */ CompositeDataState.prototype._hasInnerInvalidValues = function() { return this.aDataStates.reduce(function(bIsInvalid, oDataState) { if (oDataState.getInvalidValue() !== undefined) { return true; } else { return bIsInvalid; } }, false); }; /** * Returns an array of values for the given property in the inner datastates. * * @param {string} sProperty The property name * @returns {any[]} The array of property values in the inner datastates * * @protected */ CompositeDataState.prototype.getInternalProperty = function(sProperty) { var vReturnValue; if (sProperty === "invalidValue" && this._hasInnerInvalidValues()) { vReturnValue = this.aDataStates.map(function(oDataState) { return oDataState.getProperty("invalidValue") || oDataState.getProperty("value"); }); } else { vReturnValue = this.aDataStates.map(function(oDataState) { return oDataState.getProperty(sProperty); }); } return vReturnValue; }; /** * Returns the current value of the given property. * * @param {string} sProperty The name of the property * @returns {any} The value of the property * @private */ CompositeDataState.prototype.getProperty = function(sProperty) { var vValue = DataState.prototype.getProperty.apply(this, arguments); var aInnerValues = this.getInternalProperty(sProperty); var vReturnValue; switch (sProperty) { case "modelMessages": case "controlMessages": vReturnValue = vValue; for (var i = 0; i < aInnerValues.length; ++i) { vReturnValue = vReturnValue.concat(aInnerValues[i]); } break; default: vReturnValue = aInnerValues || vValue; } return vReturnValue; }; /** * Returns the array of current state messages of the model. * * @returns {sap.ui.core.Message[]} The array of messages of the model * * @public */ CompositeDataState.prototype.getModelMessages = function() { return this.getProperty("modelMessages"); }; /** * Returns the array of current state messages of the control. * * @return {sap.ui.core.Message[]} The array of control messages * * @public */ CompositeDataState.prototype.getControlMessages = function() { return this.getProperty("controlMessages"); }; /** * Returns an array of all model and control messages of all parts of the composite binding, * regardless of whether they are old or new. * * @returns {sap.ui.core.Message[]} The array of all messages * * @public * @since 1.98.0 */ CompositeDataState.prototype.getAllMessages = function () { var oResultSet = new Set(); this.aDataStates.forEach(function(oDataState) { oDataState.getAllMessages().forEach(oResultSet.add.bind(oResultSet)); }); return Array.from(oResultSet); }; /** * Returns the array of all current state messages combining the model and control messages. * * @returns {sap.ui.core.Message[]} The array of all messages * * @public */ CompositeDataState.prototype.getMessages = function() { return this.aDataStates.reduce(function(aMessages, oDataState) { return aMessages.concat(oDataState.getMessages()); }, DataState.prototype.getMessages.apply(this, arguments)); }; /** * Check if an Array contains values * * @param {array} vValue Array for check * @returns {boolean} bContains Containing inner values * @private */ CompositeDataState.prototype.containsValues = function(vValue) { if (Array.isArray(vValue)) { for (var i = 0; i < vValue.length; i++) { if (vValue[i] !== undefined) { return true; } } return false; } else { return !!vValue; } }; /** * Returns whether the data state is dirty. * A data state is dirty if the value was changed * but is not yet confirmed by a server or the entered value did not yet pass the type validation. * * @returns {boolean} Whether the data state is dirty * @public */ CompositeDataState.prototype.isDirty = function() { return this.aDataStates.reduce(function(bIsInvalid, oDataState) { if (oDataState.isDirty()) { return true; } else { return bIsInvalid; } }, DataState.prototype.isDirty.apply(this, arguments)); }; /** * Returns whether the data state is dirty in the UI control. * A data state is dirty in the UI control if the entered value did not yet pass the type validation. * * @returns {boolean} Whether the control data state is dirty * @public */ CompositeDataState.prototype.isControlDirty = function() { return this.aDataStates.reduce(function(bIsInvalid, oDataState) { if (oDataState.isControlDirty()) { return true; } else { return bIsInvalid; } }, DataState.prototype.isControlDirty.apply(this, arguments)); }; /** * Returns whether the data state is in laundering. * If data is send to the server the data state becomes laundering until the * data was accepted or rejected. * * @returns {boolean} Whether the data state is laundering * @public */ CompositeDataState.prototype.isLaundering = function() { return this.aDataStates.reduce(function(bIsInvalid, oDataState) { if (oDataState.isLaundering()) { return true; } else { return bIsInvalid; } }, DataState.prototype.isLaundering.apply(this, arguments)); }; /** * Returns the dirty value of a binding that was rejected by a type validation. * This value was of an incorrect type and could not be applied to the model. If the * value was not rejected it will return null. In this case the current * model value can be accessed using the <code>getValue</code> method. * * @returns {any} The value that was rejected * @public */ CompositeDataState.prototype.getInvalidValue = function() { var vValue = this.mChangedProperties["invalidValue"]; var aInvalidValues = this.getInternalProperty("invalidValue"); if (aInvalidValues && this.containsValues(aInvalidValues)) { vValue = aInvalidValues; this.setInvalidValue(aInvalidValues); } return vValue; }; /** * Returns or sets whether the data state is changed. * As long as changed was not set to false the data state is dirty * and the corresponding binding will fire data state change events. * * @param {boolean} [bNewState] the optional new state * @returns {boolean} Whether the data state was changed. * @protected */ CompositeDataState.prototype.changed = function(bNewState) { if (bNewState === false) { //clear the changed properties as changed was reset; this.mProperties = Object.assign({},this.mChangedProperties); this.aDataStates.forEach(function(oDataState) { oDataState.changed(false); }); } return this.aDataStates.reduce(function(bLastChanged, oDataState) { if (bLastChanged) { return true; } else { return oDataState.changed(); } }, !deepEqual(this.mProperties, this.mChangedProperties)); }; /** * Returns the changes of the data state in a map that the control can use in the * <code>refreshDataState</code> method. * The changed property's name is the key in the map. Each element in the map contains an object of below structure. * <pre> * { * oldValue : The old value of the property, * value : The new value of the property * } * </pre> * The map only contains the changed properties. * * @returns {Object<string,{oldValue:any,value:any}>} the changed of the data state * @public */ CompositeDataState.prototype.getChanges = function() { var mChangedProperties = {}; var i, sKey, mChanges; var aInnerChanges = []; for (i = 0; i < this.aDataStates.length; ++i) { mChanges = this.aDataStates[i].getChanges(); for (sKey in mChanges) { mChangedProperties[sKey] = []; } aInnerChanges.push(mChanges); } var bHasInvalidValue = this._hasInnerInvalidValues(); var mAllChanges = {}; for (sKey in mChangedProperties) { for (i = 0; i < aInnerChanges.length; ++i) { mChanges = aInnerChanges[i][sKey]; if (!mAllChanges[sKey]) { mAllChanges[sKey] = []; } if (mChanges) { // There were inner changes for this property, use change values mAllChanges[sKey].push(mChanges.value); } else { // There were no inner changes for this DataState, use current value for old and new values var vValue = this.aDataStates[i].getProperty(sKey); if (sKey === "invalidValue" && bHasInvalidValue && !vValue) { vValue = this.aDataStates[i].getProperty("value"); } mAllChanges[sKey].push(vValue); } } } each(this.mChangedProperties,function(sProperty, vValue) { if (this.mChangedProperties[sProperty] && !deepEqual(this.mChangedProperties[sProperty],this.mProperties[sProperty])) { mAllChanges[sProperty] = {}; mAllChanges[sProperty].value = this.mChangedProperties[sProperty]; mAllChanges[sProperty].oldValue = this.mProperties[sProperty]; } }.bind(this)); var aMessages = this.getMessages(); var aOldMessages = this._getOldMessages(); if (aMessages.length > 0 || aOldMessages.length > 0) { mAllChanges["messages"] = {}; mAllChanges["messages"].oldValue = aOldMessages; mAllChanges["messages"].value = aMessages; } return mAllChanges; }; return CompositeDataState; });