How get selected item from StandardListItem - sapui5

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

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.

How to set the input of a combobox to read-only

In one of my UI5-Dialogs, I implemented a combobox which is invisible when the screen is initially loaded.
In the method onAfterRendering, I start with setting the input to read-only:
onAfterRendering: function(oEvent) {
var oShovel = this.getView("View0200").byId("comboShovel");
oShovel.$().find("input").attr("readonly", true);
this.setVisibleByListKey();
},
After this the method setVisibleByListKey is called, the property visibleShovel will be set to false.
setVisibleByListKey: function(oEvent) {
var oModel = this.getView("View0200").getModel("Data0200");
this.setVisibleByListKey1(oModel);
// ...
},
setVisibleByListKey1: function(oModel) {
oModel.setProperty("/visibleShovel", false);
},
The property is bound to the attribute visible on my combobox.
Because of this behavior, the method onAfterRendering will be called again, the attribute readonly is not available (because of invisibility).
<ComboBox id="comboShovel"
editable="true"
enabled="true"
visible="{Data0200>/visibleShovel}"
valueState="None"
change=".changeCombo">
<items>
<core:Item text="Ja" enabled="true" key="0" />
<core:Item text="Nein" enabled="true" key="1" />
<core:Item text="Nicht erforderlich" enabled="true" key="2" />
</items>
</ComboBox>
I tried to call the set method in onInit or onBeforeRendering but at this time the input attributes can not be changed (because of invisibility again).
So how can I set the input of the combobox to read-only when I set the named visible property?
Solution would be either to use sap.m.Select or to implement a "change" event handler for the sap.m.Combobox and use a coding similar to this sample:
handleChange: function(oEvent) {
var oValidatedComboBox = oEvent.getSource();
var sSelectedKey = oValidatedComboBox.getSelectedKey();
var sValue = oValidatedComboBox.getValue();
if (!sSelectedKey && sValue) {
oValidatedComboBox.setValueState("Error");
oValidatedComboBox.setValueStateText("Please enter a valid country!");
} else {
oValidatedComboBox.setValueState("None");
}
},
Instead of using jquery, use UI5 control's methods and properties:
The sap.m.ComboBox borrows the following two methods from sap.m.InputBase:
setEditable
setEnabled
or since you are using property binding for the visibility, do the same for the editable property, e.g. {Data0200>/editableShovel}

Method getPath called in onBeforeRendering returns undefined

I have a List Report which, once selected an item, prompts to an Object Page. I am using no FIORI Elements, everything was created from scratch.
The object page has a static header, but its body changes from item to item. In essence, the body uses different fragments that depends on a field (Position Type) of the selected item. In other words:
Pos Type 1 ---> fragment A
Pos Type 2 ---> fragment B
To do all this, on the controller of the object page, I have implemented the following withing the onBeforeRendering lifecycle method:
onBeforeRendering: function() {
// // Set Fragment to be used
var oLayout = this.getView().byId("ObjectPageLayout"),
oFragment = sap.ui.xmlfragment(this._fragmentName());
oLayout.addSection(oFragment);
},
_fragmentName: function() {
var oModel = this.getView().getModel();
var sPosType = oModel.getProperty(this.getView().getObjectBinding().getPath() + "/PositionType");
var sFragment;
if (sPosType === "1") {
sFragment = "A";
} else if (sPosType === "2") {
sFragment = "B";
}
return sFragment;
},
The problem I am facing is that this code is throwing the following error message: "Uncaught (in promise) TypeError: Cannot read property 'getPath' of undefined"
The only way I found to make this to work is by, instead of using method onBeforeRendering, I used onInit. This way, getPath() works fine. But if the user goes back to the List Report, and then selects an item of a different Position Type, then the Object Page displays the same fragment used in the previous item selected.
In case you wonder, bellow you will find the object view:
<mvc:View height="100%" xmlns="sap.uxap" xmlns:core="sap.ui.core" xmlns:mvc="sap.ui.core.mvc" xmlns:m="sap.m" xmlns:semantic="sap.m.semantic"
xmlns:forms="sap.ui.layout.form" xmlns:layout="sap.ui.layout" controllerName="objectview.controller"
xmlns:aud="sap.uxap.sample.SharedBlocks.fragmentblocks">
<semantic:FullscreenPage id="page" navButtonPress="onNavBack" showNavButton="true" title="{i18n>ObjectPageTitle}">
<m:Page title="Object Page Title">
<m:content>
<ObjectPageLayout id="ObjectPageLayout">
<headerTitle>
<ObjectPageHeader id="ItemTitle" objectTitle="Item Title">
<actions>
Some actions defined
</actions>
</ObjectPageHeader>
</headerTitle>
<headerContent>
Some Header Content
</headerContent>
<sections>
</sections>
</ObjectPageLayout>
</m:content>
<m:footer>
<m:Bar>
<m:contentRight>
Buttons added to the Footer
</m:contentRight>
</m:Bar>
</m:footer>
</m:Page>
</semantic:FullscreenPage>
What happens is that each time you go to the page you add a new section on the container of sections.
You can remove all the existent sections before adding the new one.
oLayout.removeAllSections();
oLayout.addSection(oFragment);

Filtering data in UI5

The filter using below code is not working. I created an application using a template from Web IDE and then bound OData to the list in XMLView, applying filter on search.
View:
<SearchField liveChange="onSearch" id="master1SearchField" search="onSearch"/>
<List id="master1List" items="{path:'/DetailsSet'}">
<items>
<ObjectListItem id="master1ListItem">
<attributes>
<ObjectAttribute text="{Name}"/>
</attributes>
</ObjectListItem>
</items>
</List>
Controller:
onSearch : function(oEvent) {
var sFilteredValue = oEvent.getSource().getValue();
var oFilter = new sap.ui.model.Filter("Name", sap.ui.model.FilterOperator.Contains, sFilteredValue);
var oElement = this.getView().byId("table");
var oBinding = oElement.getBinding("items");
oBinding.filter([oFilter]);
}
You need to get binding of the items on which the filter need to be applied.
var oElement = this.getView().byId("master1List");
should resolve the issue.
Try to force an update of the control after setting the filter:
oBinding.refresh(true);

Value of a select in SAPUI5

I have the following select in a table in my xml view.
Table:
<Table id="variables"
rows="{
path: 'modelname>/ZDATSet'
}">
...
Select:
<m:Select
selectedKey="{modelname>Datetype}"
items="{
path: 'modelname>/ZTYPESet'
}">
<core:Item key="{modelname>Datetype}" text="modelname>Datetypetxt}" />
</m:Select>
Furthermore I have a button in an other row in the table.
In the press-function I want to read the currently selected key of the select-box.
If I try it with
var button = oEvent.getSource();
var context = button.getBindingContext("modelname");
var datetype = context.getProperty("Datetype");
I only get the preselected value but not the change from the user input.
(Same problem with an text input in the row)
I already put data-sap-ui-xx-bindingSyntax="complex" in the index.html
I found the solution now.
I thought <script src="https://sapui5.hana.ondemand.com/resources/sap-ui-core.js"
data-sap-ui-xx-bindingSyntax="complex" ... should be enough for the default two way binding.
Now I added oModel.setDefaultBindingMode(sap.ui.model.BindingMode.TwoWay); to the model and it works fine.
If your button is in the same row you could do something like this in its press event:
onPress:function(oEvent){
var button = oEvent.getSource();
var context = button.getBindingContext("modelname"); //Points to the current row
var datetype = context.getProperty("DateType");
...
}
If the button is outside of the table you have to give us more details: Which Table are you using and how is it configured, do you want to read the value of the selectbox in the currently selected row? Add more code!
Based on your code snippet, you are using model binding to set the items and the selected key of your Select.
In the Button press handler you can get the current value from the binding context:
onPress: function (oEvent) {
oEvent.getSource().getBindingContext("modelname").getProperty("Datetype");
}
Here once you set the selectedKey property in SelectionInputType.COMBOBOX, you can take value as below.
oController = this; var view = oController.getView(); var oModel = view.getModel(); var data = oModel.getData();