OpenUI5: can't instanate a model - javascript

As it is said in the 20 lesson of the walkthroug, i'm trying to instanate a model with Invoices.json. But as a result i receive "No data" in a List. I've compared all my sources with the onces they have in a tutorial, and they are the same (excluding urls in the index.html)
As far as I understand, the version of the SDK I use is "1.48.10" (i check it in a sap-ui-version.json), so the instanation should work.
Here is my index.html:
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta charset="utf-8">
<title>Walkthrough</title>
<script src="http://localhost:63342/TestOprnUI5/resources/sap-ui-core.js"
id="sap-ui-bootstrap"
data-sap-ui-theme="sap_bluecrystal"
data-sap-ui-libs="sap.m"
data-sap-ui-compatVersion="edge"
data-sap-ui-preload="async"
data-sap-ui-resourceroots='{
"sap.ui.demo.wt": "./testoprnui5/"
}'>
</script>
<script>
sap.ui.getCore().attachInit(function () {
new sap.m.Shell({
app: new sap.ui.core.ComponentContainer({
name: "sap.ui.demo.wt"
})
}).placeAt("content");
});
</script>
</head>
<body class="sapUiBody" id="content">
</body>
</html>
Here is InvoiceList.view,xml:
<mvc:View
xmlns="sap.m"
xmlns:mvc="sap.ui.core.mvc">
<List
headerText="{i18n>invoiceListTitle}"
class="sapUiResponsiveMargin"
width="auto"
items="{invoice>/Invoices}" >
<items>
<ObjectListItem
title="{invoice>Quantity} x {invoice>ProductName}"/>
</items>
</List>
</mvc:View>
Here is App.view.xml:
<mvc:View
controllerName="sap.ui.demo.wt.controller.App"
xmlns="sap.m"
xmlns:mvc="sap.ui.core.mvc"
displayBlock="true">
<App class="myAppDemoWT">
<pages>
<Page title="{i18n>homePageTitle}">
<headerContent>
<Button
icon="sap-icon://hello-world"
press="onOpenDialog"/>
</headerContent>
<content>
<mvc:XMLView viewName="sap.ui.demo.wt.view.HelloPanel"/>
<mvc:XMLView viewName="sap.ui.demo.wt.view.InvoiceList"/>
</content>
</Page>
</pages>
</App>
</mvc:View>
Here is component.js:
sap.ui.define([
"sap/ui/core/UIComponent",
"sap/ui/model/json/JSONModel",
"sap/ui/demo/wt/controller/HelloDialog"
], function (UIComponent, JSONModel, HelloDialog) {
"use strict";
return UIComponent.extend("sap.ui.demo.wt.Component", {
metadata: {
manifest: "json"
},
init: function () {
// call the init function of the parent
UIComponent.prototype.init.apply(this, arguments);
// set data model
var oData = {
recipient: {
name: "World"
}
};
var oModel = new JSONModel(oData);
this.setModel(oModel);
// set dialog
this._helloDialog = new HelloDialog(this.getRootControl());
},
openHelloDialog: function () {
this._helloDialog.open();
}
});
});
Here is the project structure:
TestOpenUI5
- resources
- testopenui5
-- controller
--- App.controller.js
--- HelloDialog.js
--- HelloPanel.controller.js
-- css
--- styles.css
-- i18n
--- i18n.properties
-- view
--- App.view.xml
--- HelloDialog.fragment.xml
--- HelloPanel.view.xml
--- InvoiceList.view.xml
-- Component.js
-- Invoices.json
-- manifest.json
- index.html
- Invoices.json
PS: i've tried to put Invoices.json to the different folders, to the root and to the /testopenui5 folder with the same result.
PPS: it looks like Invoices are not included to the model, but how can i check it to be sure? And where can i find some logs?

You should set the model in manifest.json file.Inside models section of sap.ui5 section you should add three lines of code.
"invoice": {
"type": "sap.ui.model.json.JSONModel",
"uri": "Invoices.json"
}

Yeap, sorry, i've checked my manifest.json not carefully.
The problem was in i've placed invoice section not inside models, but near it.
That is what i had:
"models": {
"i18n": {
"type": "sap.ui.model.resource.ResourceModel",
"settings": {
"bundleName": "sap.ui.demo.wt.i18n.i18n"
}
}
},
"invoice": {
"type": "sap.ui.model.json.JSONModel",
"uri": "Invoices.json"
},
"resources": {
"css": [
{
"uri": "css/style.css"
}
]
}
That is what it should be:
"models": {
"i18n": {
"type": "sap.ui.model.resource.ResourceModel",
"settings": {
"bundleName": "sap.ui.demo.wt.i18n.i18n"
}
},
"invoice": {
"type": "sap.ui.model.json.JSONModel",
"uri": "Invoices.json"
}
},
"resources": {
"css": [
{
"uri": "css/style.css"
}
]
}

Related

After upgrading to Snowpack 3 cannot find files

I'm using Snowpack + Svelte. After upgrading to Snowpack 3 is not working anymore and I can't configure mount in snowpack.config.js properly.
Don't understand exactly why it cannot find App.js also it's trying to find .jsx, .ts...
[404] /_dist_/screens/App.js
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<link rel="stylesheet" href="global.css">
<script type="module" defer src="_dist_/main.js"></script>
</head>
<body>
</body>
</html>
And then in my snowpack.config.js
/** #type {import("snowpack").SnowpackUserConfig } */
module.exports = {
mount: {
public: '/',
src: '/_dist_',
},
plugins: [
'#snowpack/plugin-svelte',
'#snowpack/plugin-dotenv',
],
routes: [
/* Enable an SPA Fallback in development: */
// {"match": "routes", "src": ".*", "dest": "/index.html"},
],
optimize: {
/* Example: Bundle your final build: */
// "bundle": true,
},
packageOptions: {
/* ... */
},
devOptions: {
/* ... */
},
buildOptions: {
/* ... */
},
alias: {
components: './src/components',
screens: './src/screens',
lib: './src/lib'
},
};
I also tried:
mount: {
// Same behavior as the "src" example above:
"src": {url: "/dist"},
// Mount "public" to the root URL path ("/*") and serve files with zero transformations:
"public": {url: "/", static: true, resolve: false}
},
So now it's complaining less but still not working
[snowpack] [404] /_dist_/main.js
Files structure
root
--node-modules
--public
----global.css
----index.html
--src
----components
----lib
----screens
----main.js
--snowpack.config.js
...
package.json
"devDependencies": {
"#snowpack/plugin-dotenv": "^2.0.5",
"#snowpack/plugin-svelte": "^3.5.0",
"#snowpack/web-test-runner-plugin": "^0.2.1",
"#testing-library/svelte": "^3.0.3",
"#web/test-runner": "^0.12.2",
"chai": "^4.2.0",
"smart-webcomponents": "^9.0.0",
"snowpack": "^3.0.10",
"svelte": "^3.31.2",
"svelte-i18n": "^3.3.0"
}
Any help or idea will be really appreciated.
Just add .svelte when you import your components.
import App from 'screens/App.svelte'
Please, check this https://github.com/snowpackjs/snowpack/pull/2014#issuecomment-756624333 if you wanna dive deeper.

External component Knockout and Require

I'm just learning knockout and I need some help. My menucomponent won't show up (i.e. it should say "Boo ya ka sha"). In chrome (under the scripts inspector) I can see that htmlString is set properly (i.e. to the contents of components/menu.html). Help, please.
index.html
<html>
<head>
...
<script data-main="js/app" src="js/require.js"></script>
</head>
<body>
...
<menucomponent></menucomponent>
</body>
</html>
js/app.js
requirejs.config({
"baseUrl": "js",
"paths": {
"app": "app",
"jquery": "jquery-2.2.3",
"knockout":"knockout-3.4.0",
"main": "main",
"menu": "../components/menu",
"text": "require-text"
}
});
// make a component called menucomponent
require(['knockout'], function(ko) {
ko.components.register('menucomponent', {require: 'menu'});
});
// Load the main app module to start the app
requirejs(["main"]);
components/menu.js
define(['knockout','text!./menu.html'], function(ko, htmlString) {
function menuViewModel() {
this.myMessage = ko.observable("Boo ya ka sha");
}
return { viewModel: menuViewModel,
template: htmlString
};
});
components/menu.html
<div data-bind='text: myMessage'></div>
Knockout supports amd registration for viewmodel only, so try this:
In js/app.js, change your component registration to:
require(['knockout','text!./menu.html'], function(ko, htmlString) {
ko.components.register('menucomponent', {
viewModel: { require: 'menu'},
template: htmlString
});
and change components/menu.js to:
define(['knockout'], function(ko) {
function menuViewModel() {
this.myMessage = ko.observable("Boo ya ka sha");
}
return menuViewModel;
});

Configure route to display pages in a SplitApp SAPUI5

I have been trying to add pages to my SplitApp from other views (view.js) with their own drivers, but doing so causes the following error:
Sap-ui-core.js: 174 Uncaught Error: failed to load 'view / GestionDePlanta.view.js' from openui5-1.40.8 / resources / view / GestionDePlanta.view.js: 404 - Not Found (...)
I think it has to do with the paths to access that view the moment it boots
Sap.ui.view ({id: "GestionDePlanta", viewName: "view.GestionDePlanta", type: sap.ui.core.mvc.ViewType.JS});
Anyone know any way to do it?
I was following a tutorial, which I found easy to understand, but apparently this is incomplete :
http://blog.mypro.de/2014/02/14/add-page-to-ui5-boilerplate/
Thank you so much.
Index.html
<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta charset="UTF-8">
<title>DatosMaestros</title>
<script id="sap-ui-bootstrap"
src="/openui5-1.40.8/resources/sap-ui-core.js"
data-sap-ui-libs="sap.m,sap.ui.commons,sap.ui.table"
data-sap-ui-theme="sap_bluecrystal"
data-sap-ui-compatVersion="edge"
</script>
<link rel="stylesheet" type="text/css" href="css/style.css">
<script type="text/javascript" src="js/utilityFunction.js"></script>
<script type="text/javascript" src="js/xml2json.js"></script>
<script>
sap.ui.localResources("P_GestionDePlanta");
var url = "http://services.odata.org/V4/Northwind/Northwind.svc/Employees",
oModel = new sap.ui.model.json.JSONModel(url, true);
sap.ui.getCore().setModel(oModel);
var app = new sap.m.SplitApp("appId",{mode:sap.m.SplitAppMode.ShowHideMode});
var master = sap.ui.view({id:"GestionDePlanta", viewName:"view.GestionDePlanta", type:sap.ui.core.mvc.ViewType.JS});
app.addMasterPage(master);
var detail = sap.ui.view({id:"PlanAbastecimiento", viewName:"view.PlanAbastecimiento", type:sap.ui.core.mvc.ViewType.JS});
app.addDetailPage(detail);
app.placeAt("content");
</script>
</head>
<body class="sapUiBody" id="content">
</body>
</html>
Component.js
sap.ui.define([
"sap/ui/core/UIComponent",
"sap/ui/Device",
"P_GestionDePlanta/model/models"
], function(UIComponent, Device, models) {
"use strict";
return UIComponent.extend("P_GestionDePlanta.Component", {
metadata: {
manifest: "json"
},
/**
* The component is initialized by UI5 automatically during the startup of the app and calls the init method once.
* #public
* #override
*/
init: function() {
// call the base component's init function
UIComponent.prototype.init.apply(this, arguments);
// set the device model
this.setModel(models.createDeviceModel(), "device");
}
});
});
Manifiest.json
{
"_version": "1.1.0",
"sap.app": {
"_version": "1.1.0",
"id": "P_GestionDePlanta",
"type": "application",
"i18n": "i18n/i18n.properties",
"applicationVersion": {
"version": "1.0.0"
},
"title": "{{appTitle}}",
"description": "{{appDescription}}",
"sourceTemplate": {
"id": "ui5template.basicSAPUI5ApplicationProject",
"version": "1.32.0"
}
},
"sap.ui": {
"_version": "1.1.0",
"technology": "UI5",
"icons": {
"icon": "",
"favIcon": "",
"phone": "",
"phone#2": "",
"tablet": "",
"tablet#2": ""
},
"deviceTypes": {
"desktop": true,
"tablet": true,
"phone": true
},
"supportedThemes": [
"sap_hcb",
"sap_bluecrystal"
]
},
"sap.ui5": {
"_version": "1.1.0",
"rootView": {
"viewName": "P_GestionDePlanta.view.GestionDePlanta",
"type": "JS"
},
"dependencies": {
"minUI5Version": "1.30.0",
"libs": {
"sap.ui.core": {},
"sap.m": {},
"sap.ui.layout": {}
}
},
"contentDensities": {
"compact": true,
"cozy": true
},
"models": {
"i18n": {
"type": "sap.ui.model.resource.ResourceModel",
"settings": {
"bundleName": "P_ProcesamientoDeArchivos.i18n.i18n"
}
}
},
"resources": {
"css": [{
"uri": "css/style.css"
}]
}
}
}
Folders
Image:
Well that tutorial you followed is quite outdated. You would want to use a Component based structure (You have a component in your sample but never use it). The official SAPUI5/OpenUI5 Developer Guide especially the walkthroughs are mostly up to date. I recommend you to do the walkthrough there.
Back to your problem: UI5 has its own way to resolve modules (≈javascript files) from names.
In your example you give UI5 the name of a view: "view.GestionDePlanta". view is the namespace and GestionDePlanta is the module name. So UI5 looks for the namespace view and – lacking any matching namespace-path-mappings – it defaults to the UI5 framework itself using the same path as the sap-ui-core.js you defined in the bootstrap <script> element: ./openui5-1.40.8/resources/view.
To add such an namespace-path-mapping you can use the sap.ui.localResources() function.
With your sap.ui.localResources("P_GestionDePlanta"); declaration UI5 would look for a module "P_GestionDePlanta.view.GestionDePlanta" in the folder ./P_GestionDePlanta/view.
Thats better already but your folder structure should look like this then:
+ P_GestionDePlanta
+ view
GestionDePlanta.view.js
+ controller
GestionDePlanta.controller.js
index.html
An other way would be to use jQuery.sap.registerModulePath() to add an namespace-path-mapping. With jQuery.sap.registerModulePath("P_GestionDePlanta", "./"); UI5 would look for a module "P_GestionDePlanta.view.GestionDePlanta" in the folder ./view.
With that you can keep your folder structure:
+ view
GestionDePlanta.view.js
+ controller
GestionDePlanta.controller.js
index.html
But either way you have to supply the full namespace starting with P_GestionDePlanta everywhere like so:
sap.ui.view({id:"GestionDePlanta", viewName:"P_GestionDePlanta.view.GestionDePlanta", type:sap.ui.core.mvc.ViewType.JS});

open sapui5 detail page in a new tab of the browser on click of a button

<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<script src="resources/sap-ui-core.js"
id="sap-ui-bootstrap"
data-sap-ui-libs="sap.m,sap.ui.table,sap.ui.commons"
data-sap-ui-theme="sap_bluecrystal">
</script>
<!-- only load the mobile lib "sap.m" and the "sap_mvi" theme -->
<script>
var bFlag;
sap.ui.localResources("views");
sap.ui.localResources("i18n");
sap.ui.localResources("utils");
jQuery.sap.registerModulePath('Application', 'Application');
jQuery.sap.require("Application");
var oApp = new Application({
root : "content"
});
</script>
<link href="css/stylesheet.css" rel="stylesheet" type="text/css">
</head>
<body class="sapUiBody" role="application">
<div id="content"></div>
</body>
</html>
I am developing a sapui5 application in which I have a split app,now on the detail page in the toolbar I have a button called open in new window.So I want to open this particular detail page(only detail page) in a new tab on clicking this button.
Can anyone help me on this as in how to go about it?
Thanks in advance.
Regards,
Shalini
Use the SAP's Router API.
Basically, define your router, routes, pattern and targets objects in your manifest.json file:
"sap.ui5": {
"rootView": {
"viewName": "path.to.view.name",
"type": "XML",
"async": true
},
"routing": {
"config": {
"routerClass": "sap.m.routing.Router",
"viewType": "XML",
"viewPath": "path.to.view",
"controlId": "init",
"controlAggregation": "pages",
"async": true
},
"routes": {
"init": {
"pattern": "",
"target": "init",
"viewId": "vid_init"
},
"target_name": {
"pattern": "url_parameter",
"target": "target_name",
"viewId": "vid_view_name"
}
},
"targets": {
"target_name": {
"viewName": "view_name",
"transition": "show"
}
}
}
}
Assign a press event handler in your button's properties:
<Button id="myButton" press=".onOpenNewWindow" />
In your view's controller write a code to handle your event. Example:
onOpenNewWindow: funtion(oEvent){
sap.ui.require([
"sap/m/library"
], sapMLib => sapMLib.URLHelper.redirect("#/url_parameter", /*new window*/true));
},
Resources
API Reference: sap.m.URLHelper.redirect
Documentation: Routing and Navigation
Basically, you can open a new tab in JavaScript like this:
window.open("<yourURL>", _blank');
For your SAPUI5 Application you simply have to provide an additional .html file at a dedicated URL which loads your View/Controller. If you want to pass information from the Master/Detail application to the new tab you could add URL parameters.
As I can see in your edited question you´re using an Application. I don´t know the further structure (especially what your Application.js does) but in a separate .html a very simple solution could look like this:
<script>
sap.ui.localResources("views");
sap.ui.localResources("i18n");
sap.ui.localResources("utils");
sap.ui.jsview("name.of.your.detailView").placeAt("content");
</script>
If you want to reuse your Application.js file you can extend it and pass a simple parameter which tells to display only one View.
One more thing: I guess you´re using sap.m.SplitApp somewhere in your application. To display only the DetailView you should use sap.m.App instead at that point.

Code coverage with Dojo, Mocha and Blanket - always reporting 1 covered line

I have tried setting up Blanket.js to get reports on the code coverage of our Dojo app, which we are testing using Mocha. So far, Blanket seems to load, instrument the correct files, and it also seems to figure out which lines it should look for. However, every single file/module in the report shows up as having one line tested. It looks to me like it's the top "define" line. Here's a not minimal example, but it minimally represents our app setup and reproduces the problem.
File structure
▾ dojo-mocha-blanket/
▾ modules/
GUIWidget.html
GUIWidget.js
▾ test/
▾ lib/
blanket_mocha.js // from the blanket /dist
chai.js
mocha-blanket.js // adapter as per instructions
mocha.css
mocha.js
▾ spec/
GUIWidget.js
testrunner.html
index.html
Dojo setup
<html>
<head>
<title>Dojo-Mocha-Blanket</title>
</head>
<body>
<div id="GUIWidgetContainer"></div>
<script>
var dojoConfig = {
async: true,
baseUrl: "",
modulePaths: {
"modules": "modules"
}
};
</script>
<script src="//ajax.googleapis.com/ajax/libs/dojo/1.10.3/dojo/dojo.js"></script>
<script>
require([
"dojo/dom",
"modules/GUIWidget"
], function (dom, GUIWidget) {
var widget = new GUIWidget({}, "GUIWidgetContainer");
});
</script>
</body>
</html>
Module to test
define([
"dojo/_base/declare",
"dijit/form/Select",
"dijit/_TemplatedMixin",
"dijit/_WidgetsInTemplateMixin",
"dijit/_WidgetBase",
"dojo/text!modules/GUIWidget.html"
], function(
declare,
Select,
_TemplatedMixin,
_WidgetsInTemplateMixin,
_WidgetBase,
template
) {
return declare("GUIWidget", [_WidgetBase, _TemplatedMixin, _WidgetsInTemplateMixin], {
templateString: template,
addNumbers: function(lhs, rhs) {
return lhs + rhs;
},
postCreate: function() {
this.inherited(arguments);
this.header.innerHTML = this.addNumbers(40, 2);
}
});
});
Test setup
<html>
<head>
<title>Mocha spec runner</title>
<link rel="stylesheet" href="lib/mocha.css">
</head>
<body>
<div id="mocha"></div>
<script src="lib/mocha.js"></script>
<script
src="lib/blanket_mocha.js"
data-cover-adapter="lib/mocha-blanket.js"
data-cover-only="/modules"></script>
<script src="lib/chai.js"></script>
<script>
mocha.setup("bdd");
mocha.globals(["dojo", "dijit"]);
mocha.setup();
expect = chai.expect;
</script>
<script>
var dojoConfig = {
async: true,
packages : [{
name : "modules",
location : "/modules"
} ]
};
</script>
<script src="//ajax.googleapis.com/ajax/libs/dojo/1.10.3/dojo/dojo.js"></script>
<script>
require(
{
paths: {
"spec": "/test/spec"
}
},
["spec/GUIWidget"], function() {
mocha.run();
});
</script>
</body>
</html>
The test
define([
"modules/GUIWidget"
], function(
GUIWidget
) {
describe("GUIWidget", function() {
var widget;
beforeEach(function() {
widget = new GUIWidget();
widget.startup();
});
it("Should set header to 42", function() {
expect(widget.header.innerHTML).to.equal("42");
});
it("Should add numbers", function() {
expect(widget.addNumbers(1, 2)).to.equal(3);
})
afterEach(function() {
widget.destroyRecursive();
});
});
});
Results
(larger image here)
Apologies for the long code and all the bootstrapping stuff, but I've found the setup to be non-trivial :) If anyone has any ideas of why this might be happening, I'd be all ears. Thanks!

Categories