Highlight selected row of table in SAP UI5 - sapui5

I am using sap.m.table with mode "SingleSelectLeft" and with Aggregation ColumnListItem of type "Navigation".
On clicking of any of the items from the table, I want to show another page in split-app(detail page). I have put the routing code in the press event of ColumnListItem but this is leading to an issue as :
The selected item goes off(not appearing selected) when I click on the detail page.
Here is the snippet I am working with:
<Table inset="false" noDataText="{i18n>noDataMasterTable}" mode="SingleSelectLeft" selectionChange="onLineItemSelected" id="s2-table"
updateFinished="onListUpdateFinished" items="{mainService>/Bp}" busyIndicatorDelay="{detailView>/lineItemTableDelay}"
itemPress="handleMasterPress" width="100%" >
<headerToolbar>
<OverflowToolbar>
<SearchField id="s2-searchfield-search" tooltip="{i18n>searchToolTip}" liveChange="onSearch" width="auto"></SearchField>
<Button id="s2-table-activate" text="Activate" press="handleActivateBusinessPurpose" enabled="false"/>
<Button id="s2-table-delete" text="{i18n>delete}" press="handleDelete" enabled="false"/>
<Button id="s2-table-add" icon="sap-icon://add" press="handleCreatePress" tooltip="{i18n>addToolTip}"/>
</OverflowToolbar>
</headerToolbar>
<columns>
<Column >
<Text text="{i18n>Name}"/>
</Column>
<Column>
<Text text="{i18n>ApplicationGroupName}"/>
</Column>
<Column demandPopin="true" minScreenWidth="Tablet">
<Text text="{i18n>DataSubjectType}"/>
</Column>
<Column demandPopin="true" minScreenWidth="Tablet">
<Text text="{i18n>LegalEntity}"/>
</Column>
<Column demandPopin="true" minScreenWidth="Tablet">
<Text text="{i18n>Status}"/>
</Column>
</columns>
<items>
<ColumnListItem type="Navigation" press="handleMasterPress">
<!--<ColumnListItem >-->
<cells>
<ObjectIdentifier title="{mainService>BusinessPurposeName}"/>
<ObjectIdentifier text="{mainService>ApplicationGroupName}"/>
<ObjectIdentifier text="{mainService>DataSubjectType}"/>
<ObjectIdentifier text="{mainService>LegalEntityValue}"/>
<ObjectStatus text="{path:'mainService>Status', formatter:'.formatPurposeStatus'}"
state="{path:'mainService>Status', formatter:'.formatStatusColor'}"/>
</cells>
</ColumnListItem>
</items>
</Table>
Please let me know how can I show the selected item highlighted in the table.

First, you are firing 2 event on pressing and handling them with the same function. So, delete itemPress="handleMasterPress" or use another funtion.
Then, handleMasterPress() will be executed by the <ColumnListItem type="Navigation" press="handleMasterPress">
So in the handler, get the source from the event object and pass it to the table in the setSelectedItem() function
handleMasterPress: function(oEvent){
var oColumnListItem = oEvent.getSource();
var oTable = oColumnListItem.getParent();
oTable.setSelectedItem(oColumnListItem);
}
Here a working snippet
// define a new (simple) Controller type
sap.ui.controller("my.own.controller", {
handleMasterPress: function(oEvent){
var oColumnListItem = oEvent.getSource();
console.log(oColumnListItem.getMetadata())
var oTable = oColumnListItem.getParent();
oTable.setSelectedItem(oColumnListItem);
}
});
// instantiate the View
var myView = sap.ui.xmlview({viewContent:jQuery('#view1').html()}); // accessing the HTML inside the script tag above
// create some dummy JSON data
var data = {
WaybillsPlaces: [{
CoNumber: "Item 1",
},{
CoNumber: "Item 2",
},{
CoNumber: "Item 3",
}]
};
// create a Model and assign it to the View
var oModel = new sap.ui.model.json.JSONModel();
oModel.setData(data);
myView.setModel(oModel, "mainService");
// put the View onto the screen
myView.placeAt('content');
<!DOCTYPE html>
<html>
<head>
<meta http-equiv='X-UA-Compatible' content='IE=edge'>
<meta charset="utf-8">
<title>MVC with XmlView</title>
<!-- Load UI5, select "blue crystal" theme and the "sap.m" control library -->
<script id='sap-ui-bootstrap'
src='https://sapui5.hana.ondemand.com/resources/sap-ui-core.js'
data-sap-ui-theme='sap_bluecrystal'
data-sap-ui-libs='sap.m'
data-sap-ui-xx-bindingSyntax='complex'></script>
<!-- DEFINE RE-USE COMPONENTS - NORMALLY DONE IN SEPARATE FILES -->
<!-- define a new (simple) View type as an XmlView
- using data binding for the Button text
- binding a controller method to the Button's "press" event
- also mixing in some plain HTML
note: typically this would be a standalone file -->
<script id="view1" type="sapui5/xmlview">
<mvc:View
controllerName="my.own.controller"
xmlns:mvc="sap.ui.core.mvc"
xmlns="sap.m">
<Panel headerText="Table Panel">
<Table inset="false" noDataText="{i18n>noDataMasterTable}" mode="SingleSelectLeft" selectionChange="onLineItemSelected" id="s2-table"
updateFinished="onListUpdateFinished" items="{mainService>/WaybillsPlaces}" busyIndicatorDelay="{detailView>/lineItemTableDelay}"
width="100%" >
<headerToolbar>
<OverflowToolbar>
<SearchField id="s2-searchfield-search" tooltip="{i18n>searchToolTip}" liveChange="onSearch" width="auto"></SearchField>
<Button id="s2-table-activate" text="Activate" press="handleActivateBusinessPurpose" enabled="false"/>
<Button id="s2-table-delete" text="{i18n>delete}" press="handleDelete" enabled="false"/>
<Button id="s2-table-add" icon="sap-icon://add" press="handleCreatePress" tooltip="{i18n>addToolTip}"/>
</OverflowToolbar>
</headerToolbar>
<columns>
<Column >
<Text text="{i18n>Name}"/>
</Column>
<Column>
<Text text="{i18n>ApplicationGroupName}"/>
</Column>
<Column demandPopin="true" minScreenWidth="Tablet">
<Text text="{i18n>DataSubjectType}"/>
</Column>
<Column demandPopin="true" minScreenWidth="Tablet">
<Text text="{i18n>LegalEntity}"/>
</Column>
<Column demandPopin="true" minScreenWidth="Tablet">
<Text text="{i18n>Status}"/>
</Column>
</columns>
<items>
<ColumnListItem type="Active" press="handleMasterPress">
<!--<ColumnListItem >-->
<cells>
<ObjectIdentifier title="{mainService>CoNumber}"/>
<ObjectIdentifier text="{mainService>CoNumber}"/>
<ObjectIdentifier text="{mainService>CoNumber}"/>
<ObjectIdentifier text="{mainService>CoNumber}"/>
<ObjectStatus text="{path:'mainService>Status', formatter:'.formatPurposeStatus'}"
state="{path:'mainService>Status', formatter:'.formatStatusColor'}"/>
</cells>
</ColumnListItem>
</items>
</Table>
</Panel>
</mvc:View>
</script>
</head>
<body id='content' class='sapUiBody'>
</body>
</html>

Add the following attribute to the items element within the Table element:
items="{
path: '{mainService>/Bp}',
type : 'sap.m.ListType.Active'
}"
Refer
sap.m.ListType.Active
Indicates that the item is clickable via active feedback when item is pressed.
Source: https://openui5.hana.ondemand.com/#/api/sap.m.ListType/overview

Related

How to Bind the Property of an Instance?

I created an array of objects:
buildPayerModel: function() {
return [
new SalesPayer("000", "2333", "033.433", "CHF"),
new SalesPayer("000", "2333", "033.433", "CHF"),
new SalesPayer("000", "2333", "033.433", "CHF")
];
}
and as a model:
this.getView().setModel(this.buildPayerModel(), "Sales")
Now I want to show the data in Table as the following:
<Table id="SalesView" inset="false" items="{ path: '/Sales' }">
<headerToolbar>
<Toolbar>
<Title text="Statistics" level="H2"/>
</Toolbar>
</headerToolbar>
<columns>
<Column width="12em">
<Text text="Payer"/>
</Column>
<Column minScreenWidth="Tablet" demandPopin="true">
<Text text="Name"/>
</Column>
<Column minScreenWidth="Tablet" demandPopin="true" hAlign="End">
<Text text="Net Value"/>
</Column>
<Column hAlign="End">
<Text text="Currency"/>
</Column>
</columns>
<items>
<ColumnListItem>
<cells>
<ObjectIdentifier title="{Sales.id}"/>
<Text text="{Sales.name}"/>
<Text text="{Sales.name}"/>
<Text text="{Sales.name}"/>
</cells>
</ColumnListItem>
</items>
</Table>
How to access the property of the instance?
Your buildPayerModel() is not building a model.
The API setModel awaits a "subclass" of sap.ui.model.Model (not an array), and a corresponding model name ("Sales" in your case).
A short binding syntax looks as follows: "{modelName>/propertyName}".
The binding is defined inside the curly brackets: { ... }
The > is needed when there is a model name.
The / at the beginning (right after possible >) indicates absolute binding syntax
Without / at the beginning --> "{modelName>childPropertyName}" indicates relative binding syntax. It is relative because such binding cannot be resolved without given context.
Given JSONModel for the "Sales", and a SalesPayer instance contains direct properties such as name and id, here is a fix for you:
buildPayerModel: function() {
return new /*sap.ui.model.json.*/JSONModel([
new SalesPayer("000", "2333", "033.433", "CHF"),
new SalesPayer("000", "2333", "033.433", "CHF"),
new SalesPayer("000", "2333", "033.433", "CHF")
]);
},
Somewhere in the same controller:
this.getView().setModel(this.buildPayerModel(), "Sales")
XMLView:
<Table id="SalesView" inset="false" items="{Sales>/}">
<headerToolbar>
<Toolbar>
<Title text="Statistics" level="H2"/>
</Toolbar>
</headerToolbar>
<columns>
<Column width="12em">
<Text text="Payer"/>
</Column>
<Column minScreenWidth="Tablet" demandPopin="true">
<Text text="Name"/>
</Column>
<Column minScreenWidth="Tablet" demandPopin="true" hAlign="End">
<Text text="Net Value"/>
</Column>
<Column hAlign="End">
<Text text="Currency"/>
</Column>
</columns>
<items>
<ColumnListItem>
<cells>
<ObjectIdentifier title="{Sales>id}"/>
<Text text="{Sales>name}"/>
<Text text="{Sales>name}"/>
<Text text="{Sales>name}"/>
</cells>
</ColumnListItem>
</items>
</Table>
setModel() gets a model as first parameter, not a plain JSON Object or Array. Furthermore, the second parameter is the model name, if you name it as "Sales", you must use "Sales>" in your bindings. Then, remember:
1. Use the "/" at the begining when building a path from the root of the model.
2. Avoid the "/" at the begining if you are binding a path relative to another context (Let's say the context of each row of the table)
Try something like this:
<!DOCTYPE html>
<html>
<head>
<meta http-equiv='X-UA-Compatible' content='IE=edge'>
<meta charset="utf-8">
<title>MVC with XmlView</title>
<!-- Load UI5, select "blue crystal" theme and the "sap.m" control library -->
<script id='sap-ui-bootstrap'
src='https://sapui5.hana.ondemand.com/resources/sap-ui-core.js'
data-sap-ui-theme='sap_belize_plus'
data-sap-ui-libs='sap.m'
data-sap-ui-xx-bindingSyntax='complex'></script>
<!-- DEFINE RE-USE COMPONENTS - NORMALLY DONE IN SEPARATE FILES -->
<!-- define a new (simple) View type as an XmlView
- using data binding for the Button text
- binding a controller method to the Button's "press" event
- also mixing in some plain HTML
note: typically this would be a standalone file -->
<script id="view1" type="sapui5/xmlview">
<mvc:View xmlns="sap.m" xmlns:mvc="sap.ui.core.mvc" controllerName="my.own.controller">
<Table id="SalesView" inset="false" items="{ path: 'Sales>/players' }">
<headerToolbar>
<Toolbar>
<Title text="Statistics" level="H2"/>
</Toolbar>
</headerToolbar>
<columns>
<Column width="12em">
<Text text="Payer"/>
</Column>
<Column minScreenWidth="Tablet" demandPopin="true">
<Text text="Name"/>
</Column>
<Column minScreenWidth="Tablet" demandPopin="true" hAlign="End">
<Text text="Net Value"/>
</Column>
<Column hAlign="End">
<Text text="Currency"/>
</Column>
</columns>
<items>
<ColumnListItem>
<cells>
<ObjectIdentifier title="{Sales>id}"/>
<Text text="{Sales>name}"/>
<Text text="{Sales>name}"/>
<Text text="{Sales>name}"/>
</cells>
</ColumnListItem>
</items>
</Table>
</mvc:View>
</script>
<script>
// define a new (simple) Controller type
sap.ui.controller("my.own.controller", {
onInit: function(){
this.getView().setModel(this.buildPayerModel(), "Sales")
},
buildPayerModel: function() {
var oModelData = {
"players": [
{"id": 001, "name": "Michael Jordan"},
{"id": 002, "name": "Kobe Bryant"},
{"id": 003, "name": "LeBron James"}
]
};
var oModel = new sap.ui.model.json.JSONModel(oModelData)
return oModel;
}
});
// instantiate the View
var myView = sap.ui.xmlview({viewContent:jQuery('#view1').html()}); // accessing the HTML inside the script tag above
// put the View onto the screen
myView.placeAt('content');
</script>
</head>
<body id='content' class='sapUiBody'>
</body>
</html>

Popover inside on Table doesn't display data

I have this table component (sap.m.Table):
<Table
inset="false"
items="{
path: '/SelectExpenseDetails'
}" >
<headerToolbar>
<Toolbar>
<Button icon="sap-icon://cause" press="onBack" ariaLabelledBy="Atrás" />
<Button icon="sap-icon://message-information" press="showInfoExpenseItem" ariaLabelledBy="Atrás" />
<Title text="{i18n>GV.APROB.EXPENSES.detail.title}" level="H2"/>
</Toolbar>
</headerToolbar>
<columns>
<Column width="7em" >
<Text text="{i18n>GV.APROB.EXPENSES.detail.concepto.pago}" />
</Column>
<Column
width="4em"
demandPopin="true"
hAlign="Center">
<Text text="{i18n>GV.APROB.EXPENSES.detail.monto}" />
</Column>
<Column width="1.5em"
demandPopin="true"
hAlign="Center">
</Column>
</columns>
<items>
<ColumnListItem>
<ObjectAttribute text="{ExpensesCategory}" />
<ObjectNumber
number="{PlanAmount}"
unit="{masterExpense>/CurrencySymbol}" />
<Button icon="sap-icon://comment" press="showCommentsExpenseDetailItem" class="sapUiTinyMarginBegin"/>
</ColumnListItem>
</items>
</Table>
Function showCommentsExpenseDetailItem display the popover. Popover component is opened but it doen's display data:
Here is code:
showCommentsExpenseDetailItem: function(event){
var popover = sap.ui.xmlfragment("la.incloud.rva.aprobaciones.view.components.popover-comment-item-detail", this);
this.getView().addDependent(popover);
popover.openBy(event.getSource());
}
And this the XML fragment:
<core:FragmentDefinition
xmlns="sap.m"
xmlns:core="sap.ui.core">
<Popover
showHeader="false"
placement="Bottom">
<TextArea value="{Comments}" growing="true" growingMaxLines="4" width="100%"/>
</Popover>
</core:FragmentDefinition>
I supposed that "{Comments}" is the right way of calling poperty of list items.
It seems that I'm wrong...
I assume that the Comments property belongs to an entity of the SelectExpenseDetails entity set. The problem that you are facing is in fact because of an incorrect binding path.
You have attached your popup as a dependent of the view itself. This means that all its relative bindings (like the one for the text area's value) will be resolved based on the binding context of the view. If the view is not bound to anything, the binding will not be resolved.
To go around this, you should bind the popup itself to the correct path, obtained from the item which was pressed. So you should adjust your event handler like so:
showCommentsExpenseDetailItem: function(event){
var popover = sap.ui.xmlfragment("la.incloud.rva.aprobaciones.view.components.popover-comment-item-detail", this);
this.getView().addDependent(popover);
popover.bindElement(event.getSource().getBindingContext().getPath());
popover.openBy(event.getSource());
}
Also, you are creating a new popup each time you press the button, you might want to reuse the popup instead (either create it declaratively in the view or store it as a property of the controller).

SAPUI5 XML View Table Color

I´ve started with my first SAPUI5 application and build a responsive table.
Now I have the requirement to color specific rows depends on a value in the model.
I´m using a XML-View.
Could I define a method in my controller for that? (How it should be working?)
Home.view.xml
<Table id="idMachineTable"
inset="false"
items="{
path: 'machinemodel>/collection'
}">
<headerToolbar>
<Toolbar>
<Title text="Header" level="H2"/>
</Toolbar>
</headerToolbar>
<columns>
<Column
width="12em">
<Text text="Product" />
</Column>
<Column
hAlign="Right">
<Text text="Price" />
</Column>
</columns>
<items>
<ColumnListItem>
<cells>
<ObjectIdentifier
title="{machinemodel>test}"
text="{machinemodel>test}"/>
<Text
text="{machinemodel>test}" />
</cells>
</ColumnListItem>
</items>
</Table>
You can do that with a customdata attribute that creates a dom attribute. Then you can select the rows you want to color via css.
<ColumnListItem>
<customData>
<core:CustomData key="mydata" value="{machinemodel>status}" writeToDom="true" />
</customData>
<cells>
...
<html:style type="text/css">
tr[data-mydata="B"] {
background-color: #faa !important;
}
</html:style>
Full example on jsbin.
I like the answer #schnoebel provided
here is an alternate way (jsbin), in the Items binding define a change handler
items="{
path: 'machinemodel>/collection',
events: {
change: '.onItemsChange'
}
}"
then in the handler add your style class
onItemsChange: function(oEvent){
var oTable = this.byId("idMachineTable");
oTable.getItems().forEach(function(oItem){
var oContext = oItem.getBindingContext("machinemodel");
if (oContext && oContext.getObject().status === 'A'){
oItem.addStyleClass("overdue");
}
});
}

getBindingContext() is undefined

I'm making a little program for a school assignment, but I encounter a problem.
I need to make a program in SAPUI5 that loads JSON data in a table. On each row there is a function (onItemSelected) attached. So when I press on a row, I need to get the ID of the weekday.
This is how the program looks like now:
When I press on a row, it says that my getBindingContext() is undefined.
In my index.html
sap.ui.getCore().attachInit(function(){
var oWeekdagModel = new sap.ui.model.json.JSONModel();
oWeekdagModel.loadData("./model/weekdagen.json");
sap.ui.getCore().setModel(oWeekdagModel, "week");
});
var oResourceModel = new sap.ui.model.resource.ResourceModel({
bundleName : "sap.ui.demo.db.i18n.i18n"
});
sap.ui.getCore().setModel(oResourceModel, "i18n");
new sap.ui.core.mvc.XMLView({
viewName: "sap.ui.demo.db.view.App"
}).placeAt("content");
App.view.xml
<mvc:View
xmlns:l="sap.ui.layout"
xmlns:mvc="sap.ui.core.mvc"
xmlns="sap.m"
controllerName="sap.ui.demo.db.controller.App"
>
<Table id="idWeekdagenTable"
inset="false"
items="{week>/weekdays}"
>
<headerToolbar>
<!-- ... -->
</headerToolbar>
<columns>
<Column width="20%">
<Text text="Id" />
</Column>
<Column width="20%">
<Text text="Weekdag" />
</Column>
<Column width="20%">
<Text text="Aantal gewoon eten" />
</Column>
</columns>
<items>
<ColumnListItem
press=".onItemSelected"
type="Active"
>
<Text id="id" text="{week>id}" />
<Text id="day" text="{week>day}" />
<Text text="{week>no_meals}" />
</ColumnListItem>
</items>
</Table>
<Table id="idMaaltijdenTable"
inset="false"
items="{maaltijd>/meals}"
>
<headerToolbar>
<!-- ... -->
</headerToolbar>
<columns>
<Column width="20%">
<Text text="Maaltijd" />
</Column>
<Column width="20%">
<Text text="Descriptie"/>
</Column>
</columns>
<items>
<ColumnListItem
press=".onItemSelected"
type="Active"
>
<Text text="{maaltijd>MealNo}" />
<Text text="{maaltijd>items}" />
</ColumnListItem>
</items>
</Table>
</mvc:View>
App.controller.js
sap.ui.define([
"sap/ui/core/mvc/Controller"
], function (Controller){
"use strict";
return Controller.extend("sap.ui.demo.db.controller.App", {
onInit: function() {
var oWeekdagModel = new sap.ui.model.json.JSONModel();
oWeekdagModel.loadData("weekdagen.json");
//binding op view
sap.ui.getCore().setModel(oWeekdagModel);
},
onItemSelected: function(oEvent) {
var oItem, oCtx;
oItem = oEvent.getSource();
oCtx = oItem.getBindingContext();
alert(oCtx); // is undefined
}
});
});
You can pull out the day's ID from the model using binding path. Here is a relevant part of your onItemSelected() function:
...
oCtx = oItem.getBindingContext();
var oPressedItem = sap.ui.getCore().getModel().getProperty(oCtx.getPath());
...
and then oPressedItem.id will give you the ID of the day from the top table and oPressedItem.dayId - from the bottom table.
Here is a working example.

Icon in table incompatible with mergeDuplicates="true"

I have a Table and I want to merge duplicates in the first column:
<Column mergeDuplicates="true">
<Text text="Society"/>
</Column>
<Column>
<Text text="Ref2"/>
</Column>
...
I want to have a complex element in the first column: An icon that shows the flag of society.
<items>
<ColumnListItem>
<cells>
<StandardListItem title="{model>society/description}"
icon="{path: 'model>society/code',
formatter: 'ui5bp.Formatter.iconGeneral'}"/>
<!--<Text text="{model>society/description}"/>-->
<Text text="{model>ref2}"/>
</cells>
</ColumnListItem>
</items>
But if I set the StandardListItem instead the simple text the mergeDuplicates="true" does not work.
Are complex column items and the mergeDuplicates property incompatible?
Now StandardListItem has this result:
How can I create a correct "MyCustomColumnListItem" to show the flag on the left and descriprion on the right without space up and down?
The data in your example is not mergeDuplicate ready (from what you show, nothing would be merged), but I took a guess and set up some test data that might be similar. You can perhaps look at using an ObjectAttribute which has an icon and a text, as shown in this snippet.
sap.ui.xmlview("main", {
viewContent: jQuery("#view-main").html()
})
.setModel(new sap.ui.model.json.JSONModel({
records : [
{ icon : "http://www.flags.net/images/smallflags/ANTA0001.GIF", text : "Delete", comment : "delete" },
{ icon : "http://www.flags.net/images/smallflags/ANBA0001.GIF", text : "Delete", comment : "negative" },
{ icon : "http://www.flags.net/images/smallflags/ANDR0001.GIF", text : "Remove", comment : "sys-minus" }
]
}))
.placeAt("content");
<script src="https://openui5.hana.ondemand.com/resources/sap-ui-core.js" id="sap-ui-bootstrap" data-sap-ui-libs="sap.m" data-sap-ui-theme="sap_bluecrystal" data-sap-ui-xx-bindingSyntax="complex"></script>
<div id="content"></div>
<script id="view-main" type="ui5/xmlview">
<mvc:View
displayBlock="true"
xmlns:mvc="sap.ui.core.mvc"
xmlns="sap.m">
<Table
items="{/records}">
<columns>
<Column mergeDuplicates="true"><Label text="Icon" /></Column>
<Column><Label text="Comment" /></Column>
</columns>
<items>
<ColumnListItem>
<cells>
<ObjectStatus
text="{text}"
icon="{icon}" />
<Text text="{comment}" />
</cells>
</ColumnListItem>
</items>
</Table>
</mvc:View>
</script>
Not sure if a custom control or ListItem will work...
As an alternative, you could also use two columns, each set with mergeDuplicates="true" and display an Image and Text separately. That should definitely work
I.e.:
<Table id="tbl" items="{model>/yourData}">
<columns>
<Column mergeDuplicates="true" mergeFunctionName="getSrc">
<Text text="Society" />
</Column>
<Column mergeDuplicates="true" />
</columns>
<items>
<ColumnListItem>
<cells>
<Image src="{model>society/flagImg}"/>
<Text text="{model>society/description}" />
</cells>
</ColumnListItem>
</items>
</Table>