UNPKG

@openui5/sap.m

Version:

OpenUI5 UI Library sap.m

254 lines (234 loc) 10.8 kB
/* eslint-disable max-nested-callbacks */ /*! * OpenUI5 * (c) Copyright 2026 SAP SE or an SAP affiliate company. * Licensed under the Apache License, Version 2.0 - see LICENSE.txt. */ sap.ui.define([ "sap/ui/fl/changeHandler/Base" ], function( ChangeHandlerBase ) { "use strict"; /** * Change handler for moving table columns. * * @alias sap.m.changeHandler.MoveTableColumns * @author SAP SE * @version 1.146.0 * @private * @since 1.48.0 */ var MoveTableColumns = {}; var SOURCE_ALIAS = "source"; var TARGET_ALIAS = "target"; var MOVED_ELEMENTS_ALIAS = "movedElements"; var COLUMNS_AGGREGATION_NAME = "columns"; var CELLS_AGGREGATION_NAME = "cells"; var ITEMS_AGGREGATION_NAME = "items"; function fnSwitchCells(oModifier, oView, oRow, iSourceIndex, iTargetIndex) { return Promise.resolve() .then(oModifier.getAggregation.bind(oModifier, oRow, CELLS_AGGREGATION_NAME)) .then(function(aCells) { // ColumnListItem and GroupHeaderListItem are only allowed for the tables items aggregation. if (!aCells) { return ChangeHandlerBase.markAsNotApplicable("Aggregation cells to move not found", true); } if (iSourceIndex < 0 || iSourceIndex >= aCells.length) { return ChangeHandlerBase.markAsNotApplicable("Move cells in table item called with invalid index: " + iSourceIndex, true); } var oMovedCell = aCells[iSourceIndex]; return Promise.resolve() .then(oModifier.removeAggregation.bind(oModifier,oRow, CELLS_AGGREGATION_NAME, oMovedCell)) .then(oModifier.insertAggregation.bind(oModifier, oRow, CELLS_AGGREGATION_NAME, oMovedCell, iTargetIndex, oView)); }); } function fnMoveColumns(oModifier, oView, oTable, iSourceIndex, iTargetIndex, oTemplate) { return Promise.resolve() .then(oModifier.getAggregation.bind(oModifier, oTable, ITEMS_AGGREGATION_NAME)) .then(function(aItems) { return aItems.reduce(function(oPreviousPromise, oItem) { return oPreviousPromise .then(function() { if (oTemplate !== oItem && oModifier.getControlType(oItem) !== "sap.m.GroupHeaderListItem") { return fnSwitchCells(oModifier, oView, oItem, iSourceIndex, iTargetIndex); } return undefined; }); }, Promise.resolve()); }); } /** * Moves a column from one index to another. * @param {sap.ui.fl.Change} oChange Change object with instructions to be applied on the control * @param {sap.ui.core.Control} oRelevantContainer Control that matches the change selector for applying the change, which is the source of the move * @param {object} mPropertyBag Map of properties * @param {object} mPropertyBag.view XML node representing a ui5 view * @param {sap.ui.core.util.reflection.BaseTreeModifier} mPropertyBag.modifier Modifier for the controls * @param {sap.ui.core.UIComponent} mPropertyBag.appComponent AppComponent * @param {function} fnIterator - Iterator function which is called on each movedElement, as an argument it gets CurrentIndex * of the element and may return TargetIndex as a result. * @return {Promise} Promise resolving when change was applied */ function _applyChange(oChange, oRelevantContainer, mPropertyBag, fnIterator) { var oModifier = mPropertyBag.modifier; var oView = mPropertyBag.view; var oAppComponent = mPropertyBag.appComponent; var oChangeContent = oChange.getContent(); var oTargetSource = oChange.getDependentControl(SOURCE_ALIAS, mPropertyBag); var oTable = oChange.getDependentControl(TARGET_ALIAS, mPropertyBag); var aColumns; var oMovedElement; return Promise.resolve() .then(function() { return oModifier.getAggregation(oTable, COLUMNS_AGGREGATION_NAME); }) .then(function(aRetrievedColumns){ aColumns = aRetrievedColumns; if (oTargetSource !== oTable) { return ChangeHandlerBase.markAsNotApplicable("Moving columns between different tables is not yet supported", true); } // Fetch the information about the movedElements together with the source and target index. return oChangeContent.movedElements.reduce(function (oPreviousPromise, mMovedElement) { var iSourceIndex; var iTargetIndex; var iCurrentIndexInAggregation; var iStoredSourceIndexInChange; var sMovedElementId; return oPreviousPromise.then(function() { oMovedElement = oModifier.bySelector(mMovedElement.selector, oAppComponent, oView); if (!oMovedElement) { sMovedElementId = mMovedElement.selector && mMovedElement.selector.id; return ChangeHandlerBase.markAsNotApplicable( "The column with id: '" + sMovedElementId + "' stored in the change is not found and the move operation cannot be applied", true ); } iCurrentIndexInAggregation = aColumns.indexOf(oMovedElement); iStoredSourceIndexInChange = mMovedElement.sourceIndex; iTargetIndex = typeof fnIterator === "function" && fnIterator(iStoredSourceIndexInChange); iTargetIndex = typeof iTargetIndex === "number" ? iTargetIndex : mMovedElement.targetIndex; if (iCurrentIndexInAggregation !== iTargetIndex) { // By default we are getting the index from the aggregation, because it is possible that the order is // already modified and the column that we want to move is not on the passed source index iSourceIndex = iCurrentIndexInAggregation; } else { // In RTA edit mode, the condition will be false, because the aggregation is modified by the drag and drop action. // Therefore, we need to use the passed source index iSourceIndex = iStoredSourceIndexInChange; } // move children in `columns` aggregation return oModifier.removeAggregation(oTable, COLUMNS_AGGREGATION_NAME, oMovedElement); }) .then(function(){ return oModifier.insertAggregation(oTable, COLUMNS_AGGREGATION_NAME, oMovedElement, iTargetIndex, oView); }) // move children in `items` aggregation (actual content) .then(function() { return oModifier.getBindingTemplate(oTable, ITEMS_AGGREGATION_NAME); }) .then(function(oTemplate) { if (oTemplate) { return fnSwitchCells(oModifier, oView, oTemplate, iSourceIndex, iTargetIndex) .then(function() { return fnMoveColumns(oModifier, oView, oTable, iSourceIndex, iTargetIndex, oTemplate); }); } else { return fnMoveColumns(oModifier, oView, oTable, iSourceIndex, iTargetIndex); } }); }, Promise.resolve()); }); } /** * Moves a column from one index to another. * * @param {sap.ui.fl.Change} oChange Change object with instructions to be applied on the control * @param {sap.ui.core.Control} oRelevantContainer Control that matches the change selector for applying the change, which is the source of the move * @param {object} mPropertyBag Map of properties * @param {object} mPropertyBag.view XML node representing a ui5 view * @param {sap.ui.core.util.reflection.BaseTreeModifier} mPropertyBag.modifier Modifier for the controls * @param {sap.ui.core.UIComponent} mPropertyBag.appComponent AppComponent * @return {Promise} Promise resolving when change was applied * @public */ MoveTableColumns.applyChange = function (oChange, oRelevantContainer, mPropertyBag) { var aRevertData = []; return Promise.resolve() .then(function(){ return _applyChange(oChange, oRelevantContainer, mPropertyBag, function (iStoredSourceIndexInChange) { aRevertData.unshift({ index: iStoredSourceIndexInChange }); }); }) .then(function() { oChange.setRevertData(aRevertData); }); }; /** * Reverts the change * * @param {sap.ui.fl.Change} oChange Change object with instructions to be applied on the control * @param {sap.ui.core.Control} oRelevantContainer Control that matches the change selector for applying the change, which is the source of the move * @param {object} mPropertyBag Map of properties * @param {object} mPropertyBag.view XML node representing a ui5 view * @param {sap.ui.core.util.reflection.BaseTreeModifier} mPropertyBag.modifier Modifier for the controls * @param {sap.ui.core.UIComponent} mPropertyBag.appComponent AppComponent * @return {Promise} Promise resolving when change was reverted * @public */ MoveTableColumns.revertChange = function (oChange, oRelevantContainer, mPropertyBag) { var aRevertData = oChange.getRevertData(); return Promise.resolve() .then(function(){ return _applyChange(oChange, oRelevantContainer, mPropertyBag, function () { var mItem = aRevertData.shift(); return mItem && mItem.index; }); }) .then(function() { oChange.resetRevertData(); }); }; /** * Completes the change by adding change handler specific content. * * @param {sap.ui.fl.Change} oChange Change object to be completed * @param {object} mSpecificChangeInfo Determines the attributes <code>source</code>, <code>target</code> and <code>movedElements</code> which are included in the change * @param {object} mPropertyBag Map of properties * @param {sap.ui.core.UIComponent} mPropertyBag.appComponent Component in which the change should be applied * @public */ MoveTableColumns.completeChangeContent = function (oChange, mSpecificChangeInfo, mPropertyBag) { var oModifier = mPropertyBag.modifier; var oAppComponent = mPropertyBag.appComponent; var oSourceControl = oModifier.bySelector(mSpecificChangeInfo.source.id, oAppComponent); var oTargetControl = oModifier.bySelector(mSpecificChangeInfo.target.id, oAppComponent); var mAdditionalSourceInfo = { aggregation: mSpecificChangeInfo.source.aggregation, type: oModifier.getControlType(oSourceControl) }; var mAdditionalTargetInfo = { aggregation: mSpecificChangeInfo.target.aggregation, type: oModifier.getControlType(oTargetControl) }; // We need to add the information about the movedElements together with the source and target index var oContent = {movedElements: []}; mSpecificChangeInfo.movedElements.forEach(function (mElement) { var oElement = mElement.element || oModifier.bySelector(mElement.id, oAppComponent); oContent.movedElements.push({ selector: oModifier.getSelector(oElement, oAppComponent), sourceIndex: mElement.sourceIndex, targetIndex: mElement.targetIndex }); }); oChange.setContent(oContent); oChange.addDependentControl(mSpecificChangeInfo.source.id, SOURCE_ALIAS, mPropertyBag, mAdditionalSourceInfo); oChange.addDependentControl(mSpecificChangeInfo.target.id, TARGET_ALIAS, mPropertyBag, mAdditionalTargetInfo); oChange.addDependentControl(mSpecificChangeInfo.movedElements.map(function (element) { return element.id; }), MOVED_ELEMENTS_ALIAS, mPropertyBag); }; return MoveTableColumns; }, /* bExport= */ true);