Show TOC

Step 10: Detail XML FragmentsLocate this document in the navigation structure

In the Detail View section, we referenced XML fragments in the sap.m.IconTabFilters. These fragments are separately maintainable and reusable collections of control declarations.

In both cases, for the Supplier and Category information display, we use the sap.ui.layout.form.SimpleForm. This offers a flexible approach to building responsive form layouts that automatically adjust according to screen size.

Because of the way Fragments are instantiated and inserted, the binding context is inherited according to the insertion point. So in the case of both of the XML fragments that we have for our app, the binding context is relative to the binding already on the detail view.

Here are the XML fragments. Both are held in their own files, and are normally kept in the same folder as the views and controllers.

SupplierAddressForm

First up is the SupplierAddressForm fragment, in file SupplierAddressForm.fragment.xml.

<core:FragmentDefinition
	xmlns:l="sap.ui.layout"
	xmlns:f="sap.ui.layout.form"
	xmlns:core="sap.ui.core"
	xmlns="sap.m">

This outermost element core:FragmentDefinition is not strictly necessary here, as our control definition has a single root node l:Grid. However, it's good practice to always use this core:FragmentDefinition element as a container, not least because then any additional root node in the definition doesn't cause a bigger change during maintenance. The container element doesn't have any representation in the HTML.

<l:Grid
		defaultSpan="L12 M12 S12"
		width="auto">
		<l:content>
			<f:SimpleForm
				minWidth="1024"
				maxContainerCols="2"
				editable="false"
				layout="ResponsiveGridLayout"
				title="{i18n>supplierAddress}"
				labelSpanL="3"
				labelSpanM="3"
				emptySpanL="4"
				emptySpanM="4"
				columnsL="1"
				columnsM="1">
				<f:content>
					<Label text="{i18n>supplierAddressName}" />
					<Text text="{Name}" />
					<Label text="{i18n>supplierAddressStreet}" />
					<Text text="{Address/Street}" />
					<Label text="{i18n>supplierAddressCity}" />
					<Text text="{Address/City}" />
					<Label text="{i18n>supplierAddressZIPCode}" />
					<Text text="{Address/ZipCode}" />
					<Label text="{i18n>supplierAddressCountry}" />
					<Text text="{Address/Country}" />
				</f:content>
			</f:SimpleForm>
		</l:content>
	</l:Grid>
</core:FragmentDefinition>

The SimpleForm's layout is a series of sap.m.Label and sap.m.Text controls. Note that the Supplier address is defined as a ComplexType in the OData service and this type is used in the definition of the Supplier entity:

<Schema Namespace="ODataDemo" ...>
  <EntityType Name="Supplier">
    <Key>
      <PropertyRef Name="ID" />
    </Key>
    <Property Name="ID" Type="Edm.Int32" ... />
    <Property Name="Name" Type="Edm.String" ... />
    <Property Name="Address" Type="ODataDemo.Address" ... />
    ...
  </EntityType>

  ...

  <ComplexType Name="Address">
    <PropertyRef Name="Street" ... />
    <PropertyRef Name="City" ... />
    ...
  </EntityType>

  ...
</Schema>

This means that we can refer to the address details for a Supplier entity via a binding path that includes an "Address/" prefix, as seen in the bindings for the text properties of the address-relevant Text controls.

CategoryInfoForm

Here's the CategoryInfoForm fragment.

<core:FragmentDefinition
	xmlns:l="sap.ui.layout"
	xmlns:f="sap.ui.layout.form"
	xmlns:core="sap.ui.core"
	xmlns="sap.m">
	<l:Grid
		defaultSpan="L12 M12 S12"
		width="auto">
		<l:content>
			<f:SimpleForm
				minWidth="1024"
				maxContainerCols="2"
				editable="false"
				layout="ResponsiveGridLayout"
				title="{i18n>categoryInfo}"
				labelSpanL="3"
				labelSpanM="3"
				emptySpanL="4"
				emptySpanM="4"
				columnsL="1"
				columnsM="1">
				<f:content>
					<Label text="{i18n>categoryInfoID}" />
					<Text text="{ID}" />
					<Label text="{i18n>categoryInfoName}" />
					<Text text="{Name}" />
				</f:content>
			</f:SimpleForm>
		</l:content>
	</l:Grid>
</core:FragmentDefinition>

It's very similar to the SupplierAddressForm fragment. Again, the bindings for the Text controls are relative to where the fragment is inserted; in this case it will be relative to the associated Category.

Progress Check

With the fragment files added to the view subfolder, our app folder content now looks like this:

tdg/
  |
  +-- i18n/
  |     |
  |     +-- messageBundle.properties
  |
  +-- util/
  |     |
  |     +-- Formatter.js
  |
  +-- view/
  |     |
  |     +-- App.view.xml
  |     +-- CategoryInfoForm.fragment.xml
  |     +-- Detail.controller.js
  |     +-- Detail.view.xml
  |     +-- Master.controller.js
  |     +-- Master.view.xml
  |     +-- SupplierAddressForm.fragment.xml
  |
  +-- Component.js
  +-- index.html
  +-- MyRouter.html

And when we uncomment the fragment insertion points in the detail view (see the Detail View section)

<items>
	<IconTabFilter
		key="supplier"
		text="{i18n>iconTabFilterSupplier}"
		icon="sap-icon://supplier">
		<content>
			<core:Fragment fragmentName="sap.ui.demo.tdg.view.SupplierAddressForm" type="XML" />
		</content>
	</IconTabFilter>
	<IconTabFilter
		key="category"
		text="{i18n>iconTabFilterCategory}"
		icon="sap-icon://hint">
		<content>
			<core:Fragment fragmentName="sap.ui.demo.tdg.view.CategoryInfoForm" type="XML" />
		</content>
	</IconTabFilter>
</items>

our app now looks like this, when a product is selected (remember, the default IconTabFilter is the for the supplier information):

And it looks like this when the category IconTabFilter is selected: