I currently try to learn UI5 and right now the concept of routing. My current use case is, that the user selects one radio button out of a group and then presses a button. On my second view it should show the selected radio button.
I've set up both views, the routes and the targets. But it somehow does not want to load the View. If I have a look at the URL it enters the pattern of the route into it but it does not load the view - is there anything I need to do?
The rounter is initialized in the component.js
After I clicked the button the following method gets called:
this.getOwnerComponent().getRouter().navTo("overview");
this is my routing config:
"flexEnabled": false,
"rootView": {
"viewName": "com.enh.ess.com.enh.ess.view.Booking",
"type": "XML",
"async": true,
"id": "Booking"
},
// some stuff in between
"routing": {
"config": {
"routerClass": "sap.m.routing.Router",
"viewType": "XML",
"async": true,
"viewPath": "com.ess.view",
"controlAggregation": "pages",
"controlId": "app",
"clearControlAggregation": false,
"bypassed": {
"target": "noFound"
}
},
"routes": [
{
"name": "home",
"pattern": "",
"target": "booking_tar"
},
{
"name": "overview",
"pattern": "overviewBooking",
"target": "Overview"
}
],
"targets": {
"booking_tar": {
"viewType": "XML",
"transition": "slide",
"viewId": "Booking",
"viewName": "Booking"
},
"Overview": {
"viewType": "XML",
"viewName": "Overview"
},
"notFound": {
"viewId": "notFound",
"viewType": "XML",
"viewName": "NotFound",
"transition": "show"
}
}
}
my rootView ( Booking.view.xml ) is built like this ( I've removed some stuff here, like the attributes for the buttons or the path of the contrllerName - and I added one "comment" for the button ):
<mvc:View controllerName="" xmlns:mvc="sap.ui.core.mvc" displayBlock="true" xmlns="sap.m" xmlns:layout="sap.ui.layout">
<Shell id="shell">
<App id="app">
<pages>
<Page id="page" title="{i18n>title}">
<content>
<layout:VerticalLayout>
<RadioButtonGroup id="" columns="1"/>
<layout:HorizontalLayout>
<Button /> <-- when this button gets clicked it should load the new view
<Button />
</layout:HorizontalLayout>
</layout:VerticalLayout>
</content>
</Page>
</pages>
</App>
</Shell>
</mvc:View>
in my view Booking.view.xml I have the button. After I click it, it should navigate to the overview target / the Overview.viewl.xml - and as I said, it writes the value into the URL, but it doesn't load the view.
Do you have any idea what I also need to do? I've tried some things ( like view levels, that didn't work )
I am currently working in the WebIDE - if this is relevant for this.
thank you!
I suggest you to use a different strategy for the XML "encapsulation" to better exploit the routing mechanism: create an (almost) empty root view, such as App.view.xml, as follows:
<mvc:View xmlns:mvc="sap.ui.core.mvc" xmlns="sap.m" displayBlock="true">
<App id="idAppControl">
<pages>
<!-- Routed views are added here -->
</pages>
</App>
</mvc:View>
Modify your manifest accordingly
In /sap.ui5/rootView:
{
"viewName": "your.namespace.view.App",
"type": "XML",
"async": true
},
and in /sap.ui5/routing/config:
{
"routerClass": "sap.m.routing.Router",
"viewType": "XML",
"async": true,
"viewPath": "your.namespace.view",
"controlAggregation": "pages",
"controlId": "idAppControl"
},
Please note that the controlId and the ID of the <App> must be the same.
Now you've prepared the "container" for your routes and your Views can be simplified as follows:
<mvc:View controllerName="your.namespace.controller.Booking"
xmlns="sap.m"
xmlns:mvc="sap.ui.core.mvc">
<Page title="title" class="sapUiResponsiveContentPadding">
<content>
<!-- Your content here -->
</content>
</Page>
</mvc:View>
Same structure also for your detail page. Please remember that your Home page should have an empty routing pattern ("pattern" : "") in order to be the first hit route.
To learn more, take a look at the tutorial Navigation and Routing.
Related
I need to navigate from View1 to view2 via routing. On the click of the event, it's throwing an error.
Error: Control with ID app could not be found - Target: View2
I made an empty app.view file and add its ID as "app", but still throwing an error.
manifest.json
"routing": {
"config": {
"routerClass": "sap.m.routing.Router",
"viewType": "XML",
"async": true,
"viewPath": "emergencyreport1.view",
"controlAggregation": "pages",
"controlId": "app"
},
"routes": [
{
"name": "View1",
"pattern": "",
"target": ["View1"]
},
{
"name": "View2",
"pattern": "View2",
"target": ["View2"]
}
],
"targets": {
"View1": {
"viewType": "XML",
"transition": "slide",
"viewId": "View1",
"viewName": "View1",
"viewLevel" : 1
},
"View2": {
"viewType": "XML",
"transition": "slide",
"viewId": "View2",
"viewName": "View2",
"viewLevel" : 2
}
}
app.view.xml
<mvc:View
controllerName="emergencyreport1.controller.app"
xmlns:mvc="sap.ui.core.mvc"
displayBlock="true"
xmlns="sap.m">
<App id="app" >
</App>
</mvc:View>
View1.xml
<mvc:View
controllerName="emergencyreport1.controller.View1"
xmlns:mvc="sap.ui.core.mvc"
displayBlock="true"
xmlns="sap.m">
<App>
<core:Icon src="sap-icon://display-more" press="ondisplay" />
</App>
</mvc:View>
View1.controller
ondisplay: function ()
{
this.getOwnerComponent().getRouter().navTo("View2");
}
you usually need to define your rootview in the manifest:
...
"sap.ui5": {
"rootView": {
"viewName": "emergencyreport1.view.app",
"type": "XML",
"async": true,
"id": "app"
},
I'm trying to run a SAPUI5 application. I created a view with a view piecharts and add them in index.html to the body by referring to its ID content
<script>
var app = new sap.m.App();
var page = sap.ui.view({
viewName: "...",
type: sap.ui.core.mvc.ViewType.XML
});
app.addPage(page);
app.placeAt("content");
</script>
My problem now is that the Component.js isn't called. So I have no chance of using Routing since the Router isn't initialized.
I tried some different ways, like this:
<script>
sap.ui.getCore().attachInit(function() {
new sap.m.Shell({
app: new sap.ui.core.ComponentContainer({
height: "100%",
name: "vizFrame.gettingStarted.demoVizFrame"
})
}).placeAt("content");
});
</script>
After this approach, the Component.js got triggered, but the page is empty. The content of my root view isn't displayed.
manifest.json
{
"_version": "1.12.0",
"sap.app": {
"id": "vizFrame.gettingStarted.demoVizFrame",
"type": "application",
"i18n": "i18n/i18n.properties",
"applicationVersion": {
"version": "1.0.0"
},
"title": "{{appTitle}}",
"description": "{{appDescription}}",
"sourceTemplate": {
"id": "ui5template.basicSAPUI5ApplicationProject",
"version": "1.40.12"
}
},
"sap.ui": {
"technology": "UI5",
"icons": {
"icon": "",
"favIcon": "",
"phone": "",
"phone#2": "",
"tablet": "",
"tablet#2": ""
},
"deviceTypes": {
"desktop": true,
"tablet": true,
"phone": true
}
},
"sap.ui5": {
"flexEnabled": false,
"rootView": {
"viewName": "vizFrame.gettingStarted.demoVizFrame.view.VizChart",
"type": "XML"
},
"dependencies": {
"minUI5Version": "1.60.1",
"libs": {
"sap.ui.layout": {},
"sap.ui.core": {},
"sap.m": {}
}
},
"contentDensities": {
"compact": true,
"cozy": true
},
"models": {
"i18n": {
"type": "sap.ui.model.resource.ResourceModel",
"settings": {
"bundleName": "vizFrame.gettingStarted.demoVizFrame.i18n.i18n"
}
}
},
"resources": {
"css": [
{
"uri": "css/style.css"
}
]
},
"routing": {
"config": {
"routerClass": "sap.m.routing.Router",
"viewType": "XML",
"async": true,
"viewPath": "vizFrame.gettingStarted.demoVizFrame.view",
"controlAggregation": "pages",
"controlId": "app",
"clearControlAggregation": false
},
"routes": [
{
"name": "RouteVizChart",
"pattern": "RouteVizChart",
"target": ["TargetVizChart"]
},
{
"pattern": "detail",
"name": "detail",
"target": "detail"
}
],
"targets": {
"TargetVizChart": {
"viewType": "XML",
"transition": "slide",
"clearControlAggregation": false,
"viewId": "VizChart",
"viewName": "VizChart"
},
"testView": {
"viewType": "XML",
"viewName": "testView",
"viewId": "testView",
"viewLevel": 2
},
"detail": {
"viewType": "XML",
"viewName": "detailView"
}
}
}
}
}
Component.js
sap.ui.define([
"sap/ui/core/UIComponent",
"sap/ui/Device",
"vizFrame/gettingStarted/demoVizFrame/model/models"
], function (UIComponent, Device, models) {
"use strict";
return UIComponent.extend("vizFrame.gettingStarted.demoVizFrame.Component", {
metadata: {
manifest: "json"
},
init: function () {
UIComponent.prototype.init.apply(this, arguments);
this.getRouter().initialize();
this.setModel(models.createDeviceModel(), "device");
}
});
});
VizChart.view.xml
This is the root view where only the page title gets displayed:
<mvc:View controllerName="vizFrame.gettingStarted.demoVizFrame.controller.VizChart"
xmlns:mvc="sap.ui.core.mvc"
xmlns="sap.m"
xmlns:viz="sap.viz.ui5.controls"
xmlns:chart="sap.suite.ui.commons"
xmlns:l="sap.ui.layout"
>
<Page title="Übersicht">
<l:VerticalLayout
width="100%"
class="gridWrapper">
<l:Grid containerQuery="true">
<viz:VizFrame xmlns="sap.viz" id="l100" width="100%" selectData="onDataClick" />
<viz:VizFrame xmlns="sap.viz" id="l300" width="100%" selectData="onDataClick" />
<viz:VizFrame xmlns="sap.viz" id="l400" width="100%" selectData="onDataClick" />
<viz:VizFrame xmlns="sap.viz" id="l430" width="100%" selectData="onDataClick" />
<viz:VizFrame xmlns="sap.viz" id="l499" width="100%" selectData="onDataClick" />
</l:Grid>
</l:VerticalLayout>
</Page>
</mvc:View>
The topic App Initialization: What Happens When an App Is Started? explains which files are loaded in which order generally. In most cases, a Component is loaded with its descriptor (manifest.json) once the ComponentContainer is instantiated.
About the issue with the page being empty, see my other answer in stackoverflow.com/a/50951902.
In your case, the root view is missing a root control (e.g. sap.m.App). So it should be:
<!-- Root view -->
<mvc:View xmlns:mvc="sap.ui.core.mvc">
<App id="app" xmlns="sap.m">
<!-- Leave this block empty if Router should be used. Otherwise, continue.. -->
<Page title="Übersicht">
<!-- content -->
</Page>
</App>
</mvc:View>
In your 1st snippet, you could see the page content because there was already sap.m.App.
ComponentContainer loads component.js file from index.html
component.js loads component descriptor(manifest.json - application descriptor file to declare dependencies) which is referenced in the file.
component.js create root view, default and resource(i18n) model.
index.html
sap.ui.getCore().attachInit(function () {
new sap.ui.core.ComponentContainer({
name: "ABC.AppName"
}).placeAt("content");
});
component.js
sap.ui.core.UIComponent.extend("ABC.AppName.Component", {
metadata : {
includes: [jQuery.device.is.phone ? "assets/css/mStyle.css" : "assets/css/dStyle.css"]
},
createContent: function () {
// create root view
var oView = sap.ui.view({
id: "app",
viewName: "ABC.AppName.ViewFolder.App",
type: "JS",
viewData: { component: this },
});
i18nGlobal = new sap.ui.model.resource.ResourceModel({
bundleUrl: "i18n/i18n.properties",
bundleLocale: "de"
});
oView.setModel(i18nGlobal, "i18n");
sap.ui.getCore().setModel(i18nGlobal, "i18n");
return oView;
}
});
I am trying to show the data of a particular item in a list when ,clicked upon , on the next page (view)
Here Overview.view.xml is the default view with a clickable list connected to an oData model.
Next is the controller for Overview navigating to the next page i.e. Overview.controller.js.
The next page is Detail.view.xml
I want to show details of clicked item in this page.
#Overview.view.xml
<mvc:View controllerName="root.demo.controller.Overview" xmlns:html="http://www.w3.org/1999/xhtml" xmlns:mvc="sap.ui.core.mvc"
displayBlock="true" xmlns="sap.m">
<App >
<pages>
<Page title="{i18n>title}">
<content>
<List headerText="list" class="sapUiResponsiveMargin" width="auto" items="{HANA>/person}">
<items>
<ObjectListItem title="{HANA>ID} x {HANA>FIRSTNAME}" type="Navigation" press="onPress"/>
</items>
</List>
</content>
</Page>
</pages>
</App>
</mvc:View>
#Overview.controller.js
sap.ui.define([
"sap/ui/core/mvc/Controller"
], function (Controller) {
"use strict";
return Controller.extend("root.demo.controller.App", {
onPress: function (oEvent) {
var oRouter = sap.ui.core.UIComponent.getRouterFor(this);
oRouter.navTo("detail");
}
});
});
#Detail.view.xml
<mvc:View xmlns="sap.m"
xmlns:mvc="sap.ui.core.mvc">
<Page title="{i18n>detailPageTitle}">
<ObjectStatus title="PAGE 1"
/>
</Page>
</mvc:View>
If you have different Entity Sets with association you need to send the key of the association to the second view and there create the binding towards the assocaited entity set
If not you need to send the object to the second view
Either way you need to navigate with parameters
In the manifest file you need to specify the routing
"routes": [
{
"name": "TargetMaster",
"pattern": "RouteMaster",
"target": [
"TargetMaster"
]
},
{
"pattern": "Detail/{storePath}",
"name": "Detail",
"target": "Detail"
}
],
"targets": {
"TargetMaster": {
"viewType": "XML",
"transition": "slide",
"clearControlAggregation": false,
"viewName": "Master"
},
"Detail": {
"viewType": "XML",
"viewName": "Detail"
}
}
In the Overview Controller you need to create the navigation similarly to
onListItemPress: function(oEvent){
var oItem = oEvent.getSource();
var oRouter = sap.ui.core.UIComponent.getRouterFor(this);
oRouter.navTo("Detail",{
storePath: oItem.getBindingContext().getProperty("Store")
});
}
you can find more information on the official documentation here
I have tried using below code but it is giving the list of all the supplier
<ObjectPageSection title="Suppliers">
<subSections>
<ObjectPageSubSection>
<blocks>
<m:Table id="suppliersTable" items="{path : 'products>/Products' , parameters:{expand : 'Supplier'} }">
<m:columns>
<m:Column/>
</m:columns>
<m:items>
<m:ColumnListItem >
<m:cells>
<m:ObjectIdentifier text="{products>Supplier/Name}"/>
</m:cells>
</m:ColumnListItem>
</m:items>
</m:Table>
</blocks>
</ObjectPageSubSection>
</subSections>
</ObjectPageSection>
I used Northwind OData service -
I want only those supplier related to the product
like below:
Supplier1 and Supplier2
Can anyone please help me.
Start by binding the element to the view on your controller (place this on your handleRouteMatched method):
var self = this;
var argsId = oEvent.getParameters().data.Id;
var view = self.getView();
var yourTable = view.byId("suppliersTable");
yourTable.bindElement({
path: "products>/Products('" + argsId + "')",
parameters: { expand: "Supplier" },
events: {
dataRequested: function () {
self.getView().setBusy(true);
//some error handling logic you might want
},
dataReceived: function () {
self.getView().setBusy(false);
}
}
});
This will make all your bindings on the table relative to the Product that triggered the navigation. Your view code will then look like this:
<ObjectPageSection title="Suppliers">
<subSections>
<ObjectPageSubSection>
<blocks>
<m:Table id="suppliersTable">
<m:columns>
<m:Column/>
</m:columns>
<m:items>
<m:ColumnListItem >
<m:cells>
<m:ObjectIdentifier text="{products>Supplier/Name}"/>
</m:cells>
</m:ColumnListItem>
</m:items>
</m:Table>
</blocks>
</ObjectPageSubSection>
</subSections>
</ObjectPageSection>
I have set navigation in manifest.json
"routing": {
"config": {
"routerClass": "sap.m.routing.Router",
"viewType": "XML",
"viewPath": "Product.view",
"controlId": "app",
"controlAggregation": "pages"
},
"routes": [{
"pattern": "",
"name": "productList",
"target": "productList"
}, {
"pattern": "detail/{productsData}/Supplier",
"name": "detail",
"target": "detail"
}],
"targets": {
"productList": {
"viewName": "ProductList"
},
"detail": {
"viewName": "Detail"
}
}
}
I am navigating from ProductList page to Details page
ProductList Page
I'm currently working on a web app based on SAPUI5. At the moment, it's based on HTML pages but we have to migrate to a dynamic structure. The solution will be the router. I've followed tons of tutorials, tried different structures (JS / XML view) but the router always throws an error saying:
The target intro has a control id or a parent but no 'controlAggregation' was set, so the target could not be displayed. - EventProvider sap.m.routing.Target
This is my current router setup:
"routing": {
"config": {
"routerClass": "sap.m.routing.Router",
"viewType": "XML",
"viewPath": "xx.xxxxxxx.view",
"controlId": "appContainer"
},
"routes": [
{
"pattern": "",
"name": "intro",
"target": "intro"
}
],
"targets": {
"intro": {
"viewName": "intro"
}
}
}
The "controlId" points to the <App> control in my "rootView".
I tried with very simple view (like Text only), but the problem persists.
<mvc:View
controllerName="xx.xxxxxxx.controller.app"
xmlns="sap.m"
xmlns:mvc="sap.ui.core.mvc"
displayBlock="true"
>
<App id="appContainer"/>
</mvc:View>
As the error message indicates, the router doesn't know into which aggregation the "intro"-view should be added. Since the control App has an aggregation named "pages" (inherited from NavContainer), include "controlAggregation": "pages" to the attribute "routing"/"config".