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.
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.
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.
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: