SAPUI5 How to display only the first element of an expanded entitySet in table - sapui5

I am currently using an entityset(i.e, "SolutioningVersions") in my smarttable which i have expanded in controler using
var mBindingParams = oEvent.getParameter("bindingParams");
mBindingParams.parameters["expand"] = "TEAMID/TEAMDETAILS,SOLREQ,SOLESTIMATE";
I have bound it in my table using
<VBox items="{ path: 'SOLESTIMATE', templateShareable:false }">
<Text text="{WBSVARIANT}"/>
</VBox>
But "SOLESTIMATE" is having array of objects & i want to show only "WBSVARIANT" from it 1st object in array.
Currently it shows me like this in single cell of table
enter image description here
I want to show only 1st element of this array. Also, i dont want to filter array here as objects are not unique.

A formatter can help you:
<Text text="{path: 'WBSVARIANT', formatter: '.formatText'}"/>
function formatText(items){
return items[0];
}

Related

SAPUI5 sap.m.list in a popover is emtpy when populated using bindElement

I have a table (sap.m.table) with different columns. One columns contains a link and when the user clicks on the link a popover fragment opens and shows some details in a list (sap.m.list). The data is coming from an oData Service. One Entity feeds the table and through a navigation property the data for the popover is fetched.
I have a working example for this scenario where I create the the list template in the controller. But I believe that this should also be possible just by xml and a bindElement in the controller. What is the mistake in my second scenario?
First Scenario (which is working fine):
Popover XML:
<Popover
showHeader="false"
contentWidth="320px"
contentHeight="300px"
placement="Bottom"
ariaLabelledBy="master-title">
<Page
id="master"
class="sapUiResponsivePadding--header"
title="Aktionen">
<List
id="AktionList">
</List>
</Page>
</Popover>
Calling the Popover in the controller file (sPath is /TableEntity('123456')/AktionSet):
if (!this._oPopover) {
Fragment.load({
id: "popoverNavCon",
name: "bernmobil.ZPM_STOERUNG_FDA.view.AktionPopover",
controller: this
}).then(function(oPopover){
this._oPopover = oPopover;
this.getView().addDependent(this._oPopover);
var oList = Fragment.byId("popoverNavCon", "AktionList");
var oItemTemplate = this._BuildItemTemplate();
oList.bindAggregation("items", sPath, oItemTemplate);
this._oPopover.openBy(oControl);
}.bind(this));
} else {
var oList = Fragment.byId("popoverNavCon", "AktionList");
var oItemTemplate = this._BuildItemTemplate();
oList.bindAggregation("items", sPath, oItemTemplate);
this._oPopover.openBy(oControl);
}
_BuildItemTemplate: function(){
var oItemTemplate = new sap.m.ObjectListItem({
title:"{AktionsBez}",
type: "Inactive"
});
oItemTemplate.addAttribute(new sap.m.ObjectAttribute({
text : "{Aktionstext}"
}));
oItemTemplate.addAttribute(new sap.m.ObjectAttribute({
text : "{path: 'ChangedAt', type: 'sap.ui.model.type.DateTime'}"
}));
return oItemTemplate;
}
And this is the idea of the second scenario which is calling the oDataService but not displaying any data:
Instead of having only the List definition in XML also the ObjectListItem is defined in the XML:
<List
id="AktionList"
items="{AktionSet}">
<ObjectListItem
title="{AktionsBez}"
type="Active">
<ObjectAttribute text="{Aktionstext}" />
<ObjectAttribute text="{ChangedAt}" />
</ObjectListItem>
</List>
And in the controller instead of building the template and doing the bindAggretation there is just:
var oList = Fragment.byId("popoverNavCon", "AktionList");
oList.bindElement(sPath);
How do I get the second scenario displaying data in the list?
I would suggest a third solution:
When pressing on your table row, get the binding context of the current row using oContext = oClickedRow.getBindingContext() or something similar. This context should point to /TableEntity('123456').
Apply this context to your Popover using oPopover.setBindingContext(oContext).
Now your Popover has the same context as your table row. The XML should look like in your second scenario.
Using the path is an extra step imo. I think it also makes more sense to bind the complete Popover and not just the List. Has the neat side effect that you can use a property of your TableEntity as the title for the Popover. It also completely avoids working with controls directly (which is one of the seven deadly sins) and you should be able to remove all those IDs.
Here is how the relevant part of the view should look:
<List
id="AktionList"
items="{AktionSet}">
<dependents>
<ObjectListItem
id="oObjectListItem"
title="{AktionsBez}"
type="Active">
<ObjectAttribute text="{Aktionstext}" />
<ObjectAttribute text="{ChangedAt}" />
</ObjectListItem>
</dependents>
</List>
And in the controller:
var oList = sap.ui.core.Fragment.byId(this.getView().createId("popoverNavCon"), "AktionList");
oList.bindItems({
path: sPath,
template: sap.ui.core.Fragment.byId(this.getView().createId("popoverNavCon"), "oObjectListItem")
});
Check dependents in sap.m.List aggregation section for details.

Conditional column value in UI5 table

I have a column in table whose value is bound to a property of data model.
text = { modelName>/OrderNo}. How to make it conditional based on a flag? If property from Model isReturnable = true, I want to show text = {modelName>/ReturnNo} else I want to show {OrderNo}. How to built syntax for that?
<table:Column>
<Label class="smartist-table-column-header" text="Qty Returned"/>
<table:template>
<Text text="{ path: 'OrderDetail>OrderNo'}"/>
</table:template>
</table:Column>
You can use expression binding.
See URL for details: https://ui5.sap.com/#/topic/daf6852a04b44d118963968a1239d2c0
Solution to your problem:
<Text text="{= ${modelName>isReturnable} ? ${modelName>/ReturnNo} : ${OrderDetail>OrderNo}}" />
As expression binding would be a more appropriate approach to this problem,
Custom formatting can also be one way to achieve this.
In the view:
<Text text= "{ parts:[
{path: "modelName>isReturnable"},
{path: "modelName>ReturnNo"},
{path: "modelName>OrderNo"},
],
formatter: '.formatOrderNo'
}"/>
In the corresponding controller
formatter: function(isReturnable, sReturnNo, sOrderNo){
if(isReturnable == true){
return sReturnNo;
}else{
return OrderNo;
}
}
In case of more complex logic where you need to perform some calculations/manipulations on the fields before binding, custom formatting is the way to go. Custom Formatters in SAPUI5

Get path from property in m.table

I'm looking for a convenient method to get the path from a table cell.
Background: It is required to implement a search field allowing to filter on all columns of responsive table. Here, the path is needed as parameter for the filter object.
XML Code
<Table items="{path: 'modelName>pathPart1/pathPart2'}">
<headerToolbar>
<Toolbar>
<Title text="titleText"/>
<SearchField search="searchInTable"/>
</Toolbar>
</headerToolbar>
<columns>
<Column>
<Text text="column1"/>
</Column>
<Column>
<Text text="column2"/>
</Column>
</columns>
<ColumnListItem>
<Text text="{modelName>cellName1}"/>
<Text text="{modelName>cellName2}"/>
</ColumnListItem>
</Table>
Controller Logic
searchInTable: function(event) {
var table = event.getSource().getParent().getParent();
var query = event.getParameters("query");
table.getBinding("items").filter(this.getFilters(table, query));
},
getFilters: function(table, query) {
var aFilters = [];
var items = table.getItems();
// Loop through items aggregation and populate filter object
jQuery.each(items, function(i, oItem) {
// Get path from cells (e.g. cellName1)
var sPath = oItem.mAggregations.cells[i].mBindingInfos.text.binding.sPath;
var sOperator = FilterOperator.EQ;
var sValue1 = query;
var oFilter = new Filter(sPath, sOperator, sValue1);
aFilters.push(oFilter);
});
return aFilters;
},
Can we replace this part by a more convenient and robust method?
var sPath = oItem.mAggregations.cells[i].mBindingInfos.text.binding.sPath;
As you notice, I'm trying to receive the sPath going through the whole object. However, its not working in all cases as the structure of the object may change. I bet there is an better approach available. However, I struggling a bit here.
Any ideas?
Edit: I do like to get the path pointing to the text property in the table. In this samplle it would be: cellName2
I'm on the phone right now, so I can't test it, but it is something like this
oItem.getCells()[i].getBindingContext().getPath()
getCells() comes from the ColumnListItem API if I am not wrong.
The other two from the ODataListBinding API or something like that...
If you dive a bit in the API you will find it
EDIT: I think you should provide the model name when getting the context. But I don't remember well...
oItem.getCells()[i].getBindingContext("modelName").getPath()
Try both, with and without it...
EDIT2: Here you have the snippet http://jsbin.com/votaxiyedi/edit?html,output
And this what you need:
oItem.getBindingContext("odata").getPath() + "/" + oItem.getCells()[0].getBinding("text").getPath();

How get selected item from StandardListItem

I'm building a master-detail app. I'm using sap.m.StandardListItem for listing master objects. I want that selected master object appear on a detail page.
<List id="lstRequest" headerText="Custom Content" selected="true" items="{
path: '/Requests',
parameters: {
expand: 'RequestTypeDetails'
}
}">
<StandardListItem
title="{RequestTypeDetails/RequestType2} - {RequestCode}"
description="{TotalAdvance}"
icon="sap-icon://request"
iconDensityAware="false"
iconInset="false"
type="Navigation"
press="onSelectApprovation"
/>
</List>
I'm following the guide from here but it doesn't work in my case.
var source = event.getSource();
var bindingobject = event.getBindingContext("Requests");
bindingobject is undefined.
Inside onSelectApprovation do the following:
var oItem = oEvent.getParameter("listItem") || oEvent.getSource());
var oCtx = oItem.getBindingContext();
var requestCode = oCtx.getProperty("RequestCode");
By the way: sap.m.List does not have a property called "selected" of type boolean. However, it has a select event that could also be used instead of using the press event of the StandardListItem...
Give the logical name while setting json model to list like below.
this.getView().byId("lstRequest").setModel(oListJson,"List");
oListJson will be your array of data.
now use your code for accessing list object in your onSelectApprovation fuction as below
onSelectApprovation : function(oEvent){
var bindingobject = oEvent.getSource().getBindingContext("List");
}

How to set/get selected text in sap.m.select?

I only find setSelectedItem setSelectedItemId setSelectedKey in sap.m.select doc, how to setSelected text in sap.m.select?
For example:
<Select
forceSelection="false"
selectedKey="{/ProductCollection/0/ProductId}"
items="{
path: '/ProductCollection',
sorter: { path: 'Name' }
}">
<core:Item key="{ProductId}" text="{Name}" />
</Select>`
How to get selected text (Name) in this control ?
The keys shall be unique but the texts do not have to be unique. In some situations the texts are translated but the keys stay the same. Thats why the keys are used for selection.
To get the text of the selected item you can use
var text = select.getSelectedItem().getText();
To select an item by text you have to search the model for the item, get its key and use that with setSelectedKey().