@sapui5/sap.fe.templates 1.147.0 → 1.148.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/sap/fe/templates/.library +1 -1
- package/src/sap/fe/templates/AnalyticalListPage/manifest.json +1 -1
- package/src/sap/fe/templates/ListReport/ListReport.view.xml +2 -2
- package/src/sap/fe/templates/ListReport/ListReportController.controller.js +10 -16
- package/src/sap/fe/templates/ListReport/ListReportController.controller.ts +10 -17
- package/src/sap/fe/templates/ListReport/controls/MultipleModeControl.js +4 -1
- package/src/sap/fe/templates/ListReport/controls/MultipleModeControl.ts +3 -0
- package/src/sap/fe/templates/ListReport/manifest.json +1 -1
- package/src/sap/fe/templates/ObjectPage/ExtensionAPI.js +134 -24
- package/src/sap/fe/templates/ObjectPage/ExtensionAPI.ts +132 -19
- package/src/sap/fe/templates/ObjectPage/ObjectPageController.controller.js +195 -20
- package/src/sap/fe/templates/ObjectPage/ObjectPageController.controller.ts +226 -22
- package/src/sap/fe/templates/ObjectPage/ObjectPageTemplating.js +16 -8
- package/src/sap/fe/templates/ObjectPage/ObjectPageTemplating.ts +20 -9
- package/src/sap/fe/templates/ObjectPage/components/CollaborationDiscardDialog.js +4 -1
- package/src/sap/fe/templates/ObjectPage/components/CollaborationDiscardDialog.tsx +1 -0
- package/src/sap/fe/templates/ObjectPage/components/CollaborationDraft.js +15 -4
- package/src/sap/fe/templates/ObjectPage/components/CollaborationDraft.tsx +11 -2
- package/src/sap/fe/templates/ObjectPage/controls/StashableHBox.js +28 -1
- package/src/sap/fe/templates/ObjectPage/controls/StashableHBox.ts +31 -0
- package/src/sap/fe/templates/ObjectPage/controls/SubSectionBlock.js +9 -3
- package/src/sap/fe/templates/ObjectPage/controls/SubSectionBlock.ts +9 -1
- package/src/sap/fe/templates/ObjectPage/helpers/SectionNavigationHelper.js +72 -0
- package/src/sap/fe/templates/ObjectPage/helpers/SectionNavigationHelper.ts +75 -0
- package/src/sap/fe/templates/ObjectPage/manifest.json +1 -15
- package/src/sap/fe/templates/ObjectPage/overrides/CollaborationManager.js +29 -20
- package/src/sap/fe/templates/ObjectPage/overrides/CollaborationManager.ts +28 -21
- package/src/sap/fe/templates/ObjectPage/overrides/IntentBasedNavigation.js +4 -3
- package/src/sap/fe/templates/ObjectPage/overrides/IntentBasedNavigation.ts +4 -4
- package/src/sap/fe/templates/ObjectPage/overrides/ViewState.js +93 -17
- package/src/sap/fe/templates/ObjectPage/overrides/ViewState.ts +108 -22
- package/src/sap/fe/templates/ObjectPage/view/fragments/EmphasizedFirstHeaderAction.fragment.xml +1 -0
- package/src/sap/fe/templates/ObjectPage/view/fragments/ExpandedHeading.fragment.xml +4 -4
- package/src/sap/fe/templates/ObjectPage/view/fragments/Heading.fragment.xml +4 -4
- package/src/sap/fe/templates/ObjectPage/view/fragments/ObjectPageHeaderAddress.fragment.xml +1 -1
- package/src/sap/fe/templates/ObjectPage/view/fragments/ObjectPageHeaderContact.fragment.xml +1 -1
- package/src/sap/fe/templates/ObjectPage/view/fragments/ObjectPageHeaderForm.fragment.xml +1 -0
- package/src/sap/fe/templates/library.js +1 -1
- package/src/sap/fe/templates/messagebundle_no.properties +1 -1
- package/src/sap/fe/templates/messagebundle_uk.properties +1 -1
|
@@ -25,6 +25,7 @@ import NavigationReason from "sap/fe/core/controllerextensions/routing/Navigatio
|
|
|
25
25
|
import type CommandExecution from "sap/fe/core/controls/CommandExecution";
|
|
26
26
|
import { RecommendationDialogDecision } from "sap/fe/core/controls/Recommendations/ConfirmRecommendationDialog";
|
|
27
27
|
import type { HiddenDraft, MicroChartManifestConfiguration } from "sap/fe/core/converters/ManifestSettings";
|
|
28
|
+
import { CreationMode } from "sap/fe/core/converters/ManifestSettings";
|
|
28
29
|
import type { InternalModelContext } from "sap/fe/core/helpers/ModelHelper";
|
|
29
30
|
import ModelHelper from "sap/fe/core/helpers/ModelHelper";
|
|
30
31
|
import FELibrary from "sap/fe/core/library";
|
|
@@ -48,6 +49,7 @@ import type { default as ObjectPageExtensionAPI } from "sap/fe/templates/ObjectP
|
|
|
48
49
|
import { default as ExtensionAPI } from "sap/fe/templates/ObjectPage/ExtensionAPI";
|
|
49
50
|
import CollaborationDiscard from "sap/fe/templates/ObjectPage/components/CollaborationDiscardDialog";
|
|
50
51
|
import type SubSectionBlock from "sap/fe/templates/ObjectPage/controls/SubSectionBlock";
|
|
52
|
+
import { pollForSectionStability } from "sap/fe/templates/ObjectPage/helpers/SectionNavigationHelper";
|
|
51
53
|
import TableScroller from "sap/fe/templates/TableScroller";
|
|
52
54
|
import type Button from "sap/m/Button";
|
|
53
55
|
import type InputBase from "sap/m/InputBase";
|
|
@@ -55,6 +57,7 @@ import InstanceManager from "sap/m/InstanceManager";
|
|
|
55
57
|
import type MenuButton from "sap/m/MenuButton";
|
|
56
58
|
import type NavContainer from "sap/m/NavContainer";
|
|
57
59
|
import type Popover from "sap/m/Popover";
|
|
60
|
+
import type SearchField from "sap/m/SearchField";
|
|
58
61
|
import type ToolbarSpacer from "sap/m/ToolbarSpacer";
|
|
59
62
|
import Device from "sap/ui/Device";
|
|
60
63
|
import type UI5Event from "sap/ui/base/Event";
|
|
@@ -104,6 +107,8 @@ export type BindingParams = {
|
|
|
104
107
|
bPersistOPScroll?: boolean;
|
|
105
108
|
listBinding?: ODataListBinding;
|
|
106
109
|
showPlaceholder?: boolean;
|
|
110
|
+
requestOnBinding?: string[];
|
|
111
|
+
targetControlId?: string;
|
|
107
112
|
};
|
|
108
113
|
|
|
109
114
|
const ProgrammingModel = FELibrary.ProgrammingModel;
|
|
@@ -189,6 +194,16 @@ class ObjectPageController extends PageController {
|
|
|
189
194
|
|
|
190
195
|
private previousBindingContextPath?: string;
|
|
191
196
|
|
|
197
|
+
private pendingTargetControlId?: string;
|
|
198
|
+
|
|
199
|
+
private targetSubSection?: ObjectPageSubSection;
|
|
200
|
+
|
|
201
|
+
// Flag to prevent ViewState.apply() from overriding section selection after user interaction or targetControlId navigation
|
|
202
|
+
private skipViewStateSectionRestore = false;
|
|
203
|
+
|
|
204
|
+
// Tracks if the binding context path changed (new entity vs same entity re-binding)
|
|
205
|
+
private isNewBindingContext = false;
|
|
206
|
+
|
|
192
207
|
/**
|
|
193
208
|
* Returns controls (Button / MenuButton) that are marked as "primary action".
|
|
194
209
|
* The marker is set by the converters when an action is emphasized (annotation-based) or
|
|
@@ -346,10 +361,14 @@ class ObjectPageController extends PageController {
|
|
|
346
361
|
}
|
|
347
362
|
const tableType = table.isA<Table>("sap.ui.mdc.Table") && (table.getType() as TableTypeBase);
|
|
348
363
|
const tableAPI = table.getParent()?.isA<TableAPI>("sap.fe.macros.Table") ? (table.getParent() as TableAPI) : undefined;
|
|
364
|
+
const tableControl = tableAPI?.getTableDefinition().control;
|
|
365
|
+
|
|
349
366
|
if (
|
|
350
367
|
tableType &&
|
|
351
368
|
(tableType?.isA("sap.ui.mdc.table.GridTableType") || tableType?.isA("sap.ui.mdc.table.TreeTableType")) &&
|
|
352
|
-
|
|
369
|
+
tableControl?.rowCountMode === "Auto" &&
|
|
370
|
+
// Exclude CreationRow mode unless sectionLayout is Tabs: the fit-container style creates whitespace in the subsection in edit mode when CreationRow is used in TableCreationOptions
|
|
371
|
+
(tableControl?.creationMode !== CreationMode.CreationRow || this.getView().getViewData().sectionLayout === "Tabs")
|
|
353
372
|
) {
|
|
354
373
|
//In case there is only a single table in a subSection we fit that to the whole page so that the scrollbar comes only on table and not on page
|
|
355
374
|
visibleSubSection.addStyleClass("sapUxAPObjectPageSubSectionFitContainer");
|
|
@@ -429,8 +448,30 @@ class ObjectPageController extends PageController {
|
|
|
429
448
|
}
|
|
430
449
|
|
|
431
450
|
_onBeforeBinding(oContext: ODataV4Context, mParameters: BindingParams = {}): void {
|
|
432
|
-
//
|
|
433
|
-
|
|
451
|
+
// Reset flag to allow section restoration on this new binding context.
|
|
452
|
+
// This ensures ViewState.apply() can properly restore sections after discard or re-navigation.
|
|
453
|
+
this.skipViewStateSectionRestore = false;
|
|
454
|
+
|
|
455
|
+
// Store targetControlId for scrolling after binding completes
|
|
456
|
+
this.pendingTargetControlId = mParameters.targetControlId;
|
|
457
|
+
|
|
458
|
+
// Apply targetControlId only on initial navigation - don't apply during edit/save/discard transitions
|
|
459
|
+
// to preserve user's section selection. Note: getView().getBindingContext() returns the OLD context
|
|
460
|
+
// therefore the oContext parameter is used.
|
|
461
|
+
const currentContextPath = oContext?.getPath();
|
|
462
|
+
const getEntityIdentity = (path: string | undefined): string | undefined => {
|
|
463
|
+
if (!path) return undefined;
|
|
464
|
+
// Remove IsActiveEntity from the path to get entity identity
|
|
465
|
+
// e.g., "/Products(ID=1,IsActiveEntity=true)" -> "/Products(ID=1)"
|
|
466
|
+
return path
|
|
467
|
+
.replace(/,?IsActiveEntity=(true|false),?/, "")
|
|
468
|
+
.replace(/\(\s*,/, "(")
|
|
469
|
+
.replace(/,\s*\)/, ")");
|
|
470
|
+
};
|
|
471
|
+
const currentEntityId = getEntityIdentity(currentContextPath);
|
|
472
|
+
const previousEntityId = getEntityIdentity(this.previousBindingContextPath);
|
|
473
|
+
this.isNewBindingContext = previousEntityId !== currentEntityId;
|
|
474
|
+
this.previousBindingContextPath = currentContextPath;
|
|
434
475
|
const aTables = this._findTables(),
|
|
435
476
|
oObjectPage = this._getObjectPageLayoutControl(),
|
|
436
477
|
oInternalModelContext = this.getView().getBindingContext("internal") as InternalModelContext,
|
|
@@ -690,6 +731,7 @@ class ObjectPageController extends PageController {
|
|
|
690
731
|
/**
|
|
691
732
|
* Set the initial focus in edit mode.
|
|
692
733
|
* @param aSubSections Object page sub sections
|
|
734
|
+
* @param fromTabNavigation Indicates if the focus is set after a tab navigation
|
|
693
735
|
*/
|
|
694
736
|
_updateFocusInEditMode(aSubSections: ObjectPageSubSection[], fromTabNavigation = false): void {
|
|
695
737
|
setTimeout(
|
|
@@ -697,7 +739,7 @@ class ObjectPageController extends PageController {
|
|
|
697
739
|
// We set the focus in a timeeout, otherwise the focus sometimes goes to the TabBar
|
|
698
740
|
const oObjectPage = this._getObjectPageLayoutControl();
|
|
699
741
|
const oMandatoryField = this._getFirstEmptyMandatoryFieldFromSubSection(aSubSections);
|
|
700
|
-
let oFieldToFocus;
|
|
742
|
+
let oFieldToFocus: UI5Element | undefined;
|
|
701
743
|
if (oMandatoryField) {
|
|
702
744
|
if (oMandatoryField.isA("sap.fe.macros.MultiValueField")) {
|
|
703
745
|
oFieldToFocus = (oMandatoryField as unknown as MultiValueFieldBlock).getMultiValueField();
|
|
@@ -713,9 +755,22 @@ class ObjectPageController extends PageController {
|
|
|
713
755
|
const focusInfo = oFieldToFocus.getFocusInfo() as { targetInfo: object };
|
|
714
756
|
focusInfo.targetInfo = { silent: true };
|
|
715
757
|
if (oFieldToFocus.isA("sap.ui.mdc.field.FieldInput")) {
|
|
716
|
-
oFieldToFocus = oFieldToFocus.getParent();
|
|
758
|
+
oFieldToFocus = oFieldToFocus.getParent() as UI5Element | undefined;
|
|
759
|
+
}
|
|
760
|
+
|
|
761
|
+
if (
|
|
762
|
+
oFieldToFocus?.isA<SearchField>("sap.m.SearchField") &&
|
|
763
|
+
oFieldToFocus.getEnableSuggestions() &&
|
|
764
|
+
!oFieldToFocus.isBound("enableSuggestions")
|
|
765
|
+
) {
|
|
766
|
+
// In case the focus is set on a search field with suggestions, we temporarily disable the suggestions to avoid triggering them on focus
|
|
767
|
+
// unless this property is bound (to avoid modifying something in a model)
|
|
768
|
+
oFieldToFocus.setEnableSuggestions(false);
|
|
769
|
+
oFieldToFocus.focus(focusInfo);
|
|
770
|
+
oFieldToFocus.setEnableSuggestions(true);
|
|
771
|
+
} else {
|
|
772
|
+
oFieldToFocus?.focus(focusInfo);
|
|
717
773
|
}
|
|
718
|
-
oFieldToFocus.focus(focusInfo);
|
|
719
774
|
}
|
|
720
775
|
}.bind(this),
|
|
721
776
|
fromTabNavigation ? 300 : 0
|
|
@@ -777,15 +832,24 @@ class ObjectPageController extends PageController {
|
|
|
777
832
|
|
|
778
833
|
// Function to navigate back, or display the launchpad if we're on the first page of the history
|
|
779
834
|
const navBack = (): void => {
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
835
|
+
// Use the new Navigation API if it's available in the browser, to check if we can go back in history.
|
|
836
|
+
const canGoBack = (window as { navigation?: { canGoBack?: boolean } }).navigation?.canGoBack;
|
|
837
|
+
if (canGoBack === true) {
|
|
838
|
+
history.back();
|
|
839
|
+
} else if (canGoBack === false) {
|
|
840
|
+
this._routing.navigateBackFromContext(oContext);
|
|
841
|
+
} else {
|
|
842
|
+
// Fallback in case the browser doesn't support the Navigation API
|
|
843
|
+
const currentURL = document.URL;
|
|
844
|
+
history.back();
|
|
845
|
+
// In case there is no previous page in the history, history.back does nothing.
|
|
846
|
+
// In this case, we need to use navigateBackFromContext, that will display the home page
|
|
847
|
+
setTimeout(() => {
|
|
848
|
+
if (document.URL === currentURL) {
|
|
849
|
+
this._routing.navigateBackFromContext(oContext);
|
|
850
|
+
}
|
|
851
|
+
}, 500);
|
|
852
|
+
}
|
|
789
853
|
};
|
|
790
854
|
|
|
791
855
|
if (this.getAppComponent().getRouterProxy().checkIfBackHasSameContext()) {
|
|
@@ -826,7 +890,7 @@ class ObjectPageController extends PageController {
|
|
|
826
890
|
this.editFlow.storeSiblingContextData(inputBindingContext);
|
|
827
891
|
}
|
|
828
892
|
|
|
829
|
-
this.
|
|
893
|
+
this.sideEffects.clearFieldGroupsValidity();
|
|
830
894
|
|
|
831
895
|
// TODO: this is only a temp solution as long as the model fix the cache issue and we use this additional
|
|
832
896
|
// binding with ownRequest
|
|
@@ -984,6 +1048,140 @@ class ObjectPageController extends PageController {
|
|
|
984
1048
|
applyAppState,
|
|
985
1049
|
this.previousBindingContextPath !== this.getView().getBindingContext()?.getPath()
|
|
986
1050
|
);
|
|
1051
|
+
|
|
1052
|
+
// Capture synchronously to avoid race with subsequent navigations
|
|
1053
|
+
const pendingTargetControlId = this.pendingTargetControlId;
|
|
1054
|
+
this.pendingTargetControlId = undefined;
|
|
1055
|
+
|
|
1056
|
+
this.handlePendingTargetControlIdNavigation(applyAppState, oObjectPage, pendingTargetControlId);
|
|
1057
|
+
}
|
|
1058
|
+
|
|
1059
|
+
/**
|
|
1060
|
+
* Handles navigation to a target section or subsection after app state is applied.
|
|
1061
|
+
* This coordinates targetControlId navigation from two sources:
|
|
1062
|
+
* - In-app navigation: pendingTargetControlId captured before applyAppState.
|
|
1063
|
+
* - Cross-app navigation: xAppState targetControlId stored by AppStateHandler during LR to OP transition.
|
|
1064
|
+
* @param applyAppState Promise that resolves when app state has been applied.
|
|
1065
|
+
* @param oObjectPage The ObjectPageLayout control.
|
|
1066
|
+
* @param pendingTargetControlId The targetControlId captured before applyAppState, if any.
|
|
1067
|
+
*/
|
|
1068
|
+
private handlePendingTargetControlIdNavigation(
|
|
1069
|
+
applyAppState: Promise<void | object>,
|
|
1070
|
+
oObjectPage: ObjectPageLayout,
|
|
1071
|
+
pendingTargetControlId: string | undefined
|
|
1072
|
+
): void {
|
|
1073
|
+
applyAppState
|
|
1074
|
+
.then(async () => {
|
|
1075
|
+
const xAppStateTargetControlId = this.getAppComponent().getAppStateHandler()?.consumePendingTargetControlId();
|
|
1076
|
+
const targetControlId = pendingTargetControlId ?? xAppStateTargetControlId;
|
|
1077
|
+
if (!targetControlId) {
|
|
1078
|
+
return;
|
|
1079
|
+
}
|
|
1080
|
+
|
|
1081
|
+
// Wait for visibility bindings (needed for lazy loading scenarios)
|
|
1082
|
+
try {
|
|
1083
|
+
await Promise.all(this.waitForVisibilityBindings);
|
|
1084
|
+
} catch {
|
|
1085
|
+
// Some visibility bindings failed to resolve, proceeding anyway
|
|
1086
|
+
}
|
|
1087
|
+
|
|
1088
|
+
// Wait for pageReady to ensure ObjectPage is fully initialized
|
|
1089
|
+
await this.pageReady.waitPageReady();
|
|
1090
|
+
|
|
1091
|
+
// Navigate to target section
|
|
1092
|
+
this.navigateToTargetSection(oObjectPage, targetControlId);
|
|
1093
|
+
return; // Required by linter rule promise/always-return
|
|
1094
|
+
})
|
|
1095
|
+
.catch(() => {
|
|
1096
|
+
// applyAppState failed - skip targetControlId navigation
|
|
1097
|
+
});
|
|
1098
|
+
}
|
|
1099
|
+
|
|
1100
|
+
/**
|
|
1101
|
+
* Navigates to a target section with automatic re-navigation if UX rules reset the selection.
|
|
1102
|
+
* Polls the section state since setSelectedSection() doesn't fire the navigate event.
|
|
1103
|
+
* @param oObjectPage The ObjectPageLayout control.
|
|
1104
|
+
* @param targetControlId The local ID of the target section or subsection.
|
|
1105
|
+
*/
|
|
1106
|
+
private navigateToTargetSection(oObjectPage: ObjectPageLayout, targetControlId: string): void {
|
|
1107
|
+
// Determine target section ID for comparison
|
|
1108
|
+
const targetControl = this.getView().byId(targetControlId);
|
|
1109
|
+
const isSection = targetControl?.isA("sap.uxap.ObjectPageSection");
|
|
1110
|
+
const targetSectionId = isSection ? targetControl?.getId() : (targetControl?.getParent() as ObjectPageSection)?.getId();
|
|
1111
|
+
|
|
1112
|
+
// Navigate function with guard to prevent duplicate calls when already on target
|
|
1113
|
+
const navigateToTarget = (): void => {
|
|
1114
|
+
if (oObjectPage.getSelectedSection() === targetSectionId) {
|
|
1115
|
+
return; // Already on target section
|
|
1116
|
+
}
|
|
1117
|
+
this.navigateWithConfirmation(targetControlId);
|
|
1118
|
+
};
|
|
1119
|
+
|
|
1120
|
+
// Navigate immediately
|
|
1121
|
+
navigateToTarget();
|
|
1122
|
+
|
|
1123
|
+
// Skip polling if already on target section (navigation was no-op or succeeded immediately)
|
|
1124
|
+
if (oObjectPage.getSelectedSection() === targetSectionId) {
|
|
1125
|
+
this.skipViewStateSectionRestore = true;
|
|
1126
|
+
return;
|
|
1127
|
+
}
|
|
1128
|
+
|
|
1129
|
+
// Poll to detect UX rules reset only on new entity binding.
|
|
1130
|
+
// _adjustSelectedSectionByUXRules() only runs when ObjectPageLayout re-initializes with a new entity.
|
|
1131
|
+
if (this.isNewBindingContext) {
|
|
1132
|
+
pollForSectionStability({
|
|
1133
|
+
getSelectedSection: () => oObjectPage.getSelectedSection(),
|
|
1134
|
+
targetSectionId,
|
|
1135
|
+
onResetDetected: navigateToTarget
|
|
1136
|
+
})
|
|
1137
|
+
.then(() => {
|
|
1138
|
+
this.skipViewStateSectionRestore = true;
|
|
1139
|
+
return; // Required by linter rule promise/always-return
|
|
1140
|
+
})
|
|
1141
|
+
.catch(() => {
|
|
1142
|
+
// Required by linter rule promise/catch-or-return - polling failures are non-critical
|
|
1143
|
+
});
|
|
1144
|
+
}
|
|
1145
|
+
}
|
|
1146
|
+
|
|
1147
|
+
/**
|
|
1148
|
+
* Sets targetSubSection based on the target control ID for app state persistence.
|
|
1149
|
+
* @param targetControlId The local ID of the target section or subsection.
|
|
1150
|
+
*/
|
|
1151
|
+
private setTargetSubSection(targetControlId: string): void {
|
|
1152
|
+
const targetControl = this.getView().byId(targetControlId);
|
|
1153
|
+
if (targetControl?.isA<ObjectPageSubSection>("sap.uxap.ObjectPageSubSection")) {
|
|
1154
|
+
this.targetSubSection = targetControl;
|
|
1155
|
+
} else if (targetControl?.isA<ObjectPageSection>("sap.uxap.ObjectPageSection")) {
|
|
1156
|
+
const subSections = targetControl.getSubSections();
|
|
1157
|
+
this.targetSubSection = subSections[0];
|
|
1158
|
+
}
|
|
1159
|
+
}
|
|
1160
|
+
|
|
1161
|
+
/**
|
|
1162
|
+
* Performs navigation to the target section and then updates the app state.
|
|
1163
|
+
* @param targetControlId The local ID of the target section or subsection.
|
|
1164
|
+
*/
|
|
1165
|
+
private navigateWithConfirmation(targetControlId: string): void {
|
|
1166
|
+
// Set targetSubSection BEFORE navigation for app state saving.
|
|
1167
|
+
// scrollToSection() doesn't fire the navigate event, so onNavigateChange won't be called.
|
|
1168
|
+
this.setTargetSubSection(targetControlId);
|
|
1169
|
+
|
|
1170
|
+
this.getExtensionAPI().navigateToSubSection(targetControlId);
|
|
1171
|
+
|
|
1172
|
+
// Wait for ExtensionAPI polling to complete (~100ms) plus scroll to finish
|
|
1173
|
+
// before updating app state and setting focus.
|
|
1174
|
+
setTimeout(() => {
|
|
1175
|
+
this.viewState.updateAppStateDebounced();
|
|
1176
|
+
|
|
1177
|
+
// Set focus if in edit mode (for in-app navigation to sub-object page in edit mode)
|
|
1178
|
+
// This is needed because scrollToSection() doesn't fire onNavigateChange,
|
|
1179
|
+
// so we need to manually trigger focus setting here
|
|
1180
|
+
const isInEditMode = CommonUtils.getIsEditable(this.getView());
|
|
1181
|
+
if (isInEditMode && this.targetSubSection) {
|
|
1182
|
+
this._updateFocusInEditMode([this.targetSubSection], false);
|
|
1183
|
+
}
|
|
1184
|
+
}, 150);
|
|
987
1185
|
}
|
|
988
1186
|
|
|
989
1187
|
/**
|
|
@@ -1384,9 +1582,7 @@ class ObjectPageController extends PageController {
|
|
|
1384
1582
|
// If there is at least one global SideEffects for the related entity, execute it/them
|
|
1385
1583
|
if (globalSideEffects.length) {
|
|
1386
1584
|
await this.editFlow.syncTask();
|
|
1387
|
-
return Promise.all(
|
|
1388
|
-
globalSideEffects.map(async (sideEffects) => this._sideEffects.requestSideEffects(sideEffects, context))
|
|
1389
|
-
);
|
|
1585
|
+
return Promise.all(globalSideEffects.map(async (sideEffects) => this.sideEffects.requestSideEffects(sideEffects, context)));
|
|
1390
1586
|
}
|
|
1391
1587
|
}
|
|
1392
1588
|
|
|
@@ -2204,17 +2400,25 @@ class ObjectPageController extends PageController {
|
|
|
2204
2400
|
|
|
2205
2401
|
onNavigateChange(this: ObjectPageController, oEvent: UI5Event<{ subSection: ObjectPageSubSection }>): void {
|
|
2206
2402
|
//will be called always when we click on a section tab
|
|
2207
|
-
this.getExtensionAPI().updateAppState();
|
|
2208
2403
|
this.bSectionNavigated = true;
|
|
2209
2404
|
|
|
2405
|
+
// Prevent ViewState from overriding the user's manual tab selection.
|
|
2406
|
+
// This is important after discard when ViewState.apply might try to restore the previous section.
|
|
2407
|
+
this.skipViewStateSectionRestore = true;
|
|
2408
|
+
|
|
2409
|
+
const subSection = oEvent.getParameter("subSection");
|
|
2410
|
+
this.targetSubSection = subSection;
|
|
2411
|
+
|
|
2412
|
+
this.getExtensionAPI().updateAppState();
|
|
2413
|
+
|
|
2210
2414
|
const oInternalModelContext = this.getView().getBindingContext("internal") as InternalModelContext;
|
|
2415
|
+
|
|
2211
2416
|
if (
|
|
2212
2417
|
CommonUtils.getIsEditable(this.getView()) &&
|
|
2213
2418
|
this.getView().getViewData().sectionLayout === "Tabs" &&
|
|
2214
2419
|
oInternalModelContext.getProperty("errorNavigationSectionFlag") === false
|
|
2215
2420
|
) {
|
|
2216
|
-
|
|
2217
|
-
this._updateFocusInEditMode([oSubSection], true);
|
|
2421
|
+
this._updateFocusInEditMode([subSection], true);
|
|
2218
2422
|
}
|
|
2219
2423
|
},
|
|
2220
2424
|
onVariantSelected: function (this: ObjectPageController): void {
|