Skip to content

Latest commit

 

History

History
329 lines (275 loc) · 12.4 KB

Step_9_List_Detail_Scenario_ec44581.md

File metadata and controls

329 lines (275 loc) · 12.4 KB
loio
ec445816634f45eb88a7e559187dac46

Step 9: List-Detail Scenario

In this step we add a detail area with additional information.


A detail area containing information about the selected user is added

A list of users with an added detail area


You can view and download all files at OData V4 - Step 9.


...
        onDelete : function () {
            var oContext,
                oPeopleList = this.byId("peopleList"),
                oSelected = oPeopleList.getSelectedItem(),
                sUserName;
 
            if (oSelected) {
                oContext = oSelected.getBindingContext();
                sUserName = oContext.getProperty("UserName");
                oContext.delete().then(function () {
                    MessageToast.show(this._getText("deletionSuccessMessage", sUserName));
                }.bind(this), function (oError) {
                    if (oContext === oPeopleList.getSelectedItem().getBindingContext()) {
                        this._setDetailArea(oContext);
                    }
                    this._setUIChanges();
                    if (oError.canceled) {
                        MessageToast.show(this._getText("deletionRestoredMessage", sUserName));
                        return;
                    }
                    MessageBox.error(oError.message + ": " + sUserName);
                }.bind(this));
                this._setDetailArea();
                this._setUIChanges(true);
            }
        },
...
		onMessageBindingChange : function (oEvent) {
			...
		},

		onSelectionChange : function (oEvent) {
            this._setDetailArea(oEvent.getParameter("listItem").getBindingContext());
        },

...		
         /**
         * Toggles the visibility of the detail area
         *
         * @param {object} [oUserContext] - the current user context
         */
        _setDetailArea : function (oUserContext) {
            var oDetailArea = this.byId("detailArea"),
                oLayout = this.byId("defaultLayout"),
                oSearchField = this.byId("searchField");
 
            oDetailArea.setBindingContext(oUserContext || null);
            // resize view
            oDetailArea.setVisible(!!oUserContext);
            oLayout.setSize(oUserContext ? "60%" : "100%");
            oLayout.setResizable(!!oUserContext);
            oSearchField.setWidth(oUserContext ? "40%" : "20%");
        }

The onSelectionChange event handler retrieves the context of the selected list item and passes it to a new _setDetailArea function. Within _setDetailArea, the given context is passed as binding context for the semantic page detail area.

Afterwards the detail area is made visible and is resized.

The application also needs to close the detail area if its binding context is deleted. If the deleted context is restored after a failed DELETE request, or undeleted via Context#resetChanges, it could be shown in the detail area again, unless the user had selected another row in the meantime. Hence, we call _setDetailArea without a context once the context gets deleted, and with the restored context in the error handler of the Context#delete API. In _setDetailArea we resize the view based on the given context in an appropriate way.


<mvc:View
	controllerName="sap.ui.core.tutorial.odatav4.controller.App"
	displayBlock="true"
	xmlns="sap.m"
	xmlns:mvc="sap.ui.core.mvc"
	xmlns:l="sap.ui.layout"
	xmlns:semantic="sap.f.semantic"
	xmlns:f="sap.ui.layout.form"
	xmlns:core="sap.ui.core">
	<Shell>
		<App busy="{appView>/busy}" class="sapUiSizeCompact">
			<pages>
				...
					<content>
						<l:ResponsiveSplitter defaultPane="defaultPane">
							<l:PaneContainer orientation="Horizontal">
								<l:SplitPane id="defaultPane">
									<l:layoutData>
										<l:SplitterLayoutData id="defaultLayout" size="100%" resizable="false"/>
									</l:layoutData>
									<Table
										id="peopleList"
										growing="true"
										growingThreshold="10"
										items="{
											path: '/People',
											parameters: {
												$count: true,
												$$updateGroupId : 'peopleGroup'
											}
										}"
										mode="SingleSelectLeft"
										selectionChange=".onSelectionChange">
										<headerToolbar>
											...
										</headerToolbar>
										...
									</Table>
								</l:SplitPane>
								<l:SplitPane>
									<!--Details-->
									<!--remove busy-->
									<semantic:SemanticPage
										id="detailArea"
										visible="false">
										<semantic:titleHeading>
											<Title
												text="{FirstName} {LastName}"
												level="H2"/>
										</semantic:titleHeading>
										<semantic:headerContent>
												<FlexBox>
													<VBox>
														<ObjectAttribute text="{i18n>userNameLabelText}"/>
														<ObjectAttribute text="{UserName}"/>
													</VBox>
													<VBox class="sapUiMediumMarginBegin">
														<ObjectAttribute text="{i18n>ageLabelText}"/>
														<ObjectNumber number="{Age}" unit="Years"/>
													</VBox>
												</FlexBox>
										</semantic:headerContent>
										<semantic:content>
											<VBox>
												<FlexBox wrap="Wrap">
													<f:Form	editable="false">
														<f:title>
															<core:Title text="{i18n>addressTitleText}" />
														</f:title>
														<f:layout>
															<f:ResponsiveGridLayout
																labelSpanXL="3"
																labelSpanL="3"
																labelSpanM="3"
																labelSpanS="12"
																adjustLabelSpan="false"
																emptySpanXL="4"
																emptySpanL="4"
																emptySpanM="4"
																emptySpanS="0"
																columnsXL="1"
																columnsL="1"
																columnsM="1"
																singleContainerFullSize="false" />
														</f:layout>
														<f:formContainers>
															<f:FormContainer>
																<f:formElements>
																	<f:FormElement label="{i18n>addressLabelText}">
																		<f:fields>
																			<Text text="{HomeAddress/Address}" />
																		</f:fields>
																	</f:FormElement>
																	<f:FormElement label="{i18n>cityLabelText}">
																		<f:fields>
																			<Text text="{HomeAddress/City/Name}" />
																		</f:fields>
																	</f:FormElement>
																	<f:FormElement label="{i18n>regionLabelText}">
																		<f:fields>
																			<Text text="{HomeAddress/City/Region}" />
																		</f:fields>
																	</f:FormElement>
																	<f:FormElement label="{i18n>countryLabelText}">
																		<f:fields>
																			<Text text="{HomeAddress/City/CountryRegion}" />
																		</f:fields>
																	</f:FormElement>
																</f:formElements>
															</f:FormContainer>
														</f:formContainers>
													</f:Form>
													<f:Form	editable="false">
														<f:title>
															<core:Title text="{i18n>bestFriendTitleText}" />
														</f:title>
														<f:layout>
															<f:ResponsiveGridLayout
																labelSpanXL="3"
																labelSpanL="3"
																labelSpanM="3"
																labelSpanS="12"
																adjustLabelSpan="false"
																emptySpanXL="4"
																emptySpanL="4"
																emptySpanM="4"
																emptySpanS="0"
																columnsXL="1"
																columnsL="1"
																columnsM="1"
																singleContainerFullSize="false" />
														</f:layout>
														<f:formContainers>
															<f:FormContainer>
																<f:formElements>
																	<f:FormElement label="{i18n>nameLabelText}">
																		<f:fields>
																			<Text text="{BestFriend/FirstName} {BestFriend/LastName}" />
																		</f:fields>
																	</f:FormElement>
																	<f:FormElement label="{i18n>ageLabelText}">
																		<f:fields>
																			<Text text="{BestFriend/Age}" />
																		</f:fields>
																	</f:FormElement>
																	<f:FormElement label="{i18n>userNameLabelText}">
																		<f:fields>
																			<Text text="{BestFriend/UserName}" />
																		</f:fields>
																	</f:FormElement>
																</f:formElements>
															</f:FormContainer>
														</f:formContainers>
													</f:Form>
												</FlexBox>
											</VBox>
										</semantic:content>
									</semantic:SemanticPage>
								</l:SplitPane>
							</l:PaneContainer>
						</l:ResponsiveSplitter>
					</content>
					...
</mvc:View>

Several new namespaces are added to the appView. After the <content> and before the <Table> tag the first part of the SplitPane is added.

We add a detail area after the user table. In the appView we add a splitter layout around the existing table. The first SplitPane contains the table with all users, and the second one contains the new detail area. It consists of two forms, one for the address information, and the other one for the best friend of the currently selected user. We also add the onSelectionChange event handler to the user table.

It is important that all bindings we introduced in the detail area are relative (property) bindings, so that we can reuse data of the list. This allows our application to share data like the user name or the age between the user selected in the table and the detail area. This helps to avoid redundant requests and to keep the data between the two areas in sync. Editing a property in the user table will thus automatically be reflected in the detail area as well.

One of the most vital parts of the data reuse functionality is the usage of the autoExpandSelect binding parameter. It permits us to put a tailored $select clause in the GET request, so that only missing properties are requested for display in the detail area.


...
# Detail Area
#XTIT: Title for Address
addressTitleText=Address
 
#XFLD: Label for Address
addressLabelText=Address
 
#XFLD: Label for City
cityLabelText=City
 
#XFLD: Label for Region
regionLabelText=Region
 
#XFLD: Label for Country
countryLabelText=Country
 
#XTIT: Title for Best Friend
bestFriendTitleText=Best Friend
 
#XFLD: Label for Best Friend Name
nameLabelText=Name

We add the missing texts to the properties file.

Parent topic:OData V4 Tutorial

Next:Step 8: OData Operations

Previous:Step 10: Enable Data Reuse

Related Information

Data Reuse