Extending SAPUI5 Applications - sapui5

I tried to acquaint myself with extending SAPUI5 Applications. To do this I used the splitapp in the folder test-resources/sap/m/demokit
As specified in the Developer Guide - Extending SAPUI5 Applications you only have to create the Component.js for a the custom application project. Now there are 2 questions:
How can you bootstrap the extended Application without having a index.html?
How do you solve relative path-problems (e.g inside the function createContent)?
My current solution is to copy the index.html from the splitapp, paste it into splittapp-ext and modify all the paths...but this solution doesn't seems to be very modular:
original index.html (splitapp):
<!DOCTYPE html>
<html>
<head>
<meta http-equiv='X-UA-Compatible' content='IE=edge' />
<meta charset="UTF-8">
<title>'sap.m.SplitApp' Demo Application</title>
<script id='sap-ui-bootstrap' type='text/javascript'
src='../lib/openui5/resources/sap-ui-core.js'
data-sap-ui-theme='sap_bluecrystal'
data-sap-ui-libs='sap.m'
data-sap-ui-resourceroots='{
"res": "./",
"sap.ui.demo.splitapp" : "./",
"view" : "./view",
"model" : "./model",
"util" : "./util"
}' >
</script>
<link rel="stylesheet" type="text/css" href="css/style.css">
<script>
new sap.m.Shell("Shell", {
title : "sap.m splitapp",
showLogout : false,
app : new sap.ui.core.ComponentContainer({
name : 'sap.ui.demo.splitapp'
}),
homeIcon : {
'phone' : 'img/57_iPhone_Desktop_Launch.png',
'phone#2' : 'img/114_iPhone-Retina_Web_Clip.png',
'tablet' : 'img/72_iPad_Desktop_Launch.png',
'tablet#2' : 'img/144_iPad_Retina_Web_Clip.png',
'favicon' : 'img/favicon.ico',
'precomposed': false
}
}).placeAt('content');
</script>
</head>
<body class='sapUiBody' id="content">
</body>
</html>
modified index.html (splitapp-ext):
<!DOCTYPE html>
<html>
<head>
<meta http-equiv='X-UA-Compatible' content='IE=edge' />
<meta charset="UTF-8">
<title>'sap.m.SplitApp' Demo Application</title>
<script id='sap-ui-bootstrap' type='text/javascript'
src='../lib/openui5/resources/sap-ui-core.js'
data-sap-ui-theme='sap_bluecrystal'
data-sap-ui-libs='sap.m'
data-sap-ui-resourceroots='{
"res": "../splitapp",
"sap.ui.demo.splitapp" : "../splitapp",
"view" : "../splitapp/view",
"model" : "../splitapp/model",
"util" : "../splitapp/util"
}' >
</script>
<link rel="stylesheet" type="text/css" href="../splitapp/css/style.css">
<script>
new sap.m.Shell("Shell", {
title : "sap.m splitapp",
showLogout : false,
app : new sap.ui.core.ComponentContainer({
name : 'sap.ui.demo.splitapp'
}),
homeIcon : {
'phone' : 'img/57_iPhone_Desktop_Launch.png',
'phone#2' : 'img/114_iPhone-Retina_Web_Clip.png',
'tablet' : 'img/72_iPad_Desktop_Launch.png',
'tablet#2' : 'img/144_iPad_Retina_Web_Clip.png',
'favicon' : 'img/favicon.ico',
'precomposed': false
}
}).placeAt('content');
</script>
</head>
<body class='sapUiBody' id="content">
</body>
</html>
For the 2. question I do not have a modular solution.
The anonymous function createContent inside Component.js of the splitapp defines a relative path to the JSON-models. The models cant't be found inside the splitapp-ext Application. The only way I found is to modify the Component.js:
createContent : function () {
// create root view
var oView = sap.ui.view({
id : "app",
viewName : "view.App",
type : "JS",
viewData : { component : this }
});
// --> WORKAROUND: add the module path to the JSON-paths
var rootPath = jQuery.sap.getModulePath("sap.ui.demo.splitapp");
// set navigation model
// load the global data model
var oJSONDataModel = new sap.ui.model.json.JSONModel(rootPath + "/model/data.json");
oView.setModel(oJSONDataModel);
// load the global image source model
var oImgModel = new sap.ui.model.json.JSONModel(rootPath + "/model/img.json");
oView.setModel(oImgModel, "img");
// done
return oView;
}
Is there a better way to extend a SAPUI5 Application?

You can try the extension of an app using SAP Web IDE . You can find the trial links on SAP SCN . The whole idea of Component based approach is to enable the applications to be launched in a broader context such as a Fiori Launchpad . If you want to test it locally, you might consider setting up a local launchpad sandbo from this link:
Set up local Fiori Launchpad.

It is possible to run a local test version of launchpad (with limitations).
first three search results
detailed wiki
As for the second question, remember that control is looking for a model matching the bind path inside on itself, later on parents, and bubbling up to the core. So, setting a model to one view is not best option. You can set model directly to the Component.js as whole application have access there, or just for testing, to the core - sap.ui.getCore().setModel(myModel).
This is an example from ui documentation of proper definition of Component.js with assigned models (for version 1.30, for previous ones you probably won't use 'define'):
sap.ui.define([
"sap/ui/core/UIComponent",
"sap/ui/model/json/JSONModel",
"sap/ui/model/resource/ResourceModel"
], function (UIComponent, JSONModel, ResourceModel) {
"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 i18n model
var i18nModel = new ResourceModel({
bundleName : "sap.ui.demo.wt.i18n.i18n"
});
this.setModel(i18nModel, "i18n");
}
});
});
Similar sample documented in openui5 you can find here:
component and model sample

Related

sails doesnt not auto insert dependencies with handlebars

I'm trying to use handlebars for the templating engine but sails does not seem to insert the files in the dependency folder.
/config/views.js:
engine: 'handlebars',
layout: false,
partials: false
/views/login.handlebars:
<!DOCTYPE html>
<html>
<head>
<!--STYLES-->
<!--STYLES END-->
</head>
<body>
<p>Handlebars</p>
<!--SCRIPTS-->
<!--SCRIPTS END-->
</body>
</html>
/assets/js/dependencies contains:
bootstrap.min
jquery.min
sails.io.js
When I go to the rendered page after lifting sails the files are not populated in between the scripts tag.
Thanks!!
You should update your tasks/config/sails-linker.js and replace all occurrences of ".ejs" with ".handlebars"
E.g. from:
devJs: {
options: {
startTag: '<!--SCRIPTS-->',
endTag: '<!--SCRIPTS END-->',
fileTmpl: '<script src="%s"></script>',
appRoot: '.tmp/public'
},
files: {
'.tmp/public/**/*.html': require('../pipeline').jsFilesToInject,
'views/**/*.html': require('../pipeline').jsFilesToInject,
'views/**/*.ejs': require('../pipeline').jsFilesToInject // <- HERE
}
},
to
devJs: {
options: {
startTag: '<!--SCRIPTS-->',
endTag: '<!--SCRIPTS END-->',
fileTmpl: '<script src="%s"></script>',
appRoot: '.tmp/public'
},
files: {
'.tmp/public/**/*.html': require('../pipeline').jsFilesToInject,
'views/**/*.html': require('../pipeline').jsFilesToInject,
'views/**/*.handlebars': require('../pipeline').jsFilesToInject // <-HERE
}
},
See also this page (where the original answer comes from).
https://mtjburton.co.uk/post/sailsjs+handlebarsjs/

Bind results of client side calculations to control (e.g. chart)

If the source for my chart in SAP UI5 is not a model loaded from a server or file, but the result of some calculations (groupings/maths) based on an existing model, how do I correctly bind it to the chart control and use the data?
You first create the outcome of the calculation. Then you transfer it in a new JSON model and use the setData function to pass the results.
Then you bind the control to the new JSON model. I try to make up some dummy code probably located in your controller:
var data = modelWithRawData.getData();
calculationOutput = doComplicatedCalculation(data);
var calculationModel = new sap.ui.model.json.JSONModel(calculationOutput)
myView.setModel(calculationModel, "calculationModel");
And in the path of your bindings you now need to reference the modelName. Eg in an xmlView:
<Chart data="{calculationModel>/PathToRelevantData}">
<!-- more xml -->
Here's a working example using the sap.viz library:
<html>
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta http-equiv='Content-Type' content='text/html;charset=UTF-8' />
<script src="resources/sap-ui-core.js" id="sap-ui-bootstrap"
data-sap-ui-libs="sap.ui.commons,sap.ui.layout,sap.ui.ux3,sap.ui.table,sap.m,sap.viz"
data-sap-ui-theme="sap_goldreflection">
</script>
<script>
var oModel = new sap.ui.model.json.JSONModel({
businessData : [
{text: "A", value: 100},
{text: "B", value: 200},
{text: "C", value: 300}
]
});
//DO SOME ADVANCE CALCULATION WITH THE JSON DATA...
var data = oModel.getData();
data.businessData[0].value += 30;
data.businessData[1].value = data.businessData[1].value * 2;
data.businessData[2].value = data.businessData[2].value - 100;
//END OF SOME ADVANCE CALCULATION WITH THE JSON DATA...
var oDataset = new sap.viz.ui5.data.FlattenedDataset({
dimensions : [{axis : 1, name : 'Text', value : "{text}"}],
measures : [{name : 'Value', value : '{value}'},
],
data : {path : "/businessData"}
});
var oBarChart = new sap.viz.ui5.Bar({
title : {
visible : true,
text : 'My bar chart'
},
dataset : oDataset
});
// attach the model to the chart and display it
oBarChart.setModel(oModel);
oBarChart.placeAt("content");
</script>
</head>
<body class="sapUiBody" role="application">
<div id="content"></div>
</body>
</html>
Hope this helps.

Unable to Execute Jquery from sidebar in Addon Firefox SDK

I am new to this Firefox SDK , but what i have understood you can execute content Scripts on Pages.
Here is the Code
MAIN.JS
var tabs = require("sdk/tabs");
var data = require("sdk/self").data;
var sidebar = require("sdk/ui/sidebar").Sidebar({
id: 'my-sidebar',
title: 'My sidebar',
url: data.url("index.html"),
onReady: function (worker) {
worker.port.emit('turl',tabs.activeTab.url);
}
});
SIDEBAR.JS
$('#bt1').on('click',function(){
$('title').textContent;
});
INDEX.HTML
<!DOCTYPE HTML>
<html>
<body>
<input type="button" id="bt1" value="Click Me"/>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<script src="sidebar.js"></script>
</body>
</html>
But this code tries to find out title of the Sidebar html.
I have also tried using contentScriptFile in Main.js but same thing happened
var tabs = require("sdk/tabs");
var data = require("sdk/self").data;
var sidebar = require("sdk/ui/sidebar").Sidebar({
id: 'my-sidebar',
title: 'My sidebar',
url: data.url("index.html"),
contentScriptFile: [data.url("jquery.min.js"),data.url("sidebar.js")],
onReady: function (worker) {
worker.port.emit('turl',tabs.activeTab.url);
}
});
The Jquery code is in the sidebar.js
Still no Results.Please help
There is no contentScriptFile for the Sidebar class.
Try this: copy the jquery library to a local file in the data folder, then refer to it using a relative path. Sidebars can only use 'local' JS, they cannot load scripts from the internet.

cross rider extension to fetch new posts from feed using google feeds api

I am trying to create an extension to display all the latest posts fetched from my feed using google feeds api. To implement this, I have added this code in background.js:
appAPI.ready(function() {
// Global variable to hold the toggle state of the button
var buttonState = true;
// Sets the initial browser icon
appAPI.browserAction.setResourceIcon('images/icon.png');
// Sets the tooltip for the button
appAPI.browserAction.setTitle('My Postreader Extension');
appAPI.browserAction.setPopup({
resourcePath:'html/popup.html',
height: 300,
width: 300
});});
and in popup.html,
<!DOCTYPE html><html><head><meta http-equiv="X-UA-Compatible" content="IE=edge">
<script type="text/javascript">
function crossriderMain($) {eval(appAPI.resources.get('script.js')); }</script>
</head>
<body><div id="feed"></div></body></html>
The script.js file is-
google.load("feeds", "1");
function initialize() {
var feed = new google.feeds.Feed("http://www.xxxxx.com/feed/");
feed.setNumEntries(10);
feed.load(function(result) {
if (!result.error) {
var container = document.getElementById("feed");
for (var i = 0; i < result.feed.entries.length; i++) {
var entry = result.feed.entries[i];
var div = document.createElement("div");
var link = document.createElement('a');
link.setAttribute('href', entry.link);
link.setAttribute('name', 'myanchor');
div.appendChild(document.createTextNode(entry.title));
div.appendChild(document.createElement('br'));
div.appendChild(link);
div.appendChild(document.createElement('br'));
container.appendChild(div);
}
}
});
}
google.setOnLoadCallback(initialize);
But I am unable to get desired result.The popup doesn't display anything.It just remain blank.
Since you are using a resource file for the popup's content, it's best to load the remote script from the crossriderMain function, as follows:
<!DOCTYPE html>
<html>
<head>
<!-- This meta tag is relevant only for IE -->
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<script type="text/javascript">
function crossriderMain($) {
appAPI.db.async.get('style-css', function(rules) {
$('<style type="text/css">').text(rules).appendTo('head');
});
appAPI.request.get({
url: 'http://www.google.com/jsapi',
onSuccess: function(code) {
$.globalEval(code);
appAPI.db.async.get('script-js', function(code) {
// runs in the context of the extension
$.globalEval(code.replace('CONTEXT','EXTN'));
// Alternatively, run in context of page DOM
$('<script type="text/javascript">').html(code.replace('CONTEXT','PAGE DOM')).appendTo('head');
});
}
});
}
</script>
</head>
<body>
<h1>Hello World</h1>
<div id="feed"></div>
</body>
</html>
[Disclaimer: I am a Crossrider employee]

backbone.js - problem loading using models defined in separate file

I'm running Sinatra with Backbone.js. I'm trying to split up my models, views, etc so they aren't all lumped into a single JS file. Right now I have the following.
index.html
<html>
<head>
<meta http-equiv="content-type" content="text/html;charset=UTF-8" />
<script src="scripts/underscore-min.js"></script>
<script src="scripts/jquery-1.5.min.js"></script>
<script src="scripts/backbone-min.js"></script>
<script src="scripts/models.js"></script>
...
models.js
Models = {
var Event = Backbone.Model.extend({
});
var Events = Backbone.Collection.extend({
url: '/events',
model: Event
});
};
So models.js expects that Backbone.js has been loaded, which it should have been based on index.html, however, I'm getting a JavaScript error in models.js where I reference Backbone.Model.
Any ideas on what I'm missing here?
That isn't valid javascript. Something like this is more likely to work :
Models = {}
Models.Event = Backbone.Model.extend({
});
Models.Events = Backbone.Collection.extend({
url: '/events',
model: Event
});