How Side Navigation component can be used in UI5 to show the content? - sapui5

I am trying to use Side Navigation component in UI5. From the below picture you can see a modal dialog, I have used side navigation to get the items in the left. when ever I select something from the list, corresponding content should be visible on the right.
Can someone please suggest me on how it can be achieved.

You will need some form of Splitter e.g. sap.ui.layout.Splitter
Take a look a this little Demo
<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge"/>
<meta http-equiv="Content-Type" content="text/html"/>
<meta charset="UTF-8">
<script src="https://sapui5.hana.ondemand.com/resources/sap-ui-core.js" id="sap-ui-bootstrap" data-sap-ui-libs="sap.m,sap.ui.layout" data-sap-ui-theme="sap_belize"></script>
<script>
var dialogModel = {
RateCategory_ID: {
id: "RateCategory_ID",
label: "Rate Category",
type: "MultiSelect",
values: [{
key: "ST",
value: "ST",
selected: true
}, {
key: "DT",
value: "DT",
selected: false
}]
},
Approval_Filter: {
id: "Approval_Filter",
label: "ApprovalFilter",
type: "SingleSelect",
values: [{
key: "Separate_Filter",
value: "Separate",
selected: true,
}, {
key: "Last_Approval_Filter",
value: "Last Approval",
selected: false
}]
}
};
var model = new sap.ui.model.json.JSONModel();
model.setData(dialogModel);
var oParentList = new sap.m.List({
mode: "SingleSelectMaster",
items: {
path: "/",
template: new sap.m.StandardListItem({
type: "Active",
title: "{label}"
})
},
selectionChange: function(event) {
var oBindingContext = event.getSource().getSelectedItem().getBindingContext();
oMembersList.setBindingContext(oBindingContext);
oSelectedItemsList.setBindingContext(oBindingContext);
oSelectedItemsList.getBinding("items").filter(new sap.ui.model.Filter("selected",sap.ui.model.FilterOperator.EQ,true));
}
});
oParentList.addEventDelegate({
onAfterRendering: function() {
// check if nothing is selected
if (this.getSelectedItem() === null) {
var items = this.getItems();
// check if there are items
if (items && items.length > 0) {
this.setSelectedItem(items[0], true);
}
}
this.fireSelectionChange();
}
}, oParentList);
var oMembersList = new sap.m.List({
mode: "{type}",
includeItemInSelection: true,
modeAnimationOn: false,
items: {
path: "values",
template: new sap.m.StandardListItem({
type: "Active",
title: "{value}",
selected: "{selected}"
})
},
selectionChange: function(event) {
var oBindingContext = event.getSource().getBindingContext();
oSelectedItemsList.setBindingContext(oBindingContext);
oSelectedItemsList.getBinding("items").filter(new sap.ui.model.Filter("selected",sap.ui.model.FilterOperator.EQ,true));
}
});
var oSelectedItemsList = new sap.m.List({
mode: "Delete",
modeAnimationOn: false,
visible: {
path: "type",
formatter: function(type) {
return type === "MultiSelect";
}
},
items: {
path: "values",
template: new sap.m.StandardListItem({
title: "{value}",
})
},
delete: function(oEvent) {
model.setProperty(oEvent.getParameters().listItem.getBindingContextPath() + "/selected", false);
oMembersList.fireSelectionChange();
}
});
var variablesVBox = new sap.m.VBox({
items: [
new sap.m.Label({
text: "Variables"
}),
new sap.m.Label({
text: ""
}),
oParentList
],
layoutData: new sap.ui.layout.SplitterLayoutData({
resizable: false
})
});
var membersVBox = new sap.m.VBox({
items: [
new sap.m.Label({
text: "Available Members"
}),
new sap.m.Label({text: ""}),
oMembersList
],
layoutData: new sap.ui.layout.SplitterLayoutData({
resizable: false
})
});
var selectedMembersVBox = new sap.m.VBox({
items: [
new sap.m.Label({
text: "Selected Members"
}),
new sap.m.Label({text: ""}),
oSelectedItemsList
],
layoutData: new sap.ui.layout.SplitterLayoutData({
resizable: false
})
});
var splitter = new sap.ui.layout.Splitter({
contentAreas: [variablesVBox, membersVBox, selectedMembersVBox]
});
splitter.setModel(model);
var okButton = new sap.m.Button({
text: "OK",
press: function(event) {
oDialog.close();
}
});
var cancelButton = new sap.m.Button({
text: "Cancel",
press: function(event) {
oDialog.close();
}
});
var oDialog = new sap.m.Dialog({
title: "Global Variables",
content: [splitter],
buttons: [okButton, cancelButton],
contentWidth: "70%",
contentHeight: "70%"
});
var oButton = new sap.m.Button({
text: "Open dialog",
press: function() {
oDialog.open();
}
}).placeAt("content");
</script>
</head>
<body class="sapUiBody">
<div id="content"></div>
</body>
</html>

sap.tnt.SideNavigation has to be placed inside sap.tnt.ToolPage in order to work properly. But the ToolPage control is meant to take the full width and height of the page, not only a part of it, like it would if placed inside Dialog. Therefore using this controls to achieve what you need is not possible.

Related

restrict addEventDelegate to parent hbox only

This is a custom control created for my previous question Custom font for currency signs
I have two span elements coming next to each other. They sit in the FormattedText. The FormattedText itself sits in the HBox.
I want popover fired when user mouses over/out from the hbox. Unfortunately, as I have 2 spans this fires separately when user hovers overs them (thus showing 2 separate popovers, when in fact it should be one). My assumption is that this causes because onmouseover/out is attached to both spans under the hood. Can I restrict these events to hbox only?
sap.ui.define([
'sap/ui/core/Control',
'sap/m/FormattedText',
'sap/m/HBox',
], function (Control, FormattedText, HBox) {
return Control.extend('drex.control.TherapyCosts', {
metadata: {
properties: {
rank: {
type: 'int',
defaultValue: 0
},
},
aggregations: {
_rankedTherapyCost: {type: 'sap.m.FormattedText', multiple: false, singularName: '_rankedTherapyCost'},
_popover: {type: 'sap.m.Popover', multiple: false, singularName: '_popover'},
_hbox: {type: 'sap.m.HBox', multiple: false}
}
},
init: function () {
Control.prototype.init.apply(this, arguments);
},
onBeforeRendering: function () {
const highlighedCurrency = this.getCurrency().repeat(this.getRank());
const fadedCurrency = this.getCurrency().repeat(7 - this.getRank());
const _popover = new sap.m.Popover({
showHeader: false,
placement: 'VerticalPreferredBottom',
content: new sap.m.Text({text: 'test'})
});
this.setAggregation('_popover', _popover);
const _formattedText = new FormattedText({
htmlText:
`<span class="currencyHighlighted">${highlighedCurrency}</span>` +
`<span class="currencyFaded">${fadedCurrency}</span>`
});
this.setAggregation('_rankedTherapyCost', _formattedText);
const _hbox = new HBox(
{ items: [this.getAggregation('_rankedTherapyCost')]})
.addEventDelegate({
onmouseover: () => {
this.getAggregation('_popover').openBy(this);
},
onmouseout: () => {
this.getAggregation('_popover').close()
}
});
this.setAggregation('_hbox', _hbox)
},
renderer: function (rm, oControl) {
const _hbox = oControl.getAggregation('_hbox');
rm.write('<div');
rm.writeControlData(oControl);
rm.write('>');
rm.renderControl(_hbox);
rm.write('</div>');
}
});
});
Here is the video of the issue
https://streamable.com/fjw408
The key here is the mouseout event is triggered when the mouse moves out of any child element of the element that is listening for the event. In this case, for example, moving from the emphasised text to the faded text, you get a mouseout event when moving off the emphasised text, which closes the popup, then a mouseover event on the faded text which opens it again.
Since you opening an already open popup doesn't do anything, you only need add a line on mouseout to inspect the element that you've gone to. If it is not a child of the current element, only then close the popover.
if (!this.getDomRef().contains(e.toElement)) {
popOver.close()
}
Building on D.Seah's answer, I've added this to the JSBin. I personally don't like using onBeforeRendering and onAfterRendering like this, so I've refactored a little to construct everything on init and simply change the controls on property change. This way, you're doing less on rendering for performance reasons.
sap.ui.define([
'sap/ui/core/Control',
'sap/m/FormattedText',
], function (Control, FormattedText) {
Control.extend('TherapyCosts', {
metadata: {
properties: {
rank: {
type: 'int',
defaultValue: 0
},
currency: {
type: "string",
defaultValue: "$"
}
},
aggregations: {
_highlighted: {type: 'sap.m.FormattedText', multiple: false},
_faded: {type: 'sap.m.FormattedText', multiple: false},
_popover: {type: 'sap.m.Popover', multiple: false, singularName: '_popover'}
}
},
init: function () {
Control.prototype.init.apply(this, arguments);
this.addStyleClass('therapy-cost');
const highlight = new FormattedText();
highlight.addStyleClass("currency-highlight");
this.setAggregation('_highlighted', highlight);
const faded = new FormattedText();
faded.addStyleClass("currency-faded");
this.setAggregation('_faded', faded);
const _popover = new sap.m.Popover({
showHeader: false,
placement: 'VerticalPreferredBottom',
content: new sap.m.Text({text: 'test'})
});
this.setAggregation('_popover', _popover);
},
_changeAggr: function () {
const highlighedCurrency = this.getCurrency().repeat(this.getRank());
const highlight = this.getAggregation("_highlighted");
highlight.setHtmlText(highlighedCurrency);
const fadedCurrency = this.getCurrency().repeat(7 - this.getRank());
const faded = this.getAggregation("_faded");
faded.setHtmlText(fadedCurrency);
},
setRank: function(rank) {
if (this.getProperty("rank") !== rank) {
this.setProperty("rank", rank);
this._changeAggr();
}
},
setCurrency: function(curr) {
if (this.getProperty("currency") !== curr) {
this.setProperty("currency", curr);
this._changeAggr();
}
},
renderer: function (rm, oControl) {
rm.write('<div');
rm.writeControlData(oControl);
rm.writeClasses(oControl);
rm.writeStyles(oControl);
rm.write('>');
rm.renderControl(oControl.getAggregation('_highlighted'));
rm.renderControl(oControl.getAggregation('_faded'));
rm.write('</div>');
},
onmouseover: function (e) {
const popOver = this.getAggregation('_popover');
popOver.openBy(this);
},
onmouseout: function (e) {
if (!this.getDomRef().contains(e.toElement)) {
const popOver = this.getAggregation('_popover');
popOver.close();
}
}
});
(new TherapyCosts({
rank: 5,
currency: "£"
})).placeAt('content')
});
.therapy-cost {
display: inline-flex;
flex-direction: row;
}
.therapy-cost .currency-highlighted {
color: black;
}
.therapy-cost .currency-faded {
color: lightgrey;
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>JS Bin</title>
<script
src="https://openui5.hana.ondemand.com/resources/sap-ui-core.js"
id="sap-ui-bootstrap"
data-sap-ui-theme="sap_bluecrystal"
data-sap-ui-xx-bindingSyntax="complex"
data-sap-ui-libs="sap.m"></script>
</head>
<body class="sapUiBody sapUiSizeCompact">
<div id='content'></div>
</body>
</html>
https://jsbin.com/gukedamemu/3/edit?css,js,output
i think you can do without the hbox; by just having two formatted text or any sapui5 controls will be ok too.
sap.ui.define([
'sap/ui/core/Control',
'sap/m/FormattedText',
], function (Control, FormattedText) {
Control.extend('TherapyCosts', {
metadata: {
properties: {
rank: {
type: 'int',
defaultValue: 0
},
currency: {
type: "string",
defaultValue: "$"
}
},
aggregations: {
_highlighted: {type: 'sap.m.FormattedText', multiple: false},
_faded: {type: 'sap.m.FormattedText', multiple: false},
_popover: {type: 'sap.m.Popover', multiple: false, singularName: '_popover'}
}
},
init: function () {
Control.prototype.init.apply(this, arguments);
this.addStyleClass('therapy-cost')
},
onBeforeRendering: function () {
const highlighedCurrency = this.getCurrency().repeat(this.getRank());
const highlight = new FormattedText({
htmlText: highlighedCurrency
});
this.setAggregation('_highlighted', highlight);
const fadedCurrency = this.getCurrency().repeat(7 - this.getRank());
const faded = new FormattedText({
htmlText: fadedCurrency
});
this.setAggregation('_faded', faded);
const _popover = new sap.m.Popover({
showHeader: false,
placement: 'VerticalPreferredBottom',
content: new sap.m.Text({text: 'test'})
});
this.setAggregation('_popover', _popover);
},
renderer: function (rm, oControl) {
rm.write('<div');
rm.writeControlData(oControl);
rm.writeClasses(oControl);
rm.writeStyles(oControl);
rm.write('>');
rm.renderControl(oControl.getAggregation('_highlighted'));
rm.renderControl(oControl.getAggregation('_faded'));
rm.write('</div>');
},
onAfterRendering: function () {
const popOver = this.getAggregation('_popover');
const highlighted = this.getAggregation("_highlighted");
highlighted.$().addClass("currency-highlighted");
highlighted.$().hover(function() {
popOver.openBy(highlighted);
}, function() {
popOver.close();
});
const faded = this.getAggregation("_faded");
faded.$().addClass("currency-faded");
},
});
(new TherapyCosts({
rank: 5
})).placeAt('content')
});
https://jsbin.com/razebuq/edit?css,js,output

Add items to SelectDialog dynamically

I need to add more items to the SelectDialog control based on the Odata from the backend based on a condition. The code is,
if (!this._oDialog) {
this._oDialog = new sap.m.SelectDialog({});
this._oDialog.setModel(oParentModel);
this._oDialog.bindAggregation("items", {
path: "/et_getSidSet",
template: new sap.m.StandardListItem({
title: "{Sid}"
})
});
if (v === '1') {
var oItem1 = new sap.m.StandardListItem({
title: 'PC2',
type: 'Active'
});
this._oDialog.addItem(oItem1);
} else if (v === '2') {
var oItem1 = new sap.m.StandardListItem({
title: 'AC2',
type: 'Active'
});
this._oDialog.addItem(oItem1);
var oItem2 = new sap.m.StandardListItem({
title: 'IC2',
type: 'Active'
});
this._oDialog.addItem(oItem2);
}}
The issue is, when I click on helprequest icon, the item is not adding for the very first time. However, its added from second time onwards.
I need the item to get added for the first time.
Thanks in advance!
Using SAPUI5's JSView to create the dialog and Radial Chart, triggered by button press event, you can have a look at the full application here Plunkr Example
openDialog: function() {
if (!this.draggableDialog) {
this.draggableDialog = new Dialog({
title: "Charts",
type: "Message",
contentWidth: "900px",
contentHeight: "700px",
resizable: true,
content: [
new RadialMicroChart({
percentage: 75,
total: 100,
size: "Responsive",
valueColor: "Critical"
})
],
beginButton: new Button({
text: "Close",
press: function() {
this.draggableDialog.close();
}.bind(this)
})
});
this.getView().addDependent(this.draggableDialog);
}
this.draggableDialog.open();
}

How to dynamically bind items of sap.m.Select

In a table, there is a drop-down for each row.
And every row has unique ID and based on it the values should be populated on UI
ID Country
1 India/Malasia/UK
2 Paris/spain/USA
3 Canada/Chile/China
So, I am trying to send the path of ObjectID.
The below code doesn't work. Not sure how to achieve this.
oEditTemplate = new Select({
forceSelection: false,
selectedKey: sPath,
items: {
path: {
path: "tempModel>ObjectId",
formatter: this._editableFormatter.bind(this, sName)
},
templateShareable: false,
template: new ListItem({
key: "{tempModel>value}",
text: "{tempModel>value}"
})
}
});
You can achieve it by using custom data and onAfterRendering. You can refer this JSBIN example
<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta http-equiv='Content-Type' content='text/html;charset=UTF-8'/>
<script src="https://sapui5.hana.ondemand.com/resources/sap-ui-core.js"
id="sap-ui-bootstrap"
data-sap-ui-libs="sap.ui.table,sap.m"
data-sap-ui-xx-bindingSyntax="complex"
data-sap-ui-theme="sap_bluecrystal"></script>
<script>
var ITEMS = {
"1": ["India", "Malasia", "UK"],
"2": ["Paris", "Spain", "USA"],
"3": ["Canada", "Chile", "China"]
};
sap.m.Select.extend("CustomSelect", {
metadata: {
properties: {
countryId: "string"
}
},
renderer: {}
});
var oSelect = new sap.m.Select({
customData: {
key: "countryId",
value: "{ID}"
}
});
oSelect.addEventDelegate({
onAfterRendering: function(oEvent) {
var src = oEvent.srcControl;
var countryId = src.data("countryId");
if (!!countryId && src.getItems().length === 0) {
ITEMS[countryId].forEach(function(i) {
src.addItem(new sap.ui.core.Item({
text: i,
value: i
}));
});
}
}
});
var oTable = new sap.ui.table.Table({
rows: '{/d/results}',
columns: [
new sap.ui.table.Column({
label: new sap.m.Label({text: "ID"}),
template: new sap.m.Text({text:"{ID}"}),
filterProperty: 'District'
}),
new sap.ui.table.Column({
label: new sap.m.Label({text: "Country"}),
template: oSelect
})]
});
var model = new sap.ui.model.json.JSONModel({
d: {
results: [
{ ID: "1"},
{ ID: "2"}
]
}
});
oTable.setModel(model);
oTable.placeAt('content');
</script>
</head>
<body id="content" class="sapUiBody sapUiSizeCompact">
</body>
</html>

How to navigate to another XML page when the user click on message popup button

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

binding is not working in javascript model

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>