Referencing custom library in SAPUI5 causes 404 when loading the library - javascript

We wrote a custom library that we now want to reference in our main application.
Thus we added the following two entries to the consumer's neo-app.json:
{
"path": "/webapp/resources/some/lib",
"target": {
"type": "application",
"name": "somedemolib"
},
"description": "..."
}, {
"path": "/resources/some/lib",
"target": {
"type": "application",
"name": "somedemolib"
},
"description": "..."
}
and the following to the manifest.json of the libs consumer:
"dependencies": {
"minUI5Version": "1.30.0",
"libs": {
...
"some.lib": {
"minVersion": "1.0.0"
}
}
},
However upon loading the web-app I can see a HTTP404 when trying to load the library under the following path:
Uncaught Error: failed to load 'some/lib/library.js' from ../../resources/some/lib/library.js: 404 - Not Found

You have to declare your custom scripts in the first lines of your components.js
First of all you have to declare the path of your custom lib folder:
https://sapui5.netweaver.ondemand.com/sdk/docs/api/symbols/jQuery.sap.html#.registerModulePath
jQuery.sap.registerResourcePath("libs/custom", "/scripts/customlibs");
After that call you are able to load your script from that path with this call:
jQuery.sap.require("libs.custom.nameofyourscript");
"libs.custom" points to that folder you have registered previously and then your are able to import the script by its name. So your components.js looks like this:
jQuery.sap.registerResourcePath("libs/custom", "/scripts/customlibs");
jQuery.sap.require("libs.custom.nameofyourscript");
// Now the declaration of the components starts
sap.ui.core.UIComponent.extend("yourappname.Component", {
// ...

Related

Front end dependency manager for appending <script> tags in order

I want a dependency manager that will append script tags in order, and avoid duplicating tags with the same src. This has been an issue with the CMS we use.
I put together something like this:
const scriptLoader = new ScriptLoader({
"jquery#3.4.1": {
"attr": {
"src": "https://code.jquery.com/jquery-3.4.1.min.js",
"integrity": "sha256-CSXorXvZcTkaix6Yvo6HppcZGetbYMGWSFlBw8HfCJo=",
"crossOrigin": "anonymous",
},
},
"bootstrap#4.0.0": {
"attr": {
"src": "https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js",
"integrity": "sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl",
"crossOrigin": "anonymous",
},
"dependencies": ["jquery#3.4.1", "popper#1.12.9"],
},
});
// global js
scriptLoader.loadScript("global", {
"src": "js/global.js",
}, ["bootstrap#4.0.0", "jquery#3.4.1"]);
So when global script is loaded, it'll first load the ["bootstrap#4.0.0", "jquery#3.4.1"] dependencies by appending them as tags, before it loads/appends the global.js.
Any attempts to load global.js again will not re-append the script:
// global js - will append
scriptLoader.loadScript("global", {
"src": "js/global.js",
}, ["bootstrap#4.0.0", "jquery#3.4.1"]);
// global js - ignored, already appended/appending
scriptLoader.loadScript("global", {
"src": "js/global.js",
}, ["bootstrap#4.0.0", "jquery#3.4.1"]);
I'd looked into require.js but I'd need to re-write all my js files as require modules which I'm not that keen on.
Does anything of this sort exist already? Mine works ok-ish, but can be a little temperamental at times and would prefer something that's already out there.
As #morganney pointed out, Require.js is designed pretty much exactly for this purpose. Many popular libraries export their libraries in UMD format, which supports the AMD (Async Module Definition) logic Require.js expects.
This will simply import asynchronously all the first level libraries in your object, using just JavaScript import.
From the network debugger tab, we can observe the HTTP code 200 success:
const ScriptLoader = async (libs) => {
for (const [k] of Object.entries(libs)) {
console.log(k, libs[k].attr.src);
await import(libs[k].attr.src)
// Lib ready here
}
}
const scriptLoader = ScriptLoader({
"jquery#3.4.1": {
"attr": {
"src": "https://code.jquery.com/jquery-3.4.1.min.js",
"integrity": "sha256-CSXorXvZcTkaix6Yvo6HppcZGetbYMGWSFlBw8HfCJo=",
"crossOrigin": "anonymous",
},
},
"bootstrap#4.0.0": {
"attr": {
"src": "https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js",
"integrity": "sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl",
"crossOrigin": "anonymous",
},
"dependencies": ["jquery#3.4.1", "popper#1.12.9"],
},
});

Firefox plugin: gapi.client is undefined

I've tried a bunch of suggested solutions from stackoverflow but none works, I suspect it may be something to do with cookies or new versions, so I have to ask at long last:
I'm trying to use Google (Sheets specifically) API in my firefox web extension, and I've downloaded this: https://apis.google.com/js/api.js
and added it into my manifest.json under "background" - "scripts" before my own script as you can see in the source code below.
Here is the tutorial:
https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets.values/append
My entire project is too big, so I recreated the problem on a smaller scale:
test.js:
function onCreated() {
if (browser.runtime.lastError) { console.log(`Error: ${browser.runtime.lastError}`); }
else { console.log("Item created successfully"); }
gapi.client.setApiKey('testkey'); //This is the line that doesn't work
}
browser.contextMenus.create({
id: "testlbl",
title: "TEST LABEL - CLICK ME",
contexts: ["all"]
}, onCreated);
browser.contextMenus.onClicked.addListener((info, tab) => {
if(info.menuItemId == "testlbl") {
console.log("ACTION TRIGGERED");
console.log("JQUERY RESULT: "+$(location).attr('href'));
}
});
manifest.json:
{
"manifest_version": 2,
"name": "Testing",
"description": "Random stuff",
"version": "1.0",
"default_locale": "en",
"background": {
"scripts": ["api.js", "jquery-3.3.1.min.js", "test.js"]
},
"permissions": [
"contextMenus",
"activeTab"
]
}
messages.json:
{
"extensionName": {
"message": "TestLabel",
"description": "Name of the extension."
}
}
folder structure(in case you need it to test):
mainFolder
--- test.js
--- api.js
--- jquery-3.3.1.min.js
--- manifest.json
--- _locales
------ en
--------- messages.json
I tried adding JQuery the same way as you can also see, just to make sure I was adding the scripts correctly, and it works fine. I downloaded it from here:
https://code.jquery.com/jquery-3.3.1.min.js
The downloading was suggested as a solution here: https://developer.chrome.com/extensions/contentSecurityPolicy#resourceLoading
The problem is that I get "gapi.client is undefined" in the browser console and nothing happening as a result. I've only put in the line gapi.client.setApiKey('testkey'); to test the Google API and narrow the problem down.

Scaffolding - Extend a js object

I'm working with scaffolt (https://www.npmjs.com/package/scaffolt) to generate some default templates.
I am using handlebars to handle the template.
This works as expected, but i would also like ot extend a JS object while scaffolding.
Basically, i have an object that looks like this:
module.export = {
name: {
"main": ["test"],
"plus": ["test", "test2"],
},
value: {
"test": [...],
"test2": [...]
}
};
and i would like to extend this when i run scaffold and append to both name and value the name of the template i'm scaffolding.
So for instance, if i run scaffolt -g generators template abc the js file will look like this:
module.export = {
name: {
"main": ["test"],
"plus": ["test", "test2"],
"abc" : []
},
value: {
"test": [...],
"test2": [...],
"abc": []
}
};
(where abc was added)
Is it possbile?
Thanks
At the end i managed to solve this but running as a "callback" a postscript.
Basically, in the package.json file i added the command i need to run and i callled it "scaffolt". Then, i've added a postscaffolt command to run a gulp task to inject the stuff i need in place.
The package.json file look something like this:
scripts: {
"scaffolt" "....",
"postscaffolt": "..."
}

how to use in-repo-addons in the ember-engines?

I have created and ember in-repo-addon. Let's say say-hello. After that I created ember-eninge. Let's say users-engine.
In may main application I can directly use the addon as
//application.hbs
{{say-hello}}
How to use it in the users-engine ?
//lib/users-engines/templates/index.hbs
{{say-hello}} //It is not working also not throwing any error
I found the answer but not sure whether it is correct way or not.
In the users-engine/package.json add relative path to addons
{
"name": "users-engine",
"keywords": [
"ember-addon",
"ember-engine"
],
"dependencies": {
"ember-cli-htmlbars": "*"
},
"ember-addon": {
"paths": [
"../say-hello"
]
}
}
and now you can use in-repo-addon in ember-engine directly.
//lib/users-engines/templates/index.hbs
{{say-hello}} //It is working now.

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});

Categories