API reference: Where to find all the properties available for aggregation binding info object? - sapui5

Where can I find aggregation binding properties like path, factory, etc.. in the API reference?
Just like in following code
<List items="{
path: '/Products',
factory: '.productListFactory',
...
}">
Where to find more such properties and their descriptions?

You can see more such properties in ManagedObject#bindAggregation.
Additionally, parameters and events await key-value pairs of which the possible keys are documented in the corresponding model type.
For example, the keys for parameters, when binding with a v2.ODataModel, can be found in ODataModel#bindList or in ODataListBinding. The latter module also documents which events can be registered.
{ // Standard options. See ManagedObject bindAggregation
path: '...',
filters: [/*...*/],
...
parameters: { // Model dependent. See e.g. ODataListBinding constructor
expand: 'ToA, ToB/ToB1/ToB2, ToC',
select: 'ProductID, ProductName',
custom: 'myCustomQuery',
batchGroupId: 'myGroup',
},
events: { // Model dependent. See e.g. ODataListBinding events
dataRequested: '.onDataRequested',
dataRequested: '.onDataReceived',
change: '.onDataChange'
}
}

That's a binding (they're enclosed in {}).
You can use the getBindingInfo method.
So, for example, if your List control has the id "mylist":
this.getView().byId("mylist").getBindingInfo("items");
It will return you an object containing all the binding properties, such as path and factory.

Related

How do I express JSON-API sparse fieldsets with OpenAPI-3.0

I'm implementing an OpenAPI-3.0 spec for my API, and I plan on using sparse fieldsets as a parameter for GETs. The examples for parameters using style=deepObject are a little sparse, so I'm not sure if I've got this exactly right.
- in: query
name: fields
style: deepObject
schema:
type: object
additionalProperties:
type: string
Can I combine both the deepObject and additionalProperties options?
I want to support flexible query parameter inputs like this:
GET /articles?include=author&fields[articles]=title,body&fields[people]=name
but I don't want to have to spell out every single option for each resource and field.
Your definition is correct. You might also need to add allowReserved: true so that the comma in =title,body is not percent-encoded, and you can add a parameter example value for documentation purposes:
- in: query
name: fields
style: deepObject
allowReserved: true
schema:
type: object
additionalProperties:
type: string
example:
articles: title,body
people: name
When using "try it out" in Swagger UI, enter the parameter value in the JSON format like so:
{
"articles": "title,body",
"people": "name"
}
Swagger UI will serialize the parameter as
?fields[articles]=title,body&fields[people]=name

Rows binding in sap.ui.table.Table dynamically

I have made a title depending on variable how it's shown in: Title depending on other variable in SAPUI5
I would like to make the same with rows in sap.ui.table.Table so I tried:
rows="{= ${someData>/infos}.length > 0 ? ${someData>/infos} : ${someData>/result}}"
Whereas someData is an ODataModel (v2).
But got an error:
Uncaught TypeError: Cannot read property 'indexOf' of undefined
Problem
The problem is that you're trying to determine .length from an object. In ODataListBinding (someData>/infos), aggregations are resolved in an object rather than an array. Therefore the syntax can't work. Furthermore, the .length syntax implies that the whole collection is already available on the client-side, contradicting the purpose of sap.ui.table.Table.
Expression binding with .length makes only sense with a client-side JSONModel as mentioned here.
Alternative approach
There are multiple ways to define aggregation binding dynamically, but the most straight-forward solution would be just to access the table control reference and call bindRows dynamically. Something like this:
onInit: function() {
this.loadCountOf("SomeSet", this.bindTableRows.bind(this));
// ...
},
loadCountOf: function(entitySetName, handleCountSuccess) {
const odataModel = /*...*/;
odataModel.read(`/${entitySetName}/$count`, {
success: count => handleCountSuccess.call(this, +count),
});
},
bindTableRows: function(count) {
this.byId("myTable").bindRows({
path: count > 0 ? "/SomeSet" : "/TheOtherSet",
// ...
});
},
API reference: sap.ui.table.Table#bindRows
the errors seem to tell you that either infos or result is undefined. You should check the current value of those arrays.
Anyway, it's not a really good idea to bind table rows like that IMHO.
What's you scenario?

Filter expanded OData request

I need to pass a parameter to the backend. I want to use $filter for this.
My code below is not working, there are no filters returned by io_tech_request_context->get_filter( )->get_filter_select_options( ) in the Figures entityset.
var aFilters = [ new sap.ui.model.Filter("TeamMembers/Figures/FILTERKEY", sap.ui.model.FilterOperator.EQ, sFilterValue) ];
this.getView().bindElement({
path: "/TeamDataSet('0')",
parameters: {
expand: 'TeamMembers/Figures'
},
filters: aFilters
});
Element binding / ContextBinding doesn't support the property filters since you're binding just a single entity and not a collection. If you need to filter Figures, you'll have to bind them to an aggregation (e.g. items on List), get the corresponding ListBinding object, and then call .filter from there.
Here is a similar example: https://embed.plnkr.co/AoIZI4/. Take a look at the handler onSearch.
In case someone actually wants to filter a list by expanded results, the navigation property can be applied in the Filter path which then gets resolved by the path of the bound binding object. For example:
<List items="{
path: 'myODataModel>/Products',
parameters: {
expand: 'ToSupplier'
}
}">
Then in Controller, filter Products by their supplier country:
new Filter({
path: "ToSupplier/Country",
operator: "EQ",
value1: "UK",
})
(From: https://embed.plnkr.co/wAlrHB/).
Be aware that this works only if expanding does not result in a collection but a single object (e.g. associated supplier). Filtering by looking up at an associated collection is supported as of OData V4 which can be achieved via FilterOperator.All / .Any.

What is use of 'parameters' option in binding object?

In the code below, what is the significance of parameters option and select option within it?
I have looked into API but to avail nothing.
<List id="list"
items="{
path: '/PurchaseOrders',
sorter: [{
path: 'ChangedAt',
descending: true
}, {
path: 'POId',
descending: false
}],
parameters: {
select: 'POId,OrderedByName,SupplierName,GrossAmount,CurrencyCode,ChangedAt,ItemCount'
}
}">
...
</List>
With the select property you can tell the server to return just a subset of entity properties. This is useful if you have large entities with a lot of properties, but want to display only some of them, e.g. in a table. This works only if you are using an ODataModel and thus an ODataListBinding.
In general the parameters argument is used to pass implementation specific parameters to the binding while having a common API for all model implementations, i.e. all implementations of a ListBinding have the following signature:
oModel (the model which holds the data)
sPath (the binding path)
oContext (the binding context)
aSorters (sorters to be applied)
aFilters (filters to be applied)
mParameters (additional parameters which depend on the model implementation and are not necessarily supported by all of them)

Swagger response class Map

I have a REST API that returns, essentially a Map of (String, Object) where Object is either
A custom bean (let's say class Bean) or
A List of elements, all of type Bean
In JSON, this translates very well to:
{
"key1":{
"val1":"some string",
"val2":"some other string",
"val3":"another string"
},
"key2":[
{
"val1":"some string",
"val2":"some other string",
"val3":"another string"
},
{
"val1":"some string",
"val2":"some other string",
"val3":"another string"
}
]
}
Via swagger annotations, is there a way to specify this kind of a dynamic Map as the response class?
Thanks
I read the 'Open API Specification' - 'Add support for Map data types #38' page. As far as I understand, it recommends to use additionalProperties, but I haven't managed to make it work with Swagger UI 2.1.4 (see my related question: Swagger: map of string, Object).
I have found the following work-around: define an object, with one property that is the key, and with an inner object as the value for the "key" property.
The display in Swagger UI is correct, but one does not see it is a map, so it is then needed to explain in the comment that this is actually a map.
In your case, I find it a bit weird to have once a Bean, and once a list of Beans: I would find it more logical to have an array of one Bean in the first case.
Still, you could do, for example:
your_property: {
description: "This is a map that can contain several objects indexed by different keys. The value can be either a Bean or a list of Beans.",
type: object,
properties: {
key_for_single_bean: {
description: "The value associated to 'key_for_single_bean' is a single Bean",
$ref: "#/definitions/Bean"
},
key_for_list_of_beans: {
description: "The value associated to 'key_for_list_of_beans' is an array of Beans",
type: array,
items: {$ref: "#/definitions/Bean"}
}
}
}