Applying MVC to SAPUI5 application - sapui5

So basically I have a Split page in SAPUI5 and have few master pages and detail pages attach to it. I have no problem to do the whole thing in one javascript file, but since the file is getting too big and too hard to read I want to apply MVC design to this application and separate every page into one view and control file. Here is my example:
var oSplitApp = new sap.m.SplitApp({
masterPages : [ page1, page4, page5],
detailPages : [ page0, page2, page3 ],
initialMaster : "page1",
initialDetail : "page0"
});
and pages are like:
var page0 = new sap.m.Page("initialPage", {});
var page1 = new sap.m.Page({
enableScrolling : true,
footer : new sap.m.Bar({
id : 'page1_footer',
contentMiddle : [ new sap.m.Button({
text: "Add"
})]
}),
content : [ oTable = new sap.m.Table("items", {
inset : true,
visible : true,
getIncludeItemInSelection : true,
showNoData : false,
columns : [ new sap.m.Column({
styleClass : "name",
hAlign : "Left",
header : new sap.m.Label({
text : "something"
})
}) ]
}) ]
});
var template = new sap.m.ColumnListItem({
type : "Navigation",
visible : true,
selected : true,
cells : [ new sap.m.Label({
text : "{name}"
}) ]
});
and so on ...
and also each page has its on attachPress function so when you click on the buttons or links something happen and some other pages fire up. please show me in details how to do so?
thank you for your help in advance.

You can do this by creating own View/Controller for every Master/Detail. In your View, where your oSplitApp is built you can then instantiate your Master/Details Views like this:
// load your external view/controller:
var page1 = sap.ui.jsview("path-to.DetailView1");
var oSplitApp = new sap.m.SplitApp({
masterPages : [ page1, page4, page5],
detailPages : [ page1, page2, page3 ],
initialMaster : "page1",
initialDetail : "page0"
});
Your external View file for example could return the sap.m.Page object in createContent.
Hopefully this helps you. If you have more questions about this just let me know.

Related

Overlapping of two buttons in SAPUI5

I want to create a content table using SAPUI5 but when I am trying to add more than one button they are getting overlapped.
Code:
var page2 = new sap.m.Page("page2",{
title : "Contents",
showNavButton : true,
navButtonPress : function() {
app.back();//go back to previous page
},
content : new sap.m.Button({
text : "Introduction",
press : function() {
app.to("page3");//navigate to Home
},
//enabled : false
type : sap.m.ButtonType.Transparent
}),
content : new sap.m.Button({
text : "Iview",
press : function() {
app.to("page3");//navigate to Home
},
//enabled : false
type : sap.m.ButtonType.Transparent
})
});
var Button1 = new sap.m.Button({
text : "Introduction",
press : function() {
//navigate to Home
app.to("page3");
},
//enabled : false
type : sap.m.ButtonType.Transparent
});
var Button2 = new sap.m.Button({
text : "Iview",
press : function() {
//navigate to Home
app.to("page3");
},
//enabled : false
type : sap.m.ButtonType.Transparent
})
var page2 = new sap.m.Page("page2",{
title : "Contents",
showNavButton : true,
navButtonPress : function() {
//go back to previous page
app.back();
},
content : [Button1, Button2]
});
page2.placeAt("body");

sap.m.list - hide a row

I have a problem and hope to find help. On a sap.m.page i have placed a list (sap.m.list)
new sap.m.Page(
"mainPage", {
title : "",
enableScrolling : true,
content : [
oList = new sap.m.List("items", {
threshold : 2,
inset : false,
headerText : "Aufträge",
//filters : filters,
columns : [
new sap.m.Column({
hAlign : "Left",
width : '45px',
//styleClass : "qty",
header : new sap.m.Label({
text : "Station"
})
}),
new sap.m.Column({
hAlign : "Left",
width : '40px',
header : new sap.m.Label({
text : "Zeit"
})
}),
new sap.m.Column({
hAlign : "Left",
width : '20px',
header : new sap.m.Label({
text : ""
})
}),
new sap.m.Column({
hAlign : "Left",
width : '20px',
header : new sap.m.Label({
text : ""
})
}),
new sap.m.Column({
hAlign : "Left",
width : '50px',
header : new sap.m.Label({
text : "Raum"
}),
minScreenWidth : "Phone"//XXSmall"
//demandPopin : true
}),
new sap.m.Column({
hAlign : "Left",
width : '40px',
header : new sap.m.Label({
text : "Bett"
}),
}),
new sap.m.Column({
hAlign : "Left",
width : '20px',
//styleClass : "qty",
header : new sap.m.Label({
text : "St."
})
}),
new sap.m.Column({
hAlign : "Left",
width : '20px',
//styleClass : "qty",
header : new sap.m.Label({
text : "Typ"
})
(...)
For the entries i have a template definded
//Template für die Listzeilen
var template = new sap.m.ColumnListItem({
type : "Navigation",
cells : [
new sap.m.Label({
text: "{Orgpf}"
}),
new sap.m.Label({
text : "{Uhrzeit}"
}),
new sap.ui.core.Icon({
src: "{IconTermin}"
}),
new sap.ui.core.Icon({
src: "{IconAufbereitung}"
}),
new sap.m.Label({
text: "{Bett}"
}),
new sap.m.Label({
text: "{Bettnr}"
}),
new sap.m.Label({
text : "{Status02}"
}),
new sap.m.Label({
text: "{Betttyp}"
})
(...)
The data for the list comes from an odata-service an our sap gateway. I fill the table with follwing routine
var filter = new sap.ui.model.Filter("Team", sap.ui.model.FilterOperator.EQ, localStorage.getItem("Team"));
oList.bindAggregation("items", { path: "/AuftragSet", filters: filter, template});
This works fine.
Problem: not all entries should be displayed after loading the entries. After processing a visibile entry with a special type the corresponding entry should be now visible. I dont want to read the data again with the service, because i have not internet access at all places. Therefore i select more entries and need to hide some of them. How can i solve this? Where can i set the filter?
THX for your answers.
Kind regards,
Sven
In your case, Filter is not good option because you want to download all data and show select few. On the other hand, Filter will cause server to return select few rows beating your purpose.
You can use inherited visible property of sap.m.ColumnListItem. When defining your template add visible property and bind it to your OData property.
var template = new sap.m.ColumnListItem({
type: "Navigation",
visible: "{put you OData determining property here}",
cells: [...]
});
Also, consider using sap.m.Table or one of its subclasses as sap.m.List with columns is deprecated. https://sapui5.hana.ondemand.com/docs/api/symbols/sap.m.List.html#addColumn.
Use this link to decide which table to use: https://sapui5.hana.ondemand.com/#docs/guide/148892ff9aea4a18b912829791e38f3e.html
Hope this helps.
Filtering out the data that you want to bind the table is the good way to do. find the below link for how to filter the Table or List on success of your OData service: sapui5-how-to-filter-data-with-2-or-more-values

How to build an expandable sap.m.Table in sapui5?

I am searching for a kind of TreeTable that uses sap.m.Table as base.
My first "hack" looks like this:
Experimental data model:
var oModel = new sap.ui.model.json.JSONModel({
"Items" : [
{"Name" : "A", "SubItems" : [
{"Name" : "A.1" },
{"Name" : "A.2" },
{"Name" : "A.3" },
]
},
{"Name" : "B", "SubItems" : [
{"Name" : "B.1" }
]
},
]
});
this.getView().setModel(oModel, "expand");
Experimental Table implementation:
var oContent = new sap.m.Table({
items : {
path : "expand>/Items",
template : new sap.m.ColumnListItem({
customData : [ new sap.ui.core.CustomData({
key : "SubItems",
value : "SubItems",
customData : {
path : "expand>SubItems",
template : new sap.ui.core.CustomData({
key : this.createId("subItem"),
value : new sap.m.ColumnListItem({
cells : [
new sap.m.Text({
text: "{expand>Name}",
})
]
})
})
}
})
],
type : sap.m.ListType.Active,
cells: [
new sap.m.Text({ text: "{expand>Name}" }),
],
press : [function(oEvent) {
var oRow = oEvent.getSource();
var oTable = oRow.getParent();
var oItems = oTable.getItems();
var insertIndex = -1;
var oSubItemsData = undefined;
for (var i=0;i<oItems.length;i++) {
if (oItems[i]==oRow) {
oSubItemsData = oRow.getAggregation("customData").filter(function(oData) {return oData.getProperty("key") == "SubItems";});
insertIndex = i;
}
}
var oSubItems = oSubItemsData[0].getAggregation("customData").map(function(oData) {return oData.getValue();});
for (var j=0;j<oSubItems.length;j++) {
var mShownSubItems = oItems.filter(function(oShownItem) {
return oShownItem == oSubItems[j];
});
if (mShownSubItems.length>0) {
console.log("removing"+j);
oTable = oTable.removeItem(oSubItems[j]);
} else {
console.log("adding "+(insertIndex+j+1));
oTable = oTable.insertItem(oSubItems[j],insertIndex+j+1);
}
}
}, oController]
})
},
columns : [ new sap.m.Column({}) ],
});
I figured out different problems with this "hack".
First of all the binding of the SubItems is not displayed, if I use hard coded text the text is shown.
Second problem is, that I can only insert exactly one row.
How can this be solved?
You may be interested in the Table - Breadcrumb sample in Explored. It uses sap.m.Table as a base and can display a hierarchy of data, in a tree table kind of style.
I have bumped into the same issue and I've solved it by using a sap.m.Panel as a sap.m.CustomListItem aggregation of the sap.m.List. If you wish to expand it by clicking anywhere on the row (collapsed Panel) and not only on the Panel's expand Button, you could get the aggregation go trough a factory, which can do something like this
var oUIControl = this.byId("custItem").clone(sId);
var oPanel = oUIControl.getContent()[0];
oPanel.addEventDelegate({
onclick: function (e) {
try {
if (sap.ui.getCore().byId(e.target.id).getMetadata().getElementName() !== "sap.ui.core.Icon") {
oPanel.setExpanded(!oPanel.getExpanded());
}
} catch (e) {
oPanel.setExpanded(!oPanel.getExpanded());
}
}
});
return oUIControl;
The check is needed because without it the click event is fired twice when clicking on the expand button itself. With it we trigger custom click event when the user clicks anywhere else on the panel row.

SAPUI5 multiple sap.m.TileContainer in JS view

I have a single page app written in SAPUI5 using JS views. I want to create a "Dashboard" page and put some tiles on it. Therefore I am creating a "sap.m.TileContainer" in the "createContent" function of my view.js-file.
What I need to implement is to have two separate TileConatiner because I have important tiles at the top and less important ones at the bottom. But no matter what I do e.g. putting the two TileContainers in a MatrixLayout, HorizontalLayout or as "content" into a sap.m.page it is no longer shown.
One TileContainer is shown when I just return this single instance directly without any componet surrounding it.
Can anyone help me out here please?
Following code works fine:
createContent : function(oController) {
var tileContainer = new sap.m.TileContainer({
tiles : [
new sap.m.StandardTile({
icon : "sap-icon://play",
title : "Important Tile",
press : function() {
oController.nav.to("AfoStart");
}
}), new sap.m.StandardTile({
icon : "sap-icon://pause",
title : "ANOTHER Important Tile",
press : function() {
oController.nav.to("AfoStart");
}
}), new sap.m.StandardTile({
icon : "sap-icon://timesheet",
title : "Third important tile",
press : function() {
oController.nav.to("AfoStart");
}
}), new sap.m.StandardTile({
icon : "sap-icon://number-sign",
title : "UNIMPORTANT ONE",
press : function() {
oController.nav.to("AfoStart");
}
}), new sap.m.StandardTile({
icon : "sap-icon://locate-me",
title : "UNIMPORTANT TWO",
press : function() {
oController.nav.to("AfoStart");
}
})
],
});
return tileContainer;
}
This code doesnt work:
createContent : function(oController) {
var tileContainerTop = new sap.m.TileContainer({
tiles : [
new sap.m.StandardTile({
icon : "sap-icon://play",
title : "Important Tile",
press : function() {
oController.nav.to("AfoStart");
}
}), new sap.m.StandardTile({
icon : "sap-icon://pause",
title : "Another important Tile",
press : function() {
oController.nav.to("AfoStart");
}
}), new sap.m.StandardTile({
icon : "sap-icon://timesheet",
title : "Third important tile",
press : function() {
oController.nav.to("AfoStart");
}
}),
],
});
var tileContainerBottom = new sap.m.TileContainer({
tiles : [
new sap.m.StandardTile({
icon : "sap-icon://play",
title : "UNIMPORTANT ONE",
press : function() {
oController.nav.to("AfoStart");
}
}), new sap.m.StandardTile({
icon : "sap-icon://pause",
title : "UNIMPORTANT TWO",
press : function() {
oController.nav.to("AfoStart");
}
})
],
});
var page = new sap.m.Page("myPage", {
title: "Dashboard",
content: [tileContainerTop, tileContainerBottom]
});
// OR create MatrixLayout here...doenst work
// OR create HorizontalLayout here...doesnt work
return page;
}
you need to set enableScrolling of your page to false.
Because then the page will take 100% of the place. If you do not do it the page will try to be as big as its content.
A tile container is by default as big as its parent so both the page and the containers will have a height of 0.
Here i placed 2 Tile containers below each other so they take half of the screen:
http://jsbin.com/disalulekezo/1/
Best regards
You have to set enableScrolling of your page to false and adjust the height of TileContainer both. Set the height of both container as 50-50% , both the tiles will be visible on your page. Only setting enableScrolling to false will not work.

How to get content of a row in sap.m.table

So basically My problem is I have a page:
var page1 = new sap.m.Page({
title: "Something",
enableScrolling : true,
content : [
oTable = new sap.m.Table("items", {
columns : [
new sap.m.Column({
styleClass : "name",
hAlign : "Left",
header : new sap.m.Label({
text : "firstColumn"
})
})
]
})]
});
var template = new sap.m.ColumnListItem({
type : "Navigation",
cells : [
new sap.m.Label({
text : "{name}"
})
]
});
template.attachPress(function(oEvent){
var selectedRowContext = oEvent.getParameter("item");
alert(selectedRowContext);
});
Here I want to get the selectedRowContext and I don't know how?
Thank you
If you are binding data try
this.getBindingContext(/*modelName?*/)
or
oEvent.getSource().getBindingContext(/*modelName?*/)
//oControlEvent is the argument from the attachpress event
var selectedData = oControlEvent.getParameters().rowBindingContext.getModel().getData();
var selectedPath = oControlEvent.getParameters().rowBindingContext.getPath();
var selectedIndex = selectedPath.split("/")[selectedPath.split("/").length - 1];
selectedData = selectedData[OBJECTNAME][selectedIndex];