<!DOCTYPE HTML>
<html>
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<script>
window["sap-ui-config"] = {
libs: "sap.ui.core, sap.m",
theme: "sap_belize_plus",
preload: "async",
compatVersion: "edge",
resourceRoots: {
"demo": "./",
},
"xx-componentPreload": "off",
"xx-waitForTheme": true,
onInit: () => sap.ui.component({
id: "rootComponent",
async: true,
manifestFirst: true,
name: "demo",
}).then(createdComponent => sap.ui.require([
"sap/m/Shell",
"sap/ui/core/ComponentContainer"
], (Shell, ComponentContainer) => new Shell({
app: new ComponentContainer("rootComponentContainer", {
component: createdComponent,
height: "100%",
}),
}).placeAt("content"))),
}
</script>
<script id="sap-ui-bootstrap"
src="https://openui5.hana.ondemand.com/1.44.36/resources/sap-ui-core.js"></script>
</head>
<body class="sapUiBody" id="content">
</body>
</html>
sap.ui.define([
"sap/ui/core/UIComponent",
"sap/ui/core/ComponentContainer"
], function(UIComponent, ComponentContainer) {
"use strict";
return UIComponent.extend("demo.Component", {
metadata: {
manifest: "json"
},
init: function() {
UIComponent.prototype.init.apply(this, arguments);
this.getRootControl().loaded().then(() => {
// Avoiding race condition. In this old UI5 version, it is still possible that the root view was not loaded at all when the router tries to place the home view at the root control.
this.getRouter().initialize();
});
}
});
});
{
"_version": "1.7.0",
"start_url": "index.html",
"sap.app": {
"id": "demo",
"type": "application",
"i18n": "",
"title": "Demo",
"description": "Sample Code",
"applicationVersion": {
"version": "1.0.0"
},
"embeds": [
"component_B"
]
},
"sap.ui": {
"technology": "UI5",
"deviceTypes": {
"desktop": true,
"tablet": true,
"phone": true
},
"supportedThemes": [
"sap_belize_hcw",
"sap_belize_hcb",
"sap_belize",
"sap_belize_plus"
]
},
"sap.ui5": {
"autoPrefixId": true,
"resourceRoots": {
"anotherComponent": "./component_B"
},
"dependencies": {
"minUI5Version": "1.44.36",
"components": {
"anotherComponent": {}
},
"libs": {
"sap.ui.core": {},
"sap.m": {},
"sap.uxap": {
"lazy": true
},
"sap.ui.layout": {
"lazy": true
},
"sap.f": {
"lazy": true
}
}
},
"resources": {},
"contentDensities": {
"compact": true,
"cozy": true
},
"models": {},
"rootView": {
"viewName": "demo.view.App",
"id": "rootView",
"type": "XML",
"async": true,
"height": "100%",
"displayBlock": true
},
"routing": {
"routes": [{
"name": "home",
"pattern": "",
"target": ["home"]
}],
"targets": {
"home": {
"viewId": "homeView",
"viewName": "Home",
"transition": "fade",
"viewLevel": 1
},
"notFound": {
"viewName": "Home",
"transition": "slide",
"viewLevel": 98
}
},
"config": {
"async": true,
"routerClass": "sap.m.routing.Router",
"viewType": "XML",
"viewPath": "demo.view",
"controlId": "rootApp",
"controlAggregation": "pages",
"transition": "slide",
"bypassed": {
"target": "notFound"
},
"homeRoute": "home"
}
}
}
}
<mvc:View
xmlns:mvc="sap.ui.core.mvc"
xmlns="sap.m"
height="100%"
displayBlock="true"
>
<App id="rootApp" />
</mvc:View>
<mvc:View
xmlns:mvc="sap.ui.core.mvc"
xmlns:core="sap.ui.core"
xmlns="sap.m"
controllerName="demo.controller.Home"
>
<Page id="homePage" title="Component-A">
<core:ComponentContainer id="childContainer"
lifecycle="Container"
height="100%"
/>
</Page>
</mvc:View>
sap.ui.define([
"sap/ui/core/mvc/Controller",
], function(Controller) {
"use strict";
return Controller.extend("demo.controller.Home", {
onInit: function() {
sap.ui.component({ // Has to be created in the Controller as the ComponentContainer doesn't evaluate child component's descriptor if the settings are defined in the view.
id: "myChildComponent",
manifestFirst: true,
async: true,
name: "anotherComponent"
}).then(this.setChildComponent.bind(this));
},
setChildComponent: function(component) {
this.byId("childContainer").setComponent(component);
},
});
});
sap.ui.define([
"sap/ui/core/UIComponent",
"sap/ui/Device",
"sap/ui/model/json/JSONModel"
], function(UIComponent, Device, JSONModel) {
"use strict";
return UIComponent.extend("anotherComponent.Component", {
metadata: {
manifest: "json"
},
init: function() {
UIComponent.prototype.init.apply(this, arguments);
this.getModel("device").setDefaultBindingMode("OneWay").setData(Device);
this.getRootControl().loaded().then(() => {
// Avoiding race condition. In this old UI5 version, it is still possible that the root view was not loaded at all when the router tries to place the home view at the root control.
this.getRouter().initialize();
});
},
});
});
{
"_version": "1.7.0",
"sap.app": {
"id": "anotherComponent",
"type": "component",
"title": "Demo",
"description": "Sample Code",
"applicationVersion": {
"version": "1.0.0"
},
"dataSources": {
"odataDemo": {
"uri": "https://cors-anywhere.herokuapp.com/https://services.odata.org/V2/Northwind/Northwind.svc/",
"type": "OData",
"settings": {
"odataVersion": "2.0"
}
}
},
"embeddedBy": "../"
},
"sap.ui": {
"technology": "UI5",
"deviceTypes": {
"desktop": true,
"tablet": true,
"phone": true
},
"supportedThemes": [
"sap_belize_hcw",
"sap_belize_hcb",
"sap_belize",
"sap_belize_plus"
]
},
"sap.ui5": {
"dependencies": {
"minUI5Version": "1.44.36",
"libs": {
"sap.ui.core": {},
"sap.m": {}
}
},
"models": {
"odataModel": {
"dataSource": "odataDemo",
"settings": {
"tokenHandling": false
},
"preload": true
},
"device": {
"type": "sap.ui.model.json.JSONModel"
},
"count": {
"type": "sap.ui.model.json.JSONModel"
}
},
"contentDensities": {
"compact": true,
"cozy": true
},
"rootView": {
"viewName": "anotherComponent.view.SplitContainer",
"id": "splitContainerView",
"type": "XML",
"async": true,
"height": "100%",
"displayBlock": true
},
"routing": {
"routes": [{
"name": "master",
"pattern": "",
"target": ["detail", "master"],
"parent": "demo.Component:home"
}, {
"name": "masterDetail",
"pattern": "items/{itemId}",
"target": ["master", "detail"],
"parent": "demo.Component:home"
}],
"targets": {
"master": {
"viewId": "masterView",
"viewName": "Master",
"controlAggregation": "masterPages"
},
"detail": {
"viewId": "detailView",
"viewName": "Detail",
"controlAggregation": "detailPages"
}
},
"config": {
"routerClass": "sap.m.routing.Router",
"async": true,
"viewType": "XML",
"viewPath": "anotherComponent.view",
"controlId": "rootSplitContainer"
}
}
}
}
sap.ui.define([
"sap/ui/core/mvc/Controller"
], function(Controller) {
"use strict";
return Controller.extend("anotherComponent.controller.Detail", {
onInit: function() {
var route = this.getOwnerComponent().getRouter().getRoute("masterDetail");
route.attachPatternMatched(this.onPatternMatched, this);
},
onDataRequested: function () {
this.byId("page").setBusy(true);
},
onDetailChange: function () {
this.getOwnerComponent().getEventBus().publish("root", "hideMaster");
this.byId("page").setBusy(false);
},
onPatternMatched: function(event) {
var model = this.getOwnerComponent().getModel("odataModel");
var itemId = event.getParameter("arguments").itemId;
model.metadataLoaded().then(this.bindSelectedItem.bind(this, itemId));
},
bindSelectedItem: function(itemId) {
var model = this.getOwnerComponent().getModel("odataModel");
var key = model.createKey("Products", {
ProductID: itemId,
});
this.getView().bindElement({
path: "odataModel>/" + key,
parameters: {
expand: [
"Supplier",
"Category",
"Order_Details/Order/Customer"
].join(","),
select: [
"ProductID",
"ProductName",
"Order_Details/OrderID",
"Order_Details/Order/OrderDate",
"Order_Details/Order/Customer/CompanyName"
].join(",")
},
events: {
dataRequested: this.onDataRequested.bind(this),
change: this.onDetailChange.bind(this),
}
});
}
});
});
sap.ui.define([
"sap/ui/core/mvc/Controller",
"sap/ui/Device"
], function(Controller, Device) {
"use strict";
return Controller.extend("anotherComponent.controller.Master", {
onItemPress: function(event) {
const item = event.getParameter("listItem");
this.navToDetailOf(item);
},
onListUpdateFinished: function(event) {
const list = this.byId("masterList");
const count = event.getParameter("total");
this.getOwnerComponent().getModel("count").setProperty("/master", count);
const currentDetail = this.getCurrentDetail();
if (currentDetail) {
this.displayDetailOfFirstItem(list);
}
},
displayDetailOfFirstItem: function(masterList) {
const items = masterList.getItems();
const containingData = item => item.getBindingContext("odataModel");
const firstItemToSelect = items.find(containingData);
if (firstItemToSelect) {
masterList.setSelectedItem(firstItemToSelect);
this.navToDetailOf(firstItemToSelect);
setTimeout(() => firstItemToSelect.focus());
}
},
navToDetailOf: function(item) {
this.getOwnerComponent().getRouter().navTo("masterDetail", {
itemId: item.getBindingContext("odataModel").getProperty("ProductID")
}, !Device.system.phone);
},
getCurrentDetail: function() { // Move to BaseController
const rootView = this.getOwnerComponent().getRootControl();
const splitContainer = rootView.byId("rootSplitContainer");
return splitContainer.getCurrentDetailPage();
}
});
});
sap.ui.define([
"sap/ui/core/mvc/Controller"
], function(Controller) {
"use strict";
return Controller.extend("anotherComponent.controller.SplitContainer", {
onInit: function() {
var eventBus = this.getOwnerComponent().getEventBus();
eventBus.subscribe("root", "hideMaster", this.shouldHideMaster, this);
},
shouldHideMaster: function () {
this.byId("rootSplitContainer").hideMaster();
},
});
});
<mvc:View
xmlns:mvc="sap.ui.core.mvc"
xmlns="sap.m"
controllerName="anotherComponent.controller.Detail"
>
<Page id="page"
title="Product: {odataModel>ProductName}"
busyIndicatorDelay="600"
>
<Table items="{odataModel>Order_Details}">
<columns>
<Column>
<Text text="Order ID" />
</Column>
<Column>
<Text text="Order Date" />
</Column>
<Column>
<Text text="Customer" />
</Column>
</columns>
<items>
<ColumnListItem>
<cells>
<Text text="{odataModel>OrderID}"/>
<Text text="{
path: 'odataModel>Order/OrderDate',
type: 'sap.ui.model.odata.type.DateTime',
formatOptions: {
style: 'short'
}
}"/>
<Text text="{odataModel>Order/Customer/CompanyName}"/>
</cells>
</ColumnListItem>
</items>
</Table>
<footer>
<OverflowToolbar>
<ToolbarSpacer></ToolbarSpacer>
<Button text="Dummy1" type="Accept" />
<Button text="Dummy2" type="Reject" />
</OverflowToolbar>
</footer>
</Page>
</mvc:View>
<mvc:View
xmlns:mvc="sap.ui.core.mvc"
xmlns="sap.m"
controllerName="anotherComponent.controller.Master"
>
<Page title="Component-B" backgroundDesign="List">
<List id="masterList"
updateFinished="onListUpdateFinished"
headerText="Products {= ${count>/master} ? '('+${count>/master}+')' : ''}"
items="{
path: 'odataModel>/Products',
parameters: {
expand: 'Category, Supplier',
select: 'ProductID, ProductName, UnitsInStock, UnitPrice, Category/CategoryName, Supplier/Country'
},
sorter: [
{
path: 'Category/CategoryName',
group: true
}
],
filters: [
{
path: 'Supplier/Country',
operator: 'EQ',
value1: 'UK'
}
],
events: {
dataReceived: '.onDataReceived'
}
}"
itemPress=".onItemPress"
mode="SingleSelectMaster"
>
<ObjectListItem
type="Active"
title="{odataModel>ProductName}"
number="x {odataModel>UnitsInStock}"
/>
</List>
</Page>
</mvc:View>
<mvc:View
xmlns:mvc="sap.ui.core.mvc"
xmlns="sap.m"
controllerName="anotherComponent.controller.SplitContainer"
displayBlock="true"
height="100%"
>
<SplitContainer
id="rootSplitContainer"
mode="{= ${device>/system/desktop} ? 'ShowHideMode' : 'HideMode'}"
/> <!-- SplitContainer instead of SplitApp as there is already App in root component -->
</mvc:View>