@openui5/sap.ui.core
Version:
OpenUI5 Core Library sap.ui.core
401 lines (367 loc) • 13.3 kB
JavaScript
/*!
* OpenUI5
* (c) Copyright 2009-2021 SAP SE or an SAP affiliate company.
* Licensed under the Apache License, Version 2.0 - see LICENSE.txt.
*/
sap.ui.define([
"sap/base/util/deepEqual",
"sap/base/util/each",
"sap/ui/base/Object",
"sap/ui/core/message/Message"
], function(deepEqual, each, BaseObject, Message) {
"use strict";
/**
* @class
* Holds the status data of a binding.
* To react to changes of this status data, a control must implement the
* <code>refreshDataState</code> method, which is called with the name of the bound control
* property and the data state object as parameters.
* With the {@link #getChanges} method, the control can determine the changed properties
* and their old and new values.
* <pre>
* // sample implementation to handle message changes
* myControl.prototype.refreshDataState = function (sPropertyName, oDataState) {
* oDataState.getMessages().forEach(function (oMessage) {
* console.log(oMessage.getMessage());
* }
* }
*
* // sample implementation to handle laundering state
* myControl.prototype.refreshDataState = function (sPropertyName, oDataState) {
* this.setBusy(oDataState.isLaundering());
* }
*
* // sample implementation to handle dirty state
* myControl.prototype.refreshDataState = function (sPropertyName, oDataState) {
* if (oDataState.isDirty()) {
* console.log("Property " + sPropertyName + " of control " + this.getId()
* + " is dirty");
* }
* }
* </pre>
*
* With the {@link #getProperty} method, the control can read a property of the data state.
* The properties are
* <ul>
* <li><code>controlMessages</code> The {@link sap.ui.core.message.Message messages}
* created from type validation or parse errors on user input for a property binding
* <li><code>dirty</code> Whether the value was not yet confirmed by the server; use
* {@link #isDirty} to read this property
* <li><code>invalidValue</code> The control value that was rejected by type parsing or
* validation on user input for a property binding
* <li><code>laundering</code> Whether the value has been sent to the server but is not yet
* confirmed
* <li><code>messages</code> All messages of the data state
* <li><code>modelMessages</code> The {@link sap.ui.core.message.Message messages}
* available for the binding in its {@link sap.ui.model.Binding#getModel model}
* <li><code>originalValue</code> The <em>original</em> value of a property binding in
* {@link sap.ui.model.PropertyBinding#getExternalValue external representation}
* <li><code>value</code> The value of a property binding in
* {@link sap.ui.model.PropertyBinding#getExternalValue external representation}
* </ul>
*
* @extends sap.ui.base.Object
*
* @author SAP SE
* @version 1.87.1
*
* @public
* @alias sap.ui.model.DataState
*/
var DataState = BaseObject.extend("sap.ui.model.DataState", /** @lends sap.ui.model.DataState.prototype */ {
metadata : {},
constructor : function() {
this.mProperties = {
modelMessages : [],
controlMessages: [],
laundering: false,
originalValue : undefined,
originalInternalValue: undefined,
value : undefined,
invalidValue: undefined,
internalValue: undefined,
dirty: false,
messages: []
};
this.mChangedProperties = Object.assign({},this.mProperties);
}
});
/**
* Updates the given property with the given value.
*
* @param {string} sProperty - The property name
* @param {any} vValue - The new value
* @returns {this} <code>this</code> to allow method chaining
* @private
*/
DataState.prototype.setProperty = function(sProperty, vValue) {
this.mChangedProperties[sProperty] = vValue;
return this;
};
/**
* @deprecated Likely unused method
* @returns {this} <code>this</code> to allow method chaining
* @private
*/
DataState.prototype.calculateChanges = function() {
for (var sProperty in this.mChangedProperties) {
var vChangedValue = this.mChangedProperties[sProperty].value;
if (!deepEqual(this.mProperties[sProperty], vChangedValue)) {
if (Array.isArray(vChangedValue)) {
vChangedValue = vChangedValue.slice(0);
}
this.mProperties[sProperty] = vChangedValue;
}
}
return this;
};
/**
* Returns the current value of the property
*
* @param {string} sProperty - The name of the property
* @returns {any} The value of the property
* @private
*/
DataState.prototype.getProperty = function(sProperty) {
return this.mChangedProperties[sProperty];
};
/**
* Returns the array of this data state's messages combining the model and control messages.
* The array is sorted descendingly by message severity.
*
* @returns {sap.ui.core.Message[]} The sorted array of all messages
* @public
*/
DataState.prototype.getMessages = function () {
return DataState.getMessagesForProperties(this.mChangedProperties);
};
/**
* Returns the array of this data state's old messages combining the model and control messages.
* The array is sorted descendingly by message severity.
*
* @returns {sap.ui.core.Message[]} The sorted array of all old messages
* @private
*/
DataState.prototype._getOldMessages = function() {
return DataState.getMessagesForProperties(this.mProperties);
};
/**
* Returns the array of the messages in the given object combining the model and control
* messages. The array is sorted descendingly by message severity.
*
* @param {object} mProperties
* Object with properties <code>controlMessages</code> and <code>modelMessages</code> which
* are both arrays of <code>sap.ui.core.Message</code> objects
* @returns {sap.ui.core.Message[]} The sorted array of messages
* @private
*/
DataState.getMessagesForProperties = function (mProperties) {
var aMessages = [],
aControlMessages = mProperties.controlMessages,
aModelMessages = mProperties.modelMessages;
if (aModelMessages || aControlMessages) {
aMessages = aMessages.concat(aModelMessages || [], aControlMessages || []);
aMessages.sort(Message.compare);
}
return aMessages;
};
/**
* Sets an array of model state messages.
*
* @param {sap.ui.core.Message[]} [aMessages=[]] The model messages for this data state.
* @returns {this} <code>this</code> to allow method chaining
* @public
*/
DataState.prototype.setModelMessages = function(aMessages) {
this.mChangedProperties["modelMessages"] = aMessages || [];
return this;
};
/**
* Returns the array of state messages of the model or undefined.
*
* @returns {sap.ui.core.Message[]} The array of messages of the model
* @public
*/
DataState.prototype.getModelMessages = function() {
return this.getProperty("modelMessages");
};
/**
* Sets an array of control state messages.
*
* @param {sap.ui.core.Message[]} aMessages - The control messages
* @return {this} <code>this</code> to allow method chaining
* @protected
*/
DataState.prototype.setControlMessages = function(aMessages) {
this.mChangedProperties["controlMessages"] = aMessages || [];
return this;
};
/**
* Returns the array of state messages of the control.
*
* @return {sap.ui.core.Message[]} The array of control messages
* @public
*/
DataState.prototype.getControlMessages = function() {
return this.getProperty("controlMessages");
};
/**
* 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
*/
DataState.prototype.isDirty = function() {
var vValue = this.mChangedProperties["value"],
vOriginalValue = this.mChangedProperties["originalValue"];
return this.isControlDirty() || !deepEqual(vValue, vOriginalValue);
};
/**
* 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 data state is dirty
* @public
*/
DataState.prototype.isControlDirty = function() {
return this.mChangedProperties["invalidValue"] !== undefined;
};
/**
* Returns whether the data state is in laundering.
* If data is sent to the server, the data state becomes laundering until the
* data was accepted or rejected.
*
* @returns {boolean} Whether the data state is laundering
* @public
*/
DataState.prototype.isLaundering = function() {
return this.mChangedProperties["laundering"];
};
/**
* Sets the laundering state of the data state.
*
* @param {boolean} bLaundering Whether the state is laundering
* @returns {this} <code>this</code> to allow method chaining
* @protected
*/
DataState.prototype.setLaundering = function(bLaundering) {
this.mChangedProperties["laundering"] = bLaundering;
return this;
};
/**
* Returns the formatted value of the data state.
*
* @returns {any} The value of the data.
* @public
*/
DataState.prototype.getValue = function() {
return this.getProperty("value");
};
/**
* Sets the formatted value of the data state,
*
* @param {any} vValue the value
* @returns {this} <code>this</code> to allow method chaining
* @protected
*/
DataState.prototype.setValue = function(vValue) {
this.mChangedProperties["value"] = vValue;
return this;
};
/**
* Returns the dirty value of a binding that was rejected by a type validation so that
* it could not be applied to the model. If the
* value was not rejected it returns <code>undefined</code>. In this case the current
* model value can be accessed using the {@link #getValue} method.
*
* @returns {any} The value that was rejected or <code>undefined</code>
* @public
*/
DataState.prototype.getInvalidValue = function() {
return this.getProperty("invalidValue");
};
/**
* Sets the dirty value that was rejected by the type validation.
*
* @param {any} vInvalidValue The value that was rejected by the type validation or
* <code>undefined</code> if the value was valid
* @returns {this} <code>this</code> to allow method chaining
* @protected
*/
DataState.prototype.setInvalidValue = function(vInvalidValue) {
this.mChangedProperties["invalidValue"] = vInvalidValue;
return this;
};
/**
* Returns the formatted original value of the data.
* The original value is the last confirmed value.
*
* @returns {any} The original confirmed value of the server
* @public
*/
DataState.prototype.getOriginalValue = function() {
return this.getProperty("originalValue");
};
/**
* Sets the formatted original value of the data.
*
* @param {boolean} vOriginalValue The original value
* @returns {this} <code>this</code> to allow method chaining
* @protected
*/
DataState.prototype.setOriginalValue = function(vOriginalValue) {
this.mChangedProperties["originalValue"] = vOriginalValue;
return this;
};
/**
* Returns whether the data state is changed, or resets the data state in case the parameter
* <code>bNewState</code> is false; reset data state means that the data state properties
* are replaced with the changed properties.
* As long as there was no call to this method with <code>bNewState</code> set to false, the
* data state is dirty, and the corresponding binding will fire data state change events.
*
* @param {boolean} [bNewState] Whether the data state is to be reset
* @returns {boolean} Whether the data state was changed
* @protected
*/
DataState.prototype.changed = function(bNewState) {
if (bNewState === false) {
//clear the changed properties as changed was reset;
this.mProperties = Object.assign({},this.mChangedProperties);
}
return !deepEqual(this.mChangedProperties,this.mProperties);
};
/**
* 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
* with the properties <code>oldValue</code> with the old property value and <code>value</code>
* with the new value of the property. The map only contains the changed properties.
*
* @returns {object} The changed properties of the data state
* @public
*/
DataState.prototype.getChanges = function() {
var mChanges = {},
aMessages,
aOldMessages;
each(this.mChangedProperties,function(sProperty, vValue) {
if (!deepEqual(this.mChangedProperties[sProperty],this.mProperties[sProperty])) {
mChanges[sProperty] = {};
mChanges[sProperty].value = this.mChangedProperties[sProperty];
mChanges[sProperty].oldValue = this.mProperties[sProperty];
}
}.bind(this));
aMessages = this.getMessages();
aOldMessages = this._getOldMessages();
if (aMessages.length > 0 || aOldMessages.length > 0) {
mChanges["messages"] = {};
mChanges["messages"].oldValue = aOldMessages;
mChanges["messages"].value = aMessages;
}
return mChanges;
};
return DataState;
});