@openui5/sap.ui.core
Version:
OpenUI5 Core Library sap.ui.core
206 lines (193 loc) • 7.64 kB
JavaScript
/*!
* OpenUI5
* (c) Copyright 2026 SAP SE or an SAP affiliate company.
* Licensed under the Apache License, Version 2.0 - see LICENSE.txt.
*/
/*eslint-disable max-len */
// Provides the concept of a sorter for list bindings
sap.ui.define([
"sap/base/Log",
"sap/base/i18n/Localization",
"sap/ui/base/Object"
], function(Log, Localization, BaseObject) {
"use strict";
/**
*
* Constructor for Sorter.
*
* @class
* Sorter for list bindings.
*
* Instances of this class define the sort order for a list binding.
*
* @param {string|object} vSorterInfo
* The binding path used for sorting or the sorter info object; if a sorter info object is given, the other
* constructor parameters are ignored
* @param {function} [vSorterInfo.comparator]
* See <code>fnComparator</code> parameter
* @param {boolean} [vSorterInfo.descending=false]
* See <code>bDescending</code> parameter
* @param {boolean|function} [vSorterInfo.group]
* See <code>vGroup</code> parameter
* @param {string[]} [vSorterInfo.groupPaths]
* An array of paths that are required for grouping. Supported since 1.147.0; consult the documentation of the
* specific model implementation whether it evaluates these paths.
* @param {string} [vSorterInfo.path]
* The binding path for this sorter
* @param {boolean} [bDescending=false]
* Whether the sort order is descending
* @param {boolean|function} [vGroup]
* Configure grouping of the content, can either be <code>true</code> to enable grouping based on the raw model
* property value, or a function which calculates the group value out of the context (e.g.
* <code>oContext.getProperty("date").getYear()</code> for year grouping). The control needs to implement the
* grouping behaviour. In case a function is provided it must either return a primitive type value as the group
* key or an object containing a "key" property and additional properties needed for group visualization. This
* object or the object with the primitive type return value as "key" property is passed to the
* <code>groupHeaderFactory</code> function that has been specified to create the group header for the control
* aggregation; see {@link sap.ui.base.ManagedObject#bindAggregation}.
* <b>Note:</b> Grouping via <code>vGroup=true</code> is only possible (and only makes sense) for the primary
* sort property. A more complicated grouping is possible by providing a grouping function. The sort order needs
* to fit to the grouping also in this case. See also
* {@link topic:ec79a5d5918f4f7f9cbc2150e66778cc Sorting, Grouping, and Filtering for List Binding}.
* @param {function} [fnComparator]
* A custom comparator function, which is used for client-side sorting instead of the default comparator method;
* information about parameters and expected return values of such a method can be found in the
* {@link #.defaultComparator default comparator} documentation.
* <b>Note:</b> Custom comparator functions are meant to be used on the client. Models that implement sorting in
* the backend usually don't support custom comparator functions. Consult the documentation of the specific model
* implementation.
* @public
* @alias sap.ui.model.Sorter
* @extends sap.ui.base.Object
*/
var Sorter = BaseObject.extend("sap.ui.model.Sorter", /** @lends sap.ui.model.Sorter.prototype */ {
constructor : function(vSorterInfo, bDescending, vGroup, fnComparator) {
let sPath = vSorterInfo;
if (typeof vSorterInfo === "object") {
sPath = vSorterInfo.path;
bDescending = vSorterInfo.descending;
vGroup = vSorterInfo.group;
fnComparator = vSorterInfo.comparator;
this.aGroupPaths = vSorterInfo.groupPaths?.slice();
}
this.sPath = sPath;
// if a model separator is found in the path, extract model name
var iSeparatorPos = this.sPath.indexOf(">");
if (iSeparatorPos > 0) {
// Model names are ignored, this must be kept for compatibility reasons. But using model names in the
// sorter path make no technical sense as the binding cannot access any other models.
Log.error("Model names are not allowed in sorter-paths: \"" + this.sPath + "\"");
this.sPath = this.sPath.substr(iSeparatorPos + 1);
}
this.bDescending = bDescending;
this.vGroup = vGroup;
if (typeof vGroup == "boolean" && vGroup) {
this.fnGroup = function(oContext) {
return oContext.getProperty(this.sPath);
};
}
if (typeof vGroup == "function") {
this.fnGroup = vGroup;
}
this.fnCompare = fnComparator;
},
/**
* Returns a group object, at least containing a "key" property for group detection.
* May contain additional properties as provided by a custom group function.
*
* @param {sap.ui.model.Context} oContext the binding context
* @return {Object<string, any>} An object containing a key property and optional custom properties
* @public
*/
getGroup : function(oContext) {
var oGroup = this.fnGroup(oContext);
if (typeof oGroup === "string" || typeof oGroup === "number" || typeof oGroup === "boolean" || oGroup == null) {
oGroup = {
key: oGroup
};
}
return oGroup;
},
/**
* Returns the group function of this Sorter. If grouping is not enabled on this Sorter, it will return
* undefined, if no explicit group function has been defined the default group function is returned.
* The returned function is bound to its Sorter, so it will group according to its own property path,
* even if it is used in the context of another Sorter.
*
* @return {function} The group function
* @public
*/
getGroupFunction : function() {
return this.fnGroup && this.fnGroup.bind(this);
},
/**
* Returns the group paths.
*
* @returns {string[]|undefined} The array of group paths or <code>undefined</code> if this sorter has no
* group paths.
*
* @public
* @since 1.147.0
*/
getGroupPaths() {
return this.aGroupPaths?.slice();
},
/**
* Returns the binding path for this sorter; see the path parameter of {@link sap.ui.model.Sorter#constructor}.
*
* @returns {string} The binding path
* @public
* @since 1.131.0
*/
getPath() {
return this.sPath;
},
/**
* Whether to sort in descending order; see the descending parameter of {@link sap.ui.model.Sorter#constructor}.
*
* @returns {boolean} Whether to sort in descending order
* @public
* @since 1.131.0
*/
isDescending() {
return this.bDescending;
}
});
/**
* Compares two values
*
* This is the default comparator function used for clientside sorting, if no custom comparator is given in the
* constructor. It does compare just by using equal/less than/greater than with automatic type casting, except
* for null values, which are last in ascending order, and string values where localeCompare is used.
*
* The comparator method returns -1, 0 or 1, depending on the order of the two items and is
* suitable to be used as a comparator method for Array.sort.
*
* @param {any} a the first value to compare
* @param {any} b the second value to compare
* @returns {int} -1, 0 or 1 depending on the compare result
* @public
*/
Sorter.defaultComparator = function(a, b) {
if (a == b) {
return 0;
}
if (b == null) {
return -1;
}
if (a == null) {
return 1;
}
if (typeof a == "string" && typeof b == "string") {
return a.localeCompare(b, Localization.getLanguageTag().toString());
}
if (a < b) {
return -1;
}
if (a > b) {
return 1;
}
return 0;
};
return Sorter;
});