UI5 using something like .. in bindingpath - binding

I using a oData-Model that returns for .../User a list like that:
[
{
Id: 5
Name: "name",
Desc: "desc",
IsEditable: false,
Items: [
{ itemName: "Name1" },
{ itemName: "Name2" },
{ itemName: "Name3" },
{ itemName: "Name4" }
]
},
...
]
I bind this to my xml view like that:
<View binding="model>/User(5)">
<Text text="model>Name" />
<Text text="model>Desc" />
<List items="{model>Items}" >
<CustomListItem>
<input text="{model>itemName}" editable="{model>../IsEditable}" />
</CustomListItem>
</List>
</View>
So now i would like to disable the input by its parent "IsEditable" proppertie.
How i can make this happen?

To achieve this you have to edit your code like this:
(Relative binding in JSON Models without a "/", absolute with a "/")
<List items="{model>/Items}" >
<CustomListItem>
<Input value="{model>itemName}" editable="{model>/IsEditable}" />
</CustomListItem>

Related

How to override renderItem item based in SectionList React Native to use section based?

According to FB docs, you can override the renderItem default, item based, render to use the section based render in the SectionList in react native, but I haven't found a way to do that. Please help.
Here is the link
I only have a workaround, I haven't found a way to make renderItem prop render per section instead of per item.
For all sections, you want to render horizontally, use a FlatList and set the data for that section to be an array of arrays.
Keep in mind that for listItems you want to render vertically, the data property should NOT be an array of arrays.
Here's a sample data structure
const DATA = [
{
header: '30 - 40% Off',
type: 'horizontal',
//horizontal list here.... As stated above, data is an array that contains an array of the actual data
data: [
[
{
imgUri:
'https://images.unsplash.com/photo-1607930231879-36bbb29ffe0a',
store: 'Asanka Store',
storeRating: '4.4',
originalPrice: '10.00',
discountedPrice: '5.00',
},
{
imgUri:
'https://images.unsplash.com/photo-1583506522440-b2639ef4c1d8',
store: 'Maame Dorkono Shop',
storeRating: '3.8',
originalPrice: '27.00',
discountedPrice: '18.99',
},
{
imgUri:
'https://images.unsplash.com/photo-1610397962076-02407a169a5b',
store: 'Thywill Store',
storeRating: '3.8',
originalPrice: '27.00',
discountedPrice: '18.99',
},
],
],
},
{
header: 'All Stores',
//Vertical List here
data: [
{
imgUri:
'https://images.unsplash.com/photo-1598965675045-45c5e72c7d05',
store: 'Thywill Store',
storeRating: '3.8',
originalPrice: '27.00',
discountedPrice: '18.99',
},
{
imgUri:
'https://images.unsplash.com/photo-1574137907555-8e9ad5bc17fa',
store: 'Asanka Store',
storeRating: '4.4',
originalPrice: '10.00',
discountedPrice: '5.00',
}
],
},
];
Now use that in your SectionList.
We're going to use a FlatList to render the horizontal list.
<SectionList
sections={DATA}
keyExtractor={(item, index) => index}
renderSectionHeader={({section}) => (
<Text>{section.header}</Text>
)}
renderItem={({section, item}) => {
return section.type === 'horizontal' ? (
<FlatList
horizontal
data={section.data[0]}
showsHorizontalScrollIndicator={false}
keyExtractor={(item, index) => item.store + index}
renderItem={({item}) => <Item item={item} />}
/>
) : (
<Item item={item} />
);
}}
/>

Binding selectedItems of MultiComboBox to OData navigation property

I would like to display MultiComboBox with preselected items.
As an example let's say I have three entities in my OData service:
Car (CarId, Name)
CarColors (CarId, ColorId)
AvailableCarColors (ColorId, Description)
A car can be painted using any number of available colors. Imagine a car configurator which enables you to choose colors for your car.
I would like to display MultiComboBox with items bound to AvailableCarColors and use CarColors as source of selected items.
Is it possible to perform such binding without contorller logic, only using xml view?
Example
In the example above I would like to have:
Porsche initially assigned Blue, Cyan and Magenta
Mercedes initially assigned Red
BMW initially assigned Green, Yellow, Black
Also, example utilizes JSONModel and I am trying to do the same with ODataModel.
If you have a navigation property from Car to CarColors then it's possible, however not completely without a code. At the point where you react to the change of CarId you have to make a context binding, any control can be bound to a context.
For example, suppose you have navigation property CarColors of entity Car, and also it is assumed that you use unnamed OData model, then you can bind the context in this way (for a View):
this.getView().bindObject({
path: oDataModel.createKey("/Car", { CarId: <some car id> }),
parameters: {
expand: "CarColors"
}
});
After that you can bind your MultiComboBox items in this form:
items="{CarColors}"
Note, there is no starting slash in the binding as it should take the property from the context.
If you want to show ALL colors with some of them selected then it can be done with complex binding and formatter function.
So, the MultiComboBox items should be bound to AvailableCarColors and selectedKeys should have complex binding, something like this:
selectedKeys="{
path: 'CarColors', formatter: '.formaSelectedColors'
}
formaSelectedColors has single array parameter with CarColors and must return String array with all color keys.
I have modified your JSON for correct binding, added new property called KeysSelected for selecting the colors corresponding to the car. As per the binding is concern the object related to the individual car should be inside.
Used selectedKeys property for selecting the key(colors)
<MultiComboBox ..... selectedKeys="{KeysSelected}" >
Working code
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>SAPUI5 single file template</title>
<script src="https://openui5.hana.ondemand.com/resources/sap-ui-core.js"
id="sap-ui-bootstrap"
data-sap-ui-theme="sap_belize"
data-sap-ui-libs="sap.m"
data-sap-ui-bindingSyntax="complex"
data-sap-ui-compatVersion="edge"
data-sap-ui-preload="async"></script>
<script id="myXmlView" type="ui5/xmlview">
<mvc:View
controllerName="MyController"
xmlns="sap.m"
xmlns:core="sap.ui.core"
xmlns:mvc="sap.ui.core.mvc"
xmlns:f="sap.ui.layout.form">
<Shell>
<List items="{/Cars}">
<CustomListItem>
<f:SimpleForm layout="ResponsiveGridLayout" editable="true">
<Label text="{Name}" />
<MultiComboBox items="{/AvailableCarColors}" selectedKeys="{KeysSelected}" >
<core:Item key="{ColorId}" text="{Description}"/>
</MultiComboBox>
</f:SimpleForm>
</CustomListItem>
</List>
</Shell>
</mvc:View>
</script>
<script>
sap.ui.getCore().attachInit(function () {
"use strict";
sap.ui.define([
"sap/ui/core/mvc/Controller",
"sap/ui/model/json/JSONModel"
], function (Controller, JSONModel) {
"use strict";
return Controller.extend("MyController", {
onInit : function () {
var oModel = new JSONModel({
Cars: [
{
CarId: 1,
KeysSelected : ["3", "4", "5"],
Name: "Porsche",
ToColors:[
{ CarId: 1, ColorId: 3},
{ CarId: 1, ColorId: 4},
{ CarId: 1, ColorId: 5},
]
},
{
CarId: 2,
KeysSelected : ["1"],
Name: "Mercedes",
ToColors:[
{ CarId: 2, ColorId: 1},
]
},
{
CarId: 3,
KeysSelected : ["2", "6", "7"],
Name: "BMW",
ToColors:[
{ CarId: 3, ColorId: 2},
{ CarId: 3, ColorId: 6},
{ CarId: 3, ColorId: 7},
]
},
],
AvailableCarColors: [
{ ColorId: 1, Description: 'Red' , KeysSelected : ["0", "1"]},
{ ColorId: 2, Description: 'Green' },
{ ColorId: 3, Description: 'Blue' },
{ ColorId: 4, Description: 'Cyan' },
{ ColorId: 5, Description: 'Magenta' },
{ ColorId: 6, Description: 'Yellow' },
{ ColorId: 7, Description: 'Black' },
],
CarColors: [
{ CarId: 1, ColorId: 3},
{ CarId: 1, ColorId: 4},
{ CarId: 1, ColorId: 5},
{ CarId: 2, ColorId: 1},
{ CarId: 3, ColorId: 2},
{ CarId: 3, ColorId: 6},
{ CarId: 3, ColorId: 7},
]
});
this.getView().setModel(oModel);
}
});
});
sap.ui.xmlview({
viewContent : jQuery("#myXmlView").html()
}).placeAt("content");
});
</script>
</head>
<body class="sapUiBody">
<div id="content"></div>
</body>
</html>
Output
You can use expression binding, its work for one selection
<MultiComboBox items="{/AvailableCarColors}" selectedKeys="{=${Name} === 'Porsche' ? '3': ${Name} === 'BMW' ? '2' : '1' }" >
But Iam not sure how to use for multi selection '3,4,5' and '2,6,7' dosent work may be i18n solve.

SAPUI5 XmlView Show Data from Aggregation Binding Child

I need to get all the ContactEmployees contacts of each BusinessPartners client, in a Table List. Contacts are loaded but I can not show fields
My request https://***/BusinessPartners?$select=ContactEmployees&$skip=0&$top=20
My JSON Result from request "Only Selected ContactEmployees"
{
"#odata.context" : "https://**********$metadata#BusinessPartners",
"value" : [
{
"ContactEmployees" : [
{
"CardCode" : "C000002",
"Name" : "Jose Duran",
"Position" : null,
"Address" : null,
"Phone1" : null,
"Phone2" : null
},
{
"CardCode" : "C000003",
"Name" : "Leo Manuel",
"Position" : null,
"Address" : null,
"Phone1" : null,
"Phone2" : null
}
]
},
{
"ContactEmployees" : [
{
"CardCode" : "C000010",
"Name" : "MILDRED MEJIA",
"Position" : null,
"Address" : null,
"Phone1" : null,
"Phone2" : null
}
]
},
{
"ContactEmployees" : []
},
{
"ContactEmployees" : []
}
],
"#odata.nextLink" : "BusinessPartners?$select=ContactEmployees&$skip=23&$top=5"
}
My Table View
<Table id="idPartnerTable"
growing="true"
growingScrollToLoad="true"
inset="false"
items="{
path: '/BusinessPartners',
parameters:{
$select:'ContactEmployees,CardCode'
},
sorter: {
path: 'CardCode'
}
}">
<columns>
<Column id="carcode">
<Text text="ID" />
</Column>
<Column id="nombre" >
<Text text="Name" />
</Column>
</columns>
<items>
<ColumnListItem
type="Navigation"
press="onPress">
<cells>
<Text text="{ContactEmployees/CardCode} "/>
<Text text="{ContactEmployees/Name} "/>
</cells>
</ColumnListItem>
</items>
</Table>
CONSOLE ERRORS
Failed to drill-down into ('BUSINESSPARTNERS
CODES')/ContactEmployees/Name, invalid segment: Name -
/******/BusinessPartners?$select=ContactEmployees,CardCode&$orderby=CardCode sap.ui.model.odata.v4.lib._Cache
If I change {ContactEmployees/Name} to {ContactEmployees/0/Name} they are shown but only 1 single contact, and I need to bring them all
Use the expand option in order to get the ContactEmployees of each BusinessPartners.
try this :
<Table id="idPartnerTable"
growing="true"
growingScrollToLoad="true"
inset="false"
items="{
path: '/BusinessPartners',
parameters:{
expand:'ContactEmployees'
},
sorter: {
path: 'CardCode'
}
}">
here is plunker it could help you : http://plnkr.co/edit/Q6KqSRk4kk0V81AdCrvQ?p=preview

SAPUI5 table binditems from expand performed in a bindelement

I am trying a proof of concept in SAPui5 to check the content of a searchfield, bind a result into another field, if i don't have any result i display an error message that has been written in a message field of my odata
so far i succeeded that this way
this.getView().bindElement({
path: "/ExcSet('" + evt.getSource().getValue() + "')",
model: "EXCEPTION",
events: {
dataReceived: function(response) {
if (response.mParameters.data.Message !== '') {
MessageBox.error(response.mParameters.data.Message);
}
}
}
(If someone knows how to do that a better way, because using mParameters is not the best way, it is welcome)
Now, I want to extend my odata call with an expand navigation to display a table of results, by not using another odata call that the one i used already, so here is my code so far :
eanSearch: function(evt) {
var oView = this.getView();
var oTemplate = new ColumnListItem({
cells: [
new Text({
text: "{Volum}"
}),
new Text({
text: "{Voleh}"
})
]
});
this.getView().bindElement({
path: "/ExcSet('" + evt.getSource().getValue() + "')",
model: "EXCEPTION",
parameters: {
expand: "ExcMarmNav"
},
events: {
dataReceived: function(response) {
if (response.mParameters.data.Message !== '') {
MessageBox.error(response.mParameters.data.Message);
}
}
}
});
oView.byId("table").bindItems({
path : '/ExcMarmNav',
template : oTemplate
});
}
The data of the expand is loaded into my response as you can see here
data: {
"ExcSet('5410366897766')": {
"__metadata": {
"id": "http://...:8000/sap/opu/odata/sap/ZEXCEPTION_SRV/ExcSet('5410366897766')",
"uri": "http://...:8000/sap/opu/odata/sap/ZEXCEPTION_SRV/ExcSet('5410366897766')",
"type": "ZEXCEPTION_SRV.Exc"
},
"Matnr": "000000000040000000",
"Ean": "5410366897766",
"Message": "",
"ExcMarmNav": {
"__list": [
"MarmSet(Matnr='40000000',Meinh='EA')"
]
}
},
"MarmSet(Matnr='40000000',Meinh='EA')": {
"__metadata": {
"id": "http://...:8000/sap/opu/odata/sap/ZEXCEPTION_SRV/MarmSet(Matnr='40000000',Meinh='EA')",
"uri": "http://...:8000/sap/opu/odata/sap/ZEXCEPTION_SRV/MarmSet(Matnr='40000000',Meinh='EA')",
"type": "ZEXCEPTION_SRV.Marm"
},
"Matnr": "40000000",
"Meinh": "EA",
"Umrez": "1",
"Umren": "1",
"Eannr": "",
"Ean11": "5410366897766",
"Numtp": "HE",
"Laeng": "20.000",
"Breit": "20.000",
"Hoehe": "10.000",
"Meabm": "CM",
"Volum": "4000.000",
"Voleh": "CCM",
"Brgew": "2.500",
"Gewei": "KG",
"Mesub": "",
"Atinn": "0000000000",
"Mesrt": "00",
"Xfhdw": "",
"Xbeww": "",
"Kzwso": "",
"Msehi": "",
"BflmeMarm": "",
"GtinVariant": "",
"NestFtr": "0",
"MaxStack": 0,
"Capause": "0.000",
"Ty2tq": ""
}
}
But i don't know how to use resultset to bind it into a table, my code above is not working, if someone has an idea of the params to use for my binditems, or if there is another way to do it?
Best regards
Denis
I managed to do the binding of my table using an intermediate JSON Model based on the response of the Odata Model
eanSearch: function(evt) {
var oView = this.getView();
this.getView().bindElement({
path: "/ExcSet('" + evt.getSource().getValue() + "')",
model: "EXCEPTION",
parameters: {
expand: "ExcMarmNav"
},
events: {
dataReceived: function(response) {
if (response.mParameters.data.Message !== '') {
MessageBox.error(response.mParameters.data.Message);
} else {
var model = new JSONModel({
"items": response.mParameters.data.ExcMarmNav
});
oView.setModel(model, "itemModel");
}
}
}
});
And this is the XML view:
<Table id="table" items="{itemModel>/items}">
<columns>
<Column><Label/></Column>
<Column><Label/></Column>
</columns>
<ColumnListItem>
<cells>
<Text text="{itemModel>Volum}"/>
<Text text="{itemModel>Voleh}"/>
</cells>
</ColumnListItem>
</Table>
works fine but I would like to avoid using the intermediate JSON Model and bind directly the array of the response in the table
Ok I managed to find what I needed :)
so the controller:
eanSearch: function(evt) {
var oView = this.getView();
this.getView().bindElement({
path: "/ExcSet('" + evt.getSource().getValue() + "')",
model: "EXCEPTION",
parameters: {
expand: "ExcMarmNav"
},
events: {
dataReceived: function(response) {
if (response.mParameters.data.Message !== '') {
MessageBox.error(response.mParameters.data.Message);
}
}
}
});
}
and the view:
<Table noDataText="No Data" items="{EXCEPTION>ExcMarmNav}">
<columns>
<Column><Label/></Column>
<Column><Label/></Column>
</columns>
<items>
<ColumnListItem>
<cells>
<Text text="{EXCEPTION>Volum}"/>
<Text text="{EXCEPTION>Voleh}"/>
</cells>
</ColumnListItem>
</items>
</Table>

SAPUI5 Two oData Datasources within manifest / descriptor

i'm using SAPUI5 Version gt 1.30 and I try to define the automatic model instantiation of two external services within the manifest.
My first question is, are more than one odata services allowed? Sorry, but i'cant find it out by the documentation.
The default datasource ("") works. But the second datasource ("HLA") not.
If more than once are allowed, please could somebody look for the right definition.
"sap.app":
"dataSources": {
"mainService": {
"uri": "path.xsodata/",
"type": "OData",
"settings": {
"odataVersion": "2.0",
"localUri": "localService/metadata.xml"
}
}
"secondService": {
"uri": "/path.......xsodata/",
"type": "OData",
"settings": {
"annotations": [],
"odataVersion": "2.0",
"localUri": ""
}
}
},
"sap.ui5":
"models": {
"i18n": {
"type": "sap.ui.model.resource.ResourceModel",
"settings": {
"bundleName": "....i18n.i18n"
}
},
"": {
"dataSource": "mainService",
"settings": {
"metadataUrlParams": {
"sap-documentation": "heading"
}
}
},
"HLA": {
"dataSource": "secondService",
"settings": {
"metadataUrlParams": {
"sap-documentation": "heading"
}
}
}
}
Thanks a lot!
Not sure if you have solved your problem, but I encountered the same problem today too. And I realise you need to use different notations when binding those two data sources to a control. I'm using XML view btw.
For the default "" model:
<Table id="table" inset="true" items="{/}" >
<columns>
<Column>
<Text text="ID"/>
</Column>
<Column>
<Text text="Name"/>
</Column>
</columns>
<items>
<ColumnListItem>
<cells>
<Text text="{id}"/>
<Text text="{name}"/>
</cells>
</ColumnListItem>
</items>
</Table>
For the second model named "Users":
<Table id="userTable" inset="true" items="{Users>/}">
<columns>
<Column>
<Text text="ID"/>
</Column>
<Column>
<Text text="Last Name"/>
</Column>
</columns>
<items>
<ColumnListItem>
<cells>
<Text text="{Users>empNumber}"/>
<Text text="{Users>lastName}"/>
</cells>
</ColumnListItem>
</items>
</Table>
It works for me :)
Of course you can have more than one data source, but it is recommended by the fiori guidelines to only use one.
Do you want your address to look like this path.......xsodata/ ?
Also I think you should remove the localUri from the second data source.
Because if there is no metadata document this might throw an arror.
"secondService": {
"uri": "/proxy/service.xsodata",
"type": "oData",
"settings": {
"odataVersion": "2.0"
}
}
What is the output of the debugger? Do you get an error?
Also your oData model should have a type.
"HLA": {
"dataSource": "secondService",
"type": "sap.ui.model.odata.v2.ODataModel"
}

Resources