Table grouping resets selected values when adding new item - sapui5

Here we have a very basic table with an Add button and grouping activated. When I select values for the existing items and then press the button to add a new row, my selected values are getting reset, but without grouping it works fine. Am I doing something wrong or is this a bug?
sap.ui.getCore().attachInit(() => sap.ui.require([
"sap/ui/core/mvc/XMLView",
"sap/ui/model/json/JSONModel" // sample model. Can be also an ODataModel.
], async (XMLView, JSONModel) => {
"use strict";
const control = await XMLView.create({
definition: `<mvc:View xmlns="sap.m" xmlns:mvc="sap.ui.core.mvc">
<Table items="{
path: '/tableItems',
sorter: { path : 'group', group: true }
}">
<headerToolbar>
<OverflowToolbar>
<Title text="Test Table" />
<ToolbarSpacer/>
<Button id="addButton" text="Add" type="Emphasized" />
</OverflowToolbar>
</headerToolbar>
<columns>
<Column width="20rem">
<Label text="col0"/>
</Column>
<Column width="20rem">
<Label text="col1"/>
</Column>
</columns>
<ColumnListItem vAlign="Middle">
<Text text="{text}" />
<Select forceSelection="false" width="100%" xmlns:core="sap.ui.core">
<core:Item text="test1" key="test1" />
<core:Item text="test2" key="test2" />
<core:Item text="test3" key="test3" />
<core:Item text="test4" key="test4" />
</Select>
</ColumnListItem>
</Table>
</mvc:View>`,
afterInit: function() {
this.byId("addButton").attachPress(onPressAdd, this);
function onPressAdd() {
const oModel = this.getModel();
const aItems = oModel.getProperty("/tableItems");
const newItems = aItems.concat({
group: "3",
text: "3-1",
key: "3-1",
});
oModel.setProperty("/tableItems", newItems);
}
},
models: new JSONModel({
number: 0,
tableItems: [
{
group: "1",
text: "1-1",
key: "1-1",
},
{
group: "1",
text: "1-2",
key: "1-2",
},
{
group: "2",
text: "2-1",
key: "2-1",
},
{
group: "2",
text: "2-2",
key: "2-2",
},
],
}),
});
control.placeAt("content");
}));
<script id="sap-ui-bootstrap"
src="https://openui5.hana.ondemand.com/1.82.2/resources/sap-ui-core.js"
data-sap-ui-libs="sap.ui.core,sap.m"
data-sap-ui-theme="sap_fiori_3"
data-sap-ui-compatversion="edge"
data-sap-ui-async="true"
data-sap-ui-excludejquerycompat="true"
data-sap-ui-xx-waitfortheme="init"
></script>
<body id="content" class="sapUiBody sapUiSizeCompact"></body>

Set the growing="true" to the sap.m.Table.
This enables GrowingEnablement internally which prevents rerendering the entire ListBase (Table) when the target gets invalidated. Only the necessary item will be then appended to the table.
Generally, in order to optimize the rendering behavior, it's always a good practice to..:
Enable the growing property if the table / list is editable, shrinkable, or expandable.
Add key: <propertyName with unique values> to the ListBinding info object to benefit from the Extended Change Detection if the model is a client-side model such as JSONModel. With an ODataModel, the key is automatically added by the framework.
<Table xmlns="sap.m"
growing="true"
items="{
path: 'myModel>/myCollection',
key: <propertyName>, (if 'myModel' is not an ODataModel)
sorter: ...
}"
>

Related

Sort table by certain parts of string only

The sorting works basically fine using the sorter. One column is the full name (e.g. "Steve Jobs"). I have only the full name in that entity set but I want to sort the entries by the last name (last word of the full name) when clicking the full name column header. Is there some way to do this?
You'll need to define a custom comparator for the sorter which applies only if all the entities are available client-side, for example, by having the operationMode set to 'Client' when defining the OData list binding.API
sap.ui.getCore().attachInit(() => sap.ui.require([
"sap/ui/model/odata/v2/ODataModel",
"sap/ui/core/mvc/XMLView",
"sap/ui/model/json/JSONModel",
"sap/ui/model/Sorter",
], (ODataModel, XMLView, JSONModel, Sorter) => {
"use strict";
const odataModel = new ODataModel({
serviceUrl: [
"https://cors-anywhere.herokuapp.com/",
"https://services.odata.org/V2/Northwind/Northwind.svc/",
].join(""),
tokenHandling: false,
preliminaryContext: true,
});
Promise.all([
odataModel.metadataLoaded(),
sap.ui.getCore().loadLibrary("sap.m", true),
]).then(() => XMLView.create({
definition: `<mvc:View xmlns:mvc="sap.ui.core.mvc"
xmlns="sap.m"
xmlns:core="sap.ui.core"
height="100%"
>
<App>
<Page showHeader="false">
<Table id="myResponsiveTable"
items="{
path: '/Customers',
parameters: {
select: 'CustomerID, ContactName',
operationMode: 'Client'
}
}"
>
<columns>
<Column id="customerIdColumn"
sortIndicator="{colCustomerId>/sortOrder}"
width="33%"
>
<Text text="Customer ID">
<customData>
<core:CustomData
key="sorterPath"
value="CustomerID"
/>
</customData>
</Text>
</Column>
<Column id="fullNameColumn"
sortIndicator="{colFullName>/sortOrder}"
width="auto"
>
<Text text="Full Name">
<customData>
<core:CustomData
key="sorterPath"
value="ContactName"
/>
</customData>
</Text>
</Column>
</columns>
<ColumnListItem>
<Text text="{CustomerID}" />
<Text text="{ContactName}" />
</ColumnListItem>
</Table>
</Page>
</App>
</mvc:View>`,
afterInit: function() { // === onInit
const table = this.byId("myResponsiveTable");
activateColumnPress(table, onColumnPress);
},
models: {
undefined: odataModel,
colCustomerId: new JSONModel({ sortOrder: "None" }),
colFullName: new JSONModel({ sortOrder: "None" }),
}
}).then(view => view.placeAt("content")));
function activateColumnPress(table, handler) {
// Making columns clickable for the demo
table.bActiveHeaders = true;
table.onColumnPress = col => handler(table, col);
}
function onColumnPress(table, pressedCol) {
table.getColumns()
.filter(col => !(col.getSortIndicator() === pressedCol.getSortIndicator()))
.map(col => col.setSortIndicator("None"));
table.getBinding("items").sort(createSorter(pressedCol));
}
function createSorter(column) {
return column.getHeader().data("sorterPath") === "ContactName"
? createFullNameSorter(column, toggleSort(column.getModel("colFullName")))
: createCustomerIdSorter(column, toggleSort(column.getModel("colCustomerId")));
}
function toggleSort(colModel) {
const descending = colModel.getProperty("/sortOrder") !== "Ascending";
colModel.setProperty("/sortOrder", descending ? "Ascending" : "Descending");
return !descending;
}
function createFullNameSorter(column, descending) {
const comparator = (a, b) => a.split(" ").pop().localeCompare(b.split(" ").pop());
return new Sorter("ContactName", descending, false, comparator);
}
function createCustomerIdSorter(column, descending) {
return new Sorter("CustomerID", descending);
}
}));
<script id="sap-ui-bootstrap"
src="https://openui5.hana.ondemand.com/resources/sap-ui-core.js"
data-sap-ui-libs="sap.ui.core"
data-sap-ui-async="true"
data-sap-ui-compatversion="edge"
data-sap-ui-theme="sap_belize"
data-sap-ui-xx-waitfortheme="true"
></script>
<body id="content" class="sapUiBody sapUiSizeCompact" style="height: 100%;"></body>
Btw: the "Client" operation mode currently doesn't fetch all entities if the service has server-side paging implemented.
As you can see in the example above, the Sorter constructor can handle custom comparator which will be invoked when the sort method is called. For comparing last parts of the full names, you can define the comparator like this:
function compare(fullName_a, fullName_b) {
const lastPart_a = fullName_a.split(" ").pop();
const lastPart_b = fullName_b.split(" ").pop();
return lastPart_a.localeCompare(lastPart_b); // 0 if equal. Otherwise a negative or positive number
}

Deselect Radiobuttons when leaving the view via cancel button

I have a table(sap.m.table) with radiobutton control in the first column.
The table shows different "prices" from which the user should be able to choose only one. My problem is, when i use the cancel button it should delete all selections made (in dropdowns, datefilter, etc.). It works for every control except radiobutton.
<ColumnListItem> <cells>
<RadioButton id="radiobutton" groupName="tablebuttons" select="onSelect"/>.....
When i leave the view with the cancel button and then open it again in the same session, the previous selected radiobutton is still selected.
I cant find any method to set it to unselected. When i use this.getView().byId("radiobutton").getSelected()
it always gives back "false".
Is it because there is one button for each table row and i only select (the first?) one? If so, how can i search all button for the selected one and deselect it?
You must have added id="radiobutton" to the template list item which is used for aggregation binding. That is why calling byId("radiobutton") does not return any rendered radio button but the template instance. If you check the IDs of the radio buttons from the HTML document, you'll notice that they all contain the generated prefix __clone0, __clone1, etc.
I can't find any method to set it to unselected.
To deselect a radio button, use:
In case of RadioButton: .setSelected(false)
In case of RadioButtonGroup: .setSelectedIndex(-1)
But you might not even need any sap.m.RadioButton to add manually to the table. Since sap.m.Table extends from sap.m.ListBase, it can have a radio button in each list item via mode="SingleSelectLeft". Here is a demo:
sap.ui.getCore().attachInit(() => sap.ui.require([
"sap/ui/model/json/JSONModel"
], JSONModel => sap.ui.xmlview({
async: true,
viewContent: `<mvc:View
xmlns:mvc="sap.ui.core.mvc"
xmlns="sap.m"
controllerName="MyController"
>
<Table
mode="SingleSelectLeft"
selectionChange=".onSelectionChange"
includeItemInSelection="true"
items="{prices>/}">
<columns>
<Column>
<Text text="Price"/>
</Column>
<Column>
<Text text="Foo"/>
</Column>
</columns>
<items>
<ColumnListItem selected="{prices>selected}" >
<ObjectNumber number="{prices>price}" />
<Text text="bar" />
</ColumnListItem>
</items>
</Table>
<Button
class="sapUiTinyMargin"
text="Deselect"
type="Emphasized"
press=".onResetPress"
/>
</mvc:View>`,
controller: sap.ui.controller("MyController", {
onInit: function() {
const model = new JSONModel(this.createModelData());
this.getView().setModel(model, "prices");
},
onResetPress: function() {
const model = this.getView().getModel("prices");
model.setProperty("/", this.createModelData());
},
createModelData: () => [{
price: 111.01,
}, {
price: 222.0245,
}, {
price: 333,
}],
}),
}).loaded().then(view => view.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-preload="async"
data-sap-ui-theme="sap_belize"
data-sap-ui-compatVersion="edge"
data-sap-ui-xx-waitForTheme="true"
></script><body id="content" class="sapUiBody sapUiSizeCompact"></body>
IMO, you should use a model to set/reset values and not called the setter function of control. here is an example of using MVC
http://jsbin.com/zijajas/edit?html,js,output
<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta charset="UTF-8">
<title>MVC</title>
<script id="sap-ui-bootstrap" type="text/javascript"
src="https://sapui5.hana.ondemand.com/resources/sap-ui-core.js"
data-sap-ui-theme="sap_bluecrystal"
data-sap-ui-libs="sap.m,sap.ui.table"
data-sap-ui-xx-bindingSyntax="complex">
</script>
<script id="oView" type="sapui5/xmlview">
<mvc:View height="100%" controllerName="myView.Template"
xmlns="sap.m"
xmlns:core="sap.ui.core"
xmlns:mvc="sap.ui.core.mvc"
xmlns:table="sap.ui.table">
<table:Table id="Table1" rows="{/}"
selectionMode="None">
<table:title>
<Button icon="sap-icon://reset" press="reset" />
</table:title>
<table:columns>
<table:Column>
<Label text="Employee name"/>
<table:template>
<Text text="{name}" ></Text>
</table:template>
</table:Column>
<table:Column>
<Label text="Company"/>
<table:template>
<Text text="{company}"></Text>
</table:template>
</table:Column>
<table:Column>
<Label text="Radio"/>
<table:template>
<RadioButtonGroup selectedIndex="{radio}">
<RadioButton text="no" />
<RadioButton text="yes" />
</RadioButtonGroup>
</table:template>
</table:Column>
<table:Column>
<Label text="Bonus"/>
<table:template>
<Input value="{bonus}" />
</table:template>
</table:Column>
</table:columns>
</table:Table>
</mvc:View>
</script>
</head>
<body class="sapUiBody sapUiSizeCompact" role="application">
<div id="content"></div>
</body>
</html>
controller
sap.ui.define([
'jquery.sap.global',
'sap/ui/core/mvc/Controller',
'sap/ui/model/json/JSONModel'
], function(jQuery, Controller, JSONModel) {
"use strict";
var oController = Controller.extend("myView.Template", {
onInit: function(oEvent) {
this.getView().setModel(new JSONModel([{
name : "John",
company: "apple inc",
radio: 0,
bonus: "0"
}, {
name : "Mary",
company: "abc inc",
radio: 0,
bonus: "0"
},
]));
},
reset: function() {
var oModel = this.getView().getModel();
oModel.getProperty('/').forEach(function(item) {
item.radio = 0;
item.bonus = 0;
});
oModel.refresh();
}
});
return oController;
});
var oView = sap.ui.xmlview({
viewContent: jQuery('#oView').html()
});
oView.placeAt('content');

Add a New Item to a Table / List

I have a fragment / view written in XML which contains a simple table with some columns and one ColumnListItem:
<m:Table id="CorrectiveActionsTable">
<m:columns>
<m:Column>
<m:Text text="Lfd. Nr"/>
</m:Column>
<m:Column width="30%">
<m:Text text=""/>
</m:Column>
<m:Column>
<m:Text text="gefordert von"/>
</m:Column>
<m:Column>
<m:Text text="Durchführungsverantwortung"/>
</m:Column>
<m:Column>
<m:Text text="Planungstermin"/>
</m:Column>
<m:Column>
<m:Text text="IST-Termin"/>
</m:Column>
</m:columns>
<m:ColumnListItem id="ListItem_00">
<m:Text text="1"/>
<m:TextArea
value="senf"
rows="6"
width="100%"
/>
<m:Input placeholder="bla"/>
<m:Input placeholder="bla2"/>
<m:DatePicker placeholder="bla3"/>
<m:DatePicker placeholder="bla4"/>
</m:ColumnListItem>
</m:Table>
<m:HBox>
<m:Button
text="Add Button"
visible="true"
press="onAddButton"
icon="sap-icon://add"
/>
</m:HBox>
The Button should be used to add a new ColumnListItem to the Table.
I think I should write the onAddButton function in the controller but I don't know where to start.
For now, my controller looks like this:
sap.ui.define([
"sap/ui/core/mvc/Controller",
"sap/m/ColumnListItem",
"sap/m/Text",
"sap/m/TextArea",
"sap/m/Input",
"sap/m/DatePicker"
], function(Controller, ColumnListItem, Text, TextArea, Input, DatePicker) {
"use strict";
return Controller.extend("...", {
onAddButton: function(oEvent) {
var columnListItemNewLine = new ColumnListItem({
cells: [
new Text({
text: "1"
}),
new TextArea({
value: "senf",
rows: "6",
width: "30%"
}),
new Input({
type: "text",
placeholder: "bla"
}),
new Input({
type: "text",
placeholder: "bla2"
}),
new DatePicker({
placeholder: "bla3"
}),
new Datepicker({
placeholder: "bla4"
})
]
});
this._oTable.addItem(columnListItemNewLine);
}
});
});
And I'm pretty sure there is a better way to do this than my approach.
Resolution
Bind the collection of data to the aggregation of table (e.g. <items>).
Add a new entry via the model (instead of to the UI directly) when the user clicks on Add.
Thanks to the aggregation binding, UI5 will create a new sap.m.ColumnListItem for you and you did not break the MVC pattern. Here are some examples, using..:
v2.ODataModel
Call createEntry and later submitChanges to send it to backend.
Demo: plnkr.co/F3t6gI8TPUZwCOnA (Click on the Add button to create a new "Flight").
Documentation: OData V2 - Creating Entities
v4.ODataModel
See the documentation topic OData V4 - Creating an Entity.
JSONModel
globalThis.onUI5Init = () => sap.ui.require([
"sap/ui/core/mvc/XMLView",
"sap/ui/model/json/JSONModel",
], async (XMLView, JSONModel) => {
"use strict";
const control = await XMLView.create({
definition: document.getElementById("myxmlview").textContent,
models: new JSONModel({
myArray: [],
}),
});
control.placeAt("content");
});
function onAddItemPress(event) {
const model = event.getSource().getModel();
const newArray = model.getProperty("/myArray").concat({
id: globalThis.crypto.randomUUID(),
text: "My New Item",
});
model.setProperty("/myArray", newArray, null, true);
}
html, body { height: 100%; }
body { margin: 0; }
<script defer id="sap-ui-bootstrap"
src="https://sdk.openui5.org/resources/sap-ui-core.js"
data-sap-ui-oninit="onUI5Init"
data-sap-ui-libs="sap.ui.core,sap.m"
data-sap-ui-theme="sap_horizon"
data-sap-ui-async="true"
data-sap-ui-compatversion="edge"
data-sap-ui-excludejquerycompat="true"
data-sap-ui-xx-waitfortheme="init"
></script>
<script id="myxmlview" type="text/xml">
<mvc:View xmlns:mvc="sap.ui.core.mvc" height="100%" displayBlock="true">
<Page xmlns="sap.m" title="My Items ({= ${/myArray}.length})">
<headerContent>
<Button text="Add" type="Emphasized" press="onAddItemPress" />
</headerContent>
<Table xmlns="sap.m"
growing="true"
items="{
path: '/myArray',
templateShareable: false,
key: 'id'
}">
<columns>
<Column>
<Text text="UUID" />
</Column>
<Column>
<Text text="Text" />
</Column>
</columns>
<ColumnListItem>
<Text text="{id}" />
<Text text="{text}" />
</ColumnListItem>
</Table>
</Page>
</mvc:View>
</script>
<body id="content" class="sapUiBody sapUiSizeCompact">
</body>
For client-side models such as JSONModel, calling setProperty is sufficient. DO NOT use push or modify the internal model reference directly.
⚠️ Note
Do not modify the control aggregation manually, e.g. via myListControl.addItem, after binding the aggregation (items). Instead, apply the changes from the model as described above.
Try with this code below
onAddButton: function(oEvent){
var columnListItemNewLine = new sap.m.ColumnListItem({
cells:[
new sap.m.Text({text: "1"}),
new sap.m.TextArea({value: "senf", rows: "6", width:
"30%"}),
new sap.m.Input({type: "text", placeholder: "bla"}),
new sap.m.Input({type: "text", placeholder: "bla2"}),
new sap.m.DatePicker({placeholder: "bla3"}),
new sap.m.Datepicker({placeholder: "bla4"})
]
});
this._oTable.removeAllItems();
this._oTable.addItem(columnListItemNewLine);
}

Correct usage for filters when binding items via XMLView

Using sap.m.Select, I have a similar code as this below:
<m:Select
selectedKey='{state}'
items="{
path: 'states>/content',
sorter: {
path: 'name'
}
}">
<core:Item key="{states>id}" text="{states>name}" />
</m:Select>
As want to be able to filter states by country when it is selected in another input, so, I'm trying using filters, which is defined in documentation in:
https://sapui5.netweaver.ondemand.com/docs/api/symbols/sap.ui.base.ManagedObject.html#bindAggregation
https://sapui5.netweaver.ondemand.com/#docs/api/symbols/sap.ui.model.Filter.html
The problem is that I couldn't find anywhere (docs, google, SO, source code, examples, tests) showing how to correctly use it. I tried these 2 ways with no success:
<m:Select
selectedKey='{state}'
items="{
path: 'states>/content',
sorter: {
path: 'name'
},
filters: [{
path: 'countryId',
operator: 'EQ',
value1: '10' // just example
]}
}">
<core:Item key="{states>id}" text="{states>name}" />
</m:Select>
and
# View
<m:Select
selectedKey='{state}'
items="{
path: 'states>/content',
sorter: {
path: 'name'
},
filters: ['.filterByCountry'}
}">
<core:Item key="{states>id}" text="{states>name}" />
</m:Select>
# Controller
...
filterByCountry: new sap.ui.model.Filter({
path: 'countryId',
operator: 'EQ',
value1: '10'
}),
...
Anybody knows the proper way to use it?
Here is how filters work in XML Views - see the 2 examples below I coded for you (use the jsbin links if they don't run here on stackoverflow). They both use the Northwind OData service. As you will see it's pretty much straight forward:
<Select
items="{
path : '/Orders',
sorter: {
path: 'OrderDate',
descending: true
},
filters : [
{ path : 'ShipCountry', operator : 'EQ', value1 : 'Brazil'}
]
}">
Of course, you can add multiple filters as well (see the second example below).
However, keep in mind that the filters are declared in the XMLView. Unfortunately, UI5 is currently not so dynamic to allow changing such filters defined in an XMLView dynamically by only using the binding syntax in the XMLView. Instead you would need some piece of JavaScript code. In your case you could listen for the change event of the other field. In the event handler you would then simply create a new Filter and apply it:
var oSelect, oBinding, aFilters, sShipCountry;
sFilterValue = ...; // I assume you can get the filter value from somewhere...
oSelect = this.getView().byId(...); //get the reference to your Select control
oBinding = oSelect.getBinding("items");
aFilters = [];
if (sFilterValue){
aFilters.push( new Filter("ShipCountry", FilterOperator.Contains, sFilterValue) );
}
oBinding.filter(aFilters, FilterType.Application); //apply the filter
That should be all you need to do. The examples below do not use any JavaScript code for the filter, but I guess you get the idea.
1. Example - Select box:
Run the code: https://jsbin.com/wamugexeda/edit?html,output
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>SAPUI5 single file template | nabisoft</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-libs="sap.m"
data-sap-ui-bindingSyntax="complex"
data-sap-ui-compatVersion="edge"
data-sap-ui-preload="async"></script>
<!-- use "sync" or change the code below if you have issues -->
<!-- XMLView -->
<script id="myXmlView" type="ui5/xmlview">
<mvc:View
controllerName="MyController"
xmlns="sap.m"
xmlns:core="sap.ui.core"
xmlns:mvc="sap.ui.core.mvc">
<Select
items="{
path : '/Orders',
sorter: {
path: 'OrderDate',
descending: true
},
filters : [
{ path : 'ShipCountry', operator : 'EQ', value1 : 'Brazil'}
]
}">
<core:Item key="{OrderID}" text="{OrderID} - {ShipName}" />
</Select>
</mvc:View>
</script>
<script>
sap.ui.getCore().attachInit(function () {
"use strict";
//### Controller ###
sap.ui.define([
"sap/ui/core/mvc/Controller",
"sap/ui/model/odata/v2/ODataModel"
], function (Controller, ODataModel) {
"use strict";
return Controller.extend("MyController", {
onInit : function () {
this.getView().setModel(
new ODataModel("https://cors-anywhere.herokuapp.com/services.odata.org/V2/Northwind/Northwind.svc/", {
json : true,
useBatch : false
})
);
}
});
});
//### THE APP: place the XMLView somewhere into DOM ###
sap.ui.xmlview({
viewContent : jQuery("#myXmlView").html()
}).placeAt("content");
});
</script>
</head>
<body class="sapUiBody">
<div id="content"></div>
</body>
</html>
2. Example - Table:
Run the code: https://jsbin.com/yugefovuyi/edit?html,output
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>SAPUI5 single file template | nabisoft</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-libs="sap.m"
data-sap-ui-bindingSyntax="complex"
data-sap-ui-compatVersion="edge"
data-sap-ui-preload="async"></script>
<!-- use "sync" or change the code below if you have issues -->
<!-- XMLView -->
<script id="myXmlView" type="ui5/xmlview">
<mvc:View
controllerName="MyController"
xmlns="sap.m"
xmlns:core="sap.ui.core"
xmlns:mvc="sap.ui.core.mvc">
<Table
id="myTable"
growing="true"
growingThreshold="10"
growingScrollToLoad="true"
busyIndicatorDelay="0"
items="{
path : '/Orders',
sorter: {
path: 'OrderDate',
descending: true
},
filters : [
{ path : 'ShipCity', operator : 'Contains', value1 : 'rio'},
{ path : 'ShipName', operator : 'EQ', value1 : 'Hanari Carnes'}
]
}">
<headerToolbar>
<Toolbar>
<Title text="Orders of ALFKI"/>
<ToolbarSpacer/>
</Toolbar>
</headerToolbar>
<columns>
<Column>
<Text text="OrderID"/>
</Column>
<Column>
<Text text="Order Date"/>
</Column>
<Column>
<Text text="To Name"/>
</Column>
<Column>
<Text text="Ship City"/>
</Column>
</columns>
<items>
<ColumnListItem type="Active">
<cells>
<ObjectIdentifier title="{OrderID}"/>
<Text
text="{
path:'OrderDate',
type:'sap.ui.model.type.Date',
formatOptions: { style: 'medium', strictParsing: true}
}"/>
<Text text="{ShipName}"/>
<Text text="{ShipCity}"/>
</cells>
</ColumnListItem>
</items>
</Table>
</mvc:View>
</script>
<script>
sap.ui.getCore().attachInit(function () {
"use strict";
//### Controller ###
sap.ui.define([
"sap/ui/core/mvc/Controller",
"sap/ui/model/odata/v2/ODataModel"
], function (Controller, ODataModel) {
"use strict";
return Controller.extend("MyController", {
onInit : function () {
this.getView().setModel(
new ODataModel("https://cors-anywhere.herokuapp.com/services.odata.org/V2/Northwind/Northwind.svc/", {
json : true,
useBatch : false
})
);
}
});
});
//### THE APP: place the XMLView somewhere into DOM ###
sap.ui.xmlview({
viewContent : jQuery("#myXmlView").html()
}).placeAt("content");
});
</script>
</head>
<body class="sapUiBody">
<div id="content"></div>
</body>
</html>

Get selected item from sap.m.Select from a sapui5 table column

I am using sap.m.Table, where I have 3 columns, as sap.m.text, sap.m.setect and the last one is button.
My model code
var oModel = new sap.ui.model.odata.OData("url");
sap.ui.getCore().setModel(oModel ,"data");
Table view code(cells)
var oTemplate = new sap.m.ColumnListItem({
cells : [
new sap.m.Text({
text: "{data>Address}"
}),
new sap.m.Select({
id:"sel",
items: {
path: "data>/OPERATORS", // this is a diffent table
template: new sap.ui.core.Item({
text: "{data>firstName} {data>lastName}"
})
},
forceSelection: false
}),
new sap.m.Button({
text : "Start",
press : [oController.onPressStart, oController]
})
]
});
oTable.bindItems("data>/ORDR", oTemplate); //differnt table
Working fine, getting all required data on the specific table.(Notice first column is coming from ORDR table and second one is coming from OPERATORS table).
Now on button click I wanted the specific row data. My code as follows -
onPressStart : function(oEvent){
var obj = oEvent.getSource().getBindingContext("data").getObject();
},
"obj" gives me ORDR table row objects(where I pressed the button).
Now I also want the value I will select on the dropdown box. How to get it.
Please suggest, Thank you
JSbin Link - http://jsbin.com/quhomoloqo/edit?html,console,output
See this working example:
Please note how (for the sake of this question) created two models:
One named 'orig' which holds your original OPERATOR and ODRD data, and
one named 'data' which holds a copy of the OPERATOR data, with an added Address property.
See the view code on how the two models are used (the new one for the table, the old one for populating the dropdown)
sap.ui.controller("view1.initial", {
onInit : function(oEvent) {
},
onAfterRendering : function() {
// your original model
var oModel = new sap.ui.model.json.JSONModel();
var oData = {
"ODRD":[
{"Address":"UK"},
{"Address":"US"}
],
"OPERATORS":[
{"firstName":"a","lastName":"b"},
{"firstName":"c","lastName":"d"}
]
};
oModel.setData(oData);
this.getView().setModel(oModel, "orig");
// the model you actually need
var oNewModel = new sap.ui.model.json.JSONModel();
var oNewData = oData.OPERATORS.map(function(result) {
return {
firstName : result.firstName,
lastName : result.lastName,
keyToAddress : null
}
})
oNewModel.setData({
"OPERATORS" : oNewData
});
this.getView().setModel(oNewModel, "data");
},
showData : function(oEvent) {
alert(JSON.stringify(oEvent.getSource().getBindingContext("data").getObject()));
}
});
sap.ui.xmlview("main", {
viewContent: jQuery("#view1").html()
})
.placeAt("uiArea");
<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-xx-bindingSyntax="complex"
data-sap-ui-libs="sap.m"></script>
<div id="uiArea"></div>
<script id="view1" type="ui5/xmlview">
<mvc:View
controllerName="view1.initial"
xmlns="sap.m"
xmlns:core="sap.ui.core"
xmlns:mvc="sap.ui.core.mvc" >
<Table id="tbl" items="{data>/OPERATORS}">
<columns>
<Column>
<Text text="First" />
</Column>
<Column>
<Text text="Last" />
</Column>
<Column>
<Text text="ODRD" />
</Column>
<Column>
<Text text="" />
</Column>
</columns>
<items>
<ColumnListItem>
<cells>
<Input value="{data>firstName}" />
<Input value="{data>lastName}" />
<Select items="{orig>/ODRD}" selectedKey="{data>keyToAddress}">
<items>
<core:ListItem key="{orig>Address}" text="{orig>Address}" />
</items>
</Select>
<Button text="Show data" press="showData" />
</cells>
</ColumnListItem>
</items>
</Table>
</mvc:View>
</script>