I am new to SAPUI5 and I would like to navigate to the details of an object on a second view, but I have an error:
TypeError: oRouter.getRoute (...) is undefined
Can someone help me?
Airport.controller.js
onInit: function() {
jQuery.sap.require("sap.m.ObjectAttribute");
jQuery.sap.require("sap.m.MessageBox");
var oList = this.getView().byId("List01");
oList.bindItems({
path: "JSON>/products",
template: new sap.m.StandardListItem({
type: "Navigation",
title: "{JSON>fields/aeroport}",
press: [this.onPress, this],
}),
});
},
onPress: function(oEvt) {
var oItem = oEvt.getSource();
var oRouter = sap.ui.core.UIComponent.getRouterFor(this);
var temp = oItem
.getBindingContext("JSON")
.getPath()
.substr(10);
oRouter.navTo("Detail", {
airportPath: temp,
});
},
Detail.controller.js
onInit: function() {
var oRouter = sap.ui.core.UIComponent.getRouterFor(this);
oRouter.getRoute("detail").attachPatternMatched(this._onObjectMatched, this);
},
_onObjectMatched: function(oEvt) {
this.getView().bindElement({
path: "/products/" + oEvt.getParameter("arguments").airportPath,
model: "JSON",
});
},
Detail.view.xml
<mvc:View
xmlns:mvc="sap.ui.core.mvc"
xmlns="sap.m"
controllerName="SAPUI5CoolProject.controller.Detail"
>
<App id="Detail">
<Page
title="Airport Detail"
showNavButton="true"
navButtonPress="goBackOtherAirport"
>
<ObjectHeader title="{JSON>products/fields}"/>
</Page>
</App>
</mvc:View>
manifest.json
{
"pattern": "Detail/{airportPath}",
"name": "Detail",
"target": ["Detail"]
}
oRouter.getRoute("detail") → oRouter.getRoute("Detail")
Since the API getRoute awaits the name of the route defined in the app descriptor, and because JS is case-sensitive, the exact same string literal has to be passed as the argument.
Related
I am trying to display a VizFrame and my data are in a simple JSON format.
Both my view and controller are in JS. (I will start writing my view in XML going forward) because I see that is the way to go.
I get a blank page with the error: "setDataset of undefined". What am I missing?
My view code is this.
createContent: function(oController) {
var oSubHeader = new sap.m.Bar({
contentLeft: [
new sap.m.Button({
icon: "sap-icon://nav-back",
press: [oController.onNavBack, oController]
})
],
contentMiddle: [
new sap.m.Label({
text: "{i18n>app_subhead_2}"
})
]
});
var oVizFrame = new sap.viz.ui5.controls.VizFrame("VizFrameId", {
width: "100%",
height: "400px",
vizType: "line"
});
var oPage = new sap.m.Page({
title: "UI5 Assignment App",
showSubHeader: true,
subHeader: oSubHeader,
content: [oVizFrame]
});
return oPage;
}
My corresponding controller is
sap.ui.define([
"sap/ui/core/mvc/Controller",
"sap/ui/core/UIComponent",
"sap/ui/core/routing/History",
"sap/viz/ui5/controls/VizFrame",
"sap/viz/ui5/data/FlattenedDataset"
], function (Controller, UIComponent, History, VizFrame, FlattenedDataset) {
"use strict";
return Controller.extend("Project_Tile_learning.Divya_tile_Project.controller.ProductDetailPage", {
onNavBack: function () {
var oHistory = History.getInstance();
var sPreviousHash = oHistory.getPreviousHash();
if (sPreviousHash !== undefined) {
window.history.go(-1);
} else {
var oRouter = sap.ui.core.UIComponent.getRouterFor(this);
oRouter.navTo("homepage", true);
}
},
onInit: function () {
var sampleDatajson = new sap.ui.model.json.JSONModel("json/PA.json");
var oVizFrame = this.getView().byId("VizFrameId");
var oDataset = new sap.viz.ui5.data.FlattenedDataset({
dimensions: [{
name: "Year",
value: "{Year}"
}],
measures: [{
name: "Supplier",
value: "{Supplier}"
}, {
name: "Liquor",
value: "{Liquor}"
}, {
name: "Quantity",
value: "{Quantity}"
}],
data: {
path: "/items"
}
});
oVizFrame.setDataset(oDataset);
oVizFrame.setModel(sampleDatajson);
var oFeedValueAxis = new sap.viz.ui5.controls.common.feeds.FeedItem({
"uid": "valueAxis",
"type": "Measure",
"values": ["Supplier"]
});
var oFeedValueAxis1 = new sap.viz.ui5.controls.common.feeds.FeedItem({
"uid": "valueAxis",
"type": "Measure",
"values": ["Liquor"]
});
var oFeedValueAxis2 = new sap.viz.ui5.controls.common.feeds.FeedItem({
"uid": "valueAxis",
"type": "Measure",
"values": ["Quantity"]
});
var oFeedCategoryAxis = new sap.viz.ui5.controls.common.feeds.FeedItem({
"uid": "categoryAxis",
"type": "Dimension",
"values": ["Year"]
});
oVizFrame.addFeed(oFeedValueAxis);
oVizFrame.addFeed(oFeedValueAxis1);
oVizFrame.addFeed(oFeedValueAxis2);
oVizFrame.addFeed(oFeedCategoryAxis);
}
});
});
Update: JS View is deprecated since UI5 v1.90. Use Typed View instead.
When creating a control in JS view definition, always use this.createId("myControl").
From the doc:
If you want to define IDs for controls inside a JSView to guarantee their uniqueness [...], you cannot give hardcoded IDs, but have to give the view the opportunity to add its own instance ID as a prefix. This is done by using the View.createId(...) method.
For the example above, this is done as follows:
new sap.viz.ui5.controls.VizFrame(this.createId("VizFrameId"), { /*...*/ });
Then in the controller, myView.byId tries to access the control with view's own ID as a prefix, which will succeed this time since the control has an ID with the view ID as a prefix.
We have upgraded the sapui5 application from 1.44 to 1.56 version. My application was working properly in 1.44 version.
After upgrade it gives me below error.
"Uncaught (in promise) Error: The specified component controller 'com.test.ui.Component' could not be found!"
Note: Component.js is loaded successfully i.e no 404 error for Component.js
<script id="sap-ui-bootstrap"
src="../../../resources/sap-ui-core.js"
data-sap-ui-libs="sap.m, sap.me"
data-sap-ui-theme="sap_bluecrystal"
data-sap-ui-xx-bindingSyntax="complex"
data-sap-ui-compatVersion="1.16"
data-sap-ui-appCacheBuster="./"
data-sap-ui-resourceroots='{"com.test.ui": "./"}'></script>
<link rel="stylesheet" type="text/css" href="CSS/style.css" />
<script>
sap.ui.getCore().attachInitEvent(function() {
var oShell = new sap.m.Shell("idshell");
var oComponentContainer = new sap.ui.core.ComponentContainer({
height : "100%",
name : "com.test.ui"
});
oShell.setApp(oComponentContainer);
oShell.placeAt("content");
});
</script>
Component.js
jQuery.sap.declare("com.test.ui.Component");
jQuery.sap.require("sap.m.routing.RouteMatchedHandler");
sap.ui.define(["sap/ui/core/UIComponent"],function(UIComponent){
"use strict";
UIComponent.extend(
"com.test.ui.Component", {
metadata: {
"name": "com.test.ui",
"version": "1.0",
"includes": ["css/style.css"],
"dependencies": {
"libs": ["sap.m", "sap.ui.core", "sap.me",
"sap.ushell"
],
"components": []
},
"config": {
"resourceBundle": "i18n/messageBundle.properties",
"titleResource": "title",
"serviceConfig": {
"url": "/sap/opu/odata/.."
}
},
"routing": {
"config": {
"viewType": "XML",
"viewPath": "com.test.ui.view",
"clearTarget": false
},
"routes": [{
name: "route1",
view: "Desktop",
pattern: ":all*:",
targetControl: "rootapp",
targetAggregation: "pages"
}]
}
},
/**
* First method of the component to be called. It initializes the odata and the i18n models, calls the super constructor
* and initializes the router.
* #memberOf com.test.ui.Component
*/
init: function() {
// Fetch the rootpath of the component
var rootPath = jQuery.sap.getModulePath("com.test.ui");
//Create the i18n model with the properties file and set for the component with the name 'i18n'
var i18nModel = new sap.ui.model.resource.ResourceModel({
bundleUrl: rootPath + "/i18n/messageBundle.properties"
});
this.setModel(i18nModel, "i18n");
//Fetch the odata service url and create an odata model and set it for the component with the name 'odata'
var sServiceUrl = this.getMetadata().getConfig().serviceConfig.url;
var oModel = new sap.ui.model.odata.ODataModel(
sServiceUrl);
this.setModel(oModel, "odata");
var sServiceUrl1 = "/sap/opu/odata/...";
var oModel = new sap.ui.model.odata.ODataModel(
sServiceUrl1);
this.setModel(oModel, "odata1");
//call the super-constructor
sap.ui.core.UIComponent.prototype.init.apply(this,
arguments);
// Initialize route matched handler and router
this.oRouteMatchedHandler = new sap.m.routing.RouteMatchedHandler(
this.getRouter());
this.getRouter().initialize();
},
createContent: function() {
return sap.ui.view({
viewName: "com.test.ui.view.View1",
type: "XML",
viewData: {
component: this
}
});
}
});
});
Any help will be appreciated.
Project Structure
When running my project, I am getting:
Error: failed to load 'stock/controller/plant.controller.js' from ./controller/plant.controller.js: TypeError: Controller.extend is not a function
Please, let me know how to fix it.
plant.controller.js
sap.ui.define([
"sap/ui/core/mvc/Controller",
"jquery.sap.global",
"stock/Formatter",
"sap/ui/core/routing/History",
"sap/ui/model/json/JSONModel"
], function (jQuery, Formatter, Controller, History, JSONModel) {
"use strict";
var TableController = Controller.extend("stock.controller.plant", {
onInit: function () {
var oModel = new JSONModel(jQuery.sap.getModulePath("sap.ui.demo.mock", "/products.json"));
this.getView().setModel(oModel);
},
getRouter : function () {
return sap.ui.core.UIComponent.getRouterFor(this);
},
onNavBack: function (oEvent) {
var oHistory = History.getInstance();
var sPreviousHash = oHistory.getPreviousHash();
if (sPreviousHash !== undefined) {
window.history.go(-1);
} else {
this.getRouter().navTo("input", {}, true /*no history*/);
}
}
});
return TableController;
});
Component.js
sap.ui.define([
"sap/ui/core/UIComponent",
"sap/ui/core/mvc/XMLView",
"sap/ui/model/json/JSONModel"
], function(UIComponent, JSONModel, XMLView) {
"use strict";
var Component = UIComponent.extend("stock.Component", {
metadata: {
manifest: "json",
getTable: function () {
return this._rootView.getContent()[0];
}
},
publicMethods: [
"getTable"
],
dependencies: {
libs: [
"sap.m",
"sap.ui.layout"
]
},
rootView: "stock.view.input",
config: {
sample: {
files: [
"view.input.view.xml",
"controller.main.controller.js",
"Formatter.js"
],
description : "In this example assisted input is provided with table-like suggestions where several columns can display more details."
}
},
init : function () {
UIComponent.prototype.init.apply(this, arguments);
this.getRouter().initialize();
}
});
Component.prototype.createContent = function () {
this._rootView = sap.ui.xmlview({ viewName : "stock.view.plant" });
return this._rootView;
};
return Component;
});
You overlooked the sequence of the files declaration. In your example you use a "stock/Formatter" file as a "Controller", which is obviously wrong. Below is a correct sequence:
sap.ui.define([
'sap/ui/core/mvc/Controller',
'jquery.sap.global',
'stock/Formatter',
'sap/ui/core/routing/History',
'sap/ui/model/json/JSONModel'
], function (Controller, jQuery, Formatter, History,JSONModel) {
});
View1.Controller.js
onClickRUSSIA: function() {
var dialog = new Dialog({
title: 'Default Message',`enter code here`
type: 'Message',
content: new Text({
text: 'Country : RUSSIA \n Contenent : ASIA \n language:RUSSIAN.'
}),
beginButton: new Button({
text: 'OK',
press: function() {
dialog.close();
}
}),
endButton: new Button({
text: 'More Info',
press: function() {
//this.getRouter().navTo("mohan");
var router = sap.ui.core.UIComponent.getRouterFor();
router.navTo("View2");
}
}),
afterClose: function() {
dialog.destroy();
}
});
dialog.open();
},
Component.js
sap.ui.define([
"sap/ui/core/UIComponent",
"sap/ui/Device",
"Test1/model/models"
], function(UIComponent, Device, models) {
"use strict";
return UIComponent.extend("Test1.Component", {
metadata: {
//rootView: "test1.webapp.view.App",
manifest: "json",
routing: {
config: {
viewType: "XML",
viewPath: "test1.webapp.view",
controlId: "rootControl",
controlAggregation: "pages",
//routerClass: "Test1.controller",
transition: "slide"
},
routes: [
{
pattern: "",
name: "default",
view: "view1"
}, {
pattern: "mohan",
name: "view2",
View: "view2"
}
]
// targets: {
// page1: {
// viewName: "View1",
// viewLevel: 0
// },
// page2: {
// viewName: "View2",
// viewLevel: 1
// }
// }
}
},
init: function() {
// call the base component's init function
UIComponent.prototype.init.apply(this, arguments);
jQuery.sap.require("sap.m.routing.RouteMatchedHandler");
jQuery.sap.require("sap.ui.core.routing.HashChanger");
sap.ui.core.UIComponent.prototype.init.apply(this, arguments);
this._router = this.getRouter();
// set the device model
this.setModel(models.createDeviceModel(), "device");
//initlialize the router
this._routeHandler = new sap.m.routing.RouteMatchedHandler(this._router);
this._router.initialize();
}
});
});
You will have to get the router for your controller/view. As this is not your controller inside endButton.press(), you have to use a helper variable that.
You have to give Router.navTo() the name of the route to navigate to. So it has to be view2 instead of View2.
var that = this;
var dialog = new Dialog({
...
endButton: new Button({
text: 'More Info',
press: function() {
var router = sap.ui.core.UIComponent.getRouterFor(that);
router.navTo("view2");
}
}),
...
this.getOwnerComponent().getTargets().display("page1");
I created javascript view
sap.ui.jsview("view.taskListView", {
/** Specifies the Controller belonging to this View.
* In the case that it is not implemented, or that "null" is returned, this View does not have a Controller.
* #memberOf view.taskListView
*/
getControllerName : function() {
return "view.taskListView";
},
/** Is initially called once after the Controller has been instantiated. It is the place where the UI is constructed.
* Since the Controller is given to this method, its event handlers can be attached right away.
* #memberOf view.taskListView
*/
createContent : function(oController) {
var oLabel = new sap.m.Label("l1",{ text :"Weekly Tasks", textAlign:"Center", width:"100%"});
// var oList = new sap.m.List({noDataText:"No data", items:"{/modelData}"});
var oList= new sap.m.List({ // define List Control
// mode: "MultiSelect", // multi selection mode
columns : [
new sap.m.Column({ // first column
}),
new sap.m.Column({ // second column
})
],
items : [
new sap.m.ColumnListItem({ // first row
type : "Navigation",
//selected : true, // first item is selected (from ListItemBase)
cells : [
new sap.ui.core.Icon({
src : "{/iconTaskSource}",
size : "1.5em"
}),
new sap.m.Text({ // second cell related to second column definition
text : "{/taskName}"
})
]
}),
new sap.m.ColumnListItem({ // second row
type : "Navigation",
cells : [
new sap.ui.core.Icon({
src : "{/iconTaskSource}",
size : "1.5em"
}),
new sap.m.Text({ // second cell related to second column definition
text : "{/taskName}"
})
]
})
]
});
return new sap.m.Page({
title: "Title",
content: [
oLabel , oList
/*
new sap.m.Button({
text:"Go to Page2",
tap: function(){
//app.to("abc.SecondPage");
alert("Hello");
}
})
*/
]
});
}
});
and controller
sap.ui.controller("view.weeklyTasks", {
onInit: function() {
var aData2 = { modelData : [
{iconTaskSource:"icon1", taskName: "task1"},
{iconTaskSource:"icon2", taskName: "task2"}
]};
var oModel = new sap.ui.model.json.JSONModel(aData2);
this.getView().setModel(oModel2);
}
});
The binding is not working
Did I miss something ?
Try running this code snippet.
sap.ui.jsview("view.taskListView", {
getControllerName: function() {
return "view.taskListView";
},
createContent: function(oController) {
var oLabel = new sap.m.Label("l1", {
text: "Weekly Tasks",
textAlign: "Center",
width: "100%"
});
var oList = new sap.m.List({ // define List Control
columns: [
new sap.m.Column({ // first column
})
]
});
var oTemplate = new sap.m.ColumnListItem({
type: "Navigation",
cells: [
new sap.m.Text({
text: "{taskName}"
})
]
});
oList.bindItems('/modelData', oTemplate);
return new sap.m.Page({
title: "Title",
content: [
oLabel, oList
]
});
}
});
sap.ui.controller("view.taskListView", {
onInit: function() {
var aData2 = {
modelData: [
{
iconTaskSource: "icon1",
taskName: "task1"
}, {
iconTaskSource: "icon2",
taskName: "task2"
}
]
};
var oModel = new sap.ui.model.json.JSONModel(aData2);
this.getView().setModel(oModel);
}
});
var oApp = new sap.m.App();
var myView = sap.ui.view({
type: sap.ui.core.mvc.ViewType.JS,
viewName: "view.taskListView"
});
oApp.addPage(myView);
oApp.placeAt('content');
<!DOCTYPE html>
<html>
<head>
<meta http-equiv='X-UA-Compatible' content='IE=edge' />
<title>test</title>
<script id='sap-ui-bootstrap' type='text/javascript' src='https://openui5.hana.ondemand.com/resources/sap-ui-core.js' data-sap-ui-theme='sap_bluecrystal' data-sap-ui-libs='sap.m'></script>
</head>
<body class='sapUiBody'>
<div id='content'></div>
</body>
</html>
Check this for the fixed version of your code http://jsbin.com/kequme/1/edit
You neeed to include data-sap-ui-xx-bindingSyntax="complex" in index.html file.
Look:
<script src="resources/sap-ui-core.js" id="sap-ui-bootstrap"
data-sap-ui-xx-bindingSyntax="complex" data-sap-ui-libs="sap.m"
data-sap-ui-theme="sap_bluecrystal">
</script>