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.
Just did as you suggested and it works perfectly fine and I could get rid of the IDs in the fragment. Can you explain me why the navigation property works when I do setBindingContext and the list items point to (AktionSet}. Is this because of the relative binding {AktionSet} (without the /) and the root is the /TableEntity('123456') of the bound context?
And could you point me to some more information about the deadly sin of using IDs. I am aware that it can create issues, but never looked at it as such bad practice.
Yes, that's how binding works. If you provide a relative path (no slash) it will check if there is a surrounding context and append the relative path to that.
I think IDs create a tight bond between XML and JS which is not necessary. This makes the code less reusable. This also makes refactorings harder. Your list becomes a table? You also have to rename your ID to AktionTable. I heard an interesting talk at this years UI5Con, basically everything can be done without IDs and it makes your code more maintainable.