Dynamic content type of table cell - sapui5

I get data from a database, make a model out of it and bind to a table.
I have a problem with one databse field that contains dataURL of the image or "Not Available" if no image is present.
The problem is that depending on the database field value, the cell of the table should be sap.m.Image or sap.m.Text.
And I can't get it to work.
Here is the relevant code part:
var signatureData = {};
signatureData.item = "Signature";
signatureData.value = data.signature;
var oModelSignature = new sap.ui.model.json.JSONModel();
oModelSignature.setData(signatureData);
var oSignatureTable = sap.ui.getCore().byId("reportDetailsSignature");
oSignatureTable.setModel(oModelSignature);
var oSignature;
if(data.signature == "Not Available"){
oSignature = new sap.m.Text({text: "{value}"});
}else{
oSignature = new sap.m.Image({src: "{value}", width: "7%", height: "7%"});
}
oSignatureTable.bindItems("/", new sap.m.ColumnListItem({
cells : [ new sap.m.Text({text: "{item}"}),
oSignature,]
}));
I have my table empty with "No data".

Since you're getting the value from data.signature only once, that will be the value your template will work with, regardless of whatever values it may have further in your model
A better approach will be to use a HBox as a template, with both an Image and a Text control, and using a formatter (see https://sapui5.hana.ondemand.com/sdk/#docs/guide/a2fe8e763014477e87990ff50657a0d0.html) you toggle the visibility for either of them.
(Forgive me for using XML syntax for the view, as that's my preferred style. But you can adapt to JS View easily):
EDIT: As an exercise for myself, I have created a running Code Snippet below.
// The UI5 controller
sap.ui.controller("view1.initial", {
onInit : function(oEvent) {
// a model with dummy data. Values are either empty or contain a URL
var oModel = new sap.ui.model.json.JSONModel();
oModel.setData({
rows : [
{ value : "sap-icon://syringe", col2 : "Value 2", col3 : "Value 3", ol4 : "Value 4" },
{ value : "", col2 : "Value 6", col3 : "Value 7", col4 : "Value 8" },
{ value : "sap-icon://account", col2 : "Value 10", col3 : "Value 11", col4 : "Value 12" },
{ value : "sap-icon://chalkboard", col2 : "Value 14", col3 : "Value 15", col4 : "Value 16" },
{ value : "sap-icon://e-care", col2 : "Value 18", col3 : "Value 19", col4 : "Value 20" },
{ value : "", col2 : "Value 22", col3 : "Value 23", col4 : "Value 24" }
]
});
this.getView().setModel(oModel);
},
// Formatter for icon visibility
setIconVisible : function (sValue) {
return !!sValue;
},
// Formatter for text visibility
setTextVisible : function (sValue) {
return !sValue;
}
});
// Code needed to place XML view into 'uiArea' DIV element
sap.ui.xmlview("main", {
viewContent: jQuery("#view1").html()
})
.placeAt("uiArea");
<!-- bootstrapper -->
<script id="sap-ui-bootstrap"
src="https://sapui5.hana.ondemand.com/resources/sap-ui-core.js"
data-sap-ui-theme="sap_bluecrystal"
data-sap-ui-xx-bindingSyntax="complex"
data-sap-ui-libs="sap.m"></script>
<!-- here the magic will be shown -->
<div id="uiArea"></div>
<!-- The XMLView definition -->
<script id="view1" type="ui5/xmlview">
<mvc:View
controllerName="view1.initial"
xmlns="sap.m"
xmlns:core="sap.ui.core"
xmlns:mvc="sap.ui.core.mvc" >
<Table id="tbl" inset="true" multiSelect="true" selectionMode="MultiToggle" mode="MultiSelect"
items="{/rows}">
<columns>
<Column>
<Text text="Col1" />
</Column>
<Column>
<Text text="Col2" />
</Column>
<Column>
<Text text="Col3" />
</Column>
</columns>
<items>
<ColumnListItem>
<cells>
<!-- Notice how the cell contains a HBox with an Icon and Text control -->
<!-- Visibility will be toggled using the formatter function for both -->
<HBox>
<core:Icon src="{value}" visible="{path:'value', formatter:'.setIconVisible'}" />
<Text text="No data" visible="{path:'value', formatter:'.setTextVisible'}" />
</HBox>
<Text text="{col2}" />
<Text text="{col3}" />
</cells>
</ColumnListItem>
</items>
</Table>
</mvc:View>
</script>

The problem in my code was the absence of an array in my signatureData object.
After I added the above object into an array which is included in another object, the data appeared in the table.
Here is a working example.
If the value of signature key is a data URL of the image (or a link to it), the image is shown.

Related

How to iterate a nested model and generate Elements based on that

As the title states, I do have a Model, with Choices property which is nested.
let modelExample = {
0: {
"Description": "Example 0",
"Choices": [ "0", "1", "2" ]
},
1: {
"Description": "Example 1",
"Choices": [ "0", "1", "2" ]
},
2: {
"Description": "Example 2",
"Choices": [ "0", "1", "2" ]
}
};
It should construct a Table with Description as a Label and Choices as Buttons, something like:
Table:
<Table items="{modelExample>/}">
<columns>
<Column>
<Text text="Description" />
</Column>
<Column>
<Text text="Choices" />
</Column>
</columns>
<ColumnListItem>
<Label text="{modelExample>Description}" />
<SegmentedButton selectedButton="none">
<items>
<SegmentedButtonItem text="{modelExample>Choices/0}" />
<SegmentedButtonItem text="{modelExample>Choices/1}" />
<SegmentedButtonItem text="{modelExample>Choices/2}" />
</items>
</SegmentedButton>
</ColumnListItem>
</Table>
Issue: As it stands right now, it does work in this way. The problem is that; if you were to extend Choices to 20+ entries, it would also require to add 20+ SegmentedButtonItem, and that is something I try to avoid.
Question: How to generically generate Buttons based on a nested Choices-Property / How to also iterate through nested Choices?
Set your SegementedButton item path to {modelExample>Choices}. The path of your text property in SegmentedButtonItem is modelExample> because there's no key/value in your array.
<SegmentedButton items="{
path: 'modelExample>Choices',
templateShareable: false
}">
<items>
<SegmentedButtonItem text="{modelExample>}" />
</items>
</SegmentedButton>
In case of an array like [{0:"0"},{1:"1"},{2:"2"}] (Your example in your comment isn't valid) you should prepare you're array to receive a static property.
const aArray = [{0:"0"},{1:"1"},{2:"2"}];
const aPreparedArray = aArray.map(oObject =>{ //Loop through array
for(let key in oObject){ //Loop through object
return {propertyName: oObject[key]}; /return object with a static property
}
});
modelExample.setProperty("/", aPreparedArray); //Set array to model
Then you could use:
<SegmentedButton items="{
path: 'modelExample>Choices',
templateShareable: false
}">
<items>
<SegmentedButtonItem text="{modelExample>propertyName}" />
</items>
</SegmentedButton>

Table with Context Binding

I am an intern at SAP, and I am having some problem with Context binding in SAPUI5 for a table in an XML view.
So I am trying to create a dialog panel in SAPUI5 in an XML view so that if I click on a row in a table, then a separate popup/panel should come up above it and display more information about the product I clicked on
I have it working with javascript with:
var details = new sap.m.Panel("details",{
headerText: "This is the {name}",
visible: false,
content: [
new sap.m.Table({
alternateRowColors: true,
fixedLayout: false,
sticky: sap.m.Sticky.ColumnHeaders,
columns:[
new sap.m.Column({
header : new sap.m.Label({
text : "This is the Number of failed Tests: {coverage}"
})
}),
new sap.m.Column({
header : new sap.m.Label({
text : "This is the Number of Bugs: {unitTestCoverage}"
})
}),
new sap.m.Column({
header : new sap.m.Label({
text : "This is the P/F ratio: {unitFirstCoverage}"
})
})
]})
// dataTable
]
});
with in XML I have my details panel as:
<!--Details Panel!-->
<Panel id= "details"
headerText= "This is the {data>name}"
visible= "false">
<content>
<Table>
<columns>
<Column>
<header>
<Label text="This is the Number of failed Tests: {data>coverage}" />
</header>
</Column>
<Column>
<Label text="This is the Number of Bugs: {data>unitTestCoverage}" />
</Column>
<Column>
<Label text="This is the P/F ratio: {data>unitFirstCoverage}" />
</Column>
</columns>
<items>
</items>
</Table>
</content>
</Panel>
I am calling the row within the XML with this snippet:
............
<items>
<ColumnListItem
press= "onItemSelected"
type= "Active">
<cells>
.........
With the controller context binding it with:
onItemSelected: function(oEvent) {
var oSelectedItem = oEvent.getSource();
var sPath = oSelectedItem.getBindingContextPath();
var oProductDetailPanel = this.byId("details");
oProductDetailPanel.bindElement({ path: sPath });
this.byId("details").setVisible(true);
},
I suspect that i am going wrong with how I am trying to call the data in my details panel in XML, and how the data gets binded at the end
try this.
var sPath = oSelectedItem.getBindingContextPath()
with
var sPath = oSelectedItem.getBindingContext('data').getPath()
Alongside:
oProductDetailPanel.bindElement({ path: 'data>' + sPath });

How to Make List Items Reorderable?

I have to create a table (sap.m.Table) in SAPUI5 where rows can be deleted, reordered, and clicked on to open a dialog. So far I've figured out that I can set the Table to mode="delete" and ColumnListItem to type="Navigation" to achieve deleting rows and clicking on rows to open dialogs at the same time:
Is it possible to add the functions to reorder rows to this?
You can use a "editModeEnabled" variable in your view model to change the Table mode to "SingleSelectLeft" and show/hide some buttons. Then in "editMode", use some buttons to insert and remove the items of the table wherever you want
Here a snippet
<html>
<head>
<meta http-equiv='X-UA-Compatible' content='IE=edge'>
<meta charset="utf-8">
<title>MVC with XmlView</title>
<!-- Load UI5, select "blue crystal" theme and the "sap.m" control library -->
<script id='sap-ui-bootstrap' src='https://sapui5.hana.ondemand.com/resources/sap-ui-core.js' data-sap-ui-theme='sap_bluecrystal' data-sap-ui-libs='sap.m' data-sap-ui-xx-bindingSyntax='complex'></script>
<!-- DEFINE RE-USE COMPONENTS - NORMALLY DONE IN SEPARATE FILES -->
<!-- define a new (simple) View type as an XmlView
- using data binding for the Button text
- binding a controller method to the Button's "press" event
- also mixing in some plain HTML
note: typically this would be a standalone file -->
<script id="view1" type="sapui5/xmlview">
<mvc:View xmlns="sap.m" xmlns:mvc="sap.ui.core.mvc" controllerName="my.own.controller">
<Page>
<Table id="myTable" mode="{= ${viewModel>/editModeEnabled} ? 'SingleSelectLeft' : 'SingleSelectMaster'}" items="{path:'json>/rows'}">
<headerToolbar>
<Toolbar>
<ToolbarSpacer></ToolbarSpacer>
<Button text="Edit" press="onEditPressed" visible="{= ${viewModel>/editModeEnabled} ? false : true}"></Button>
<Button icon="sap-icon://slim-arrow-down" press="onDownPressed" visible="{= ${viewModel>/editModeEnabled} ? true : false}"></Button>
<Button icon="sap-icon://slim-arrow-up" press="onUpPressed" visible="{= ${viewModel>/editModeEnabled} ? true : false}"></Button>
<Button text="Finish" press="onFinishEditPressed" visible="{= ${viewModel>/editModeEnabled} ? true : false}"></Button>
</Toolbar>
</headerToolbar>
<columns>
<Column>
<Text text="Column1" />
</Column>
<Column>
<Text text="Column2" />
</Column>
</columns>
<items>
<ColumnListItem>
<Text text="{json>col1}"></Text>
<Text text="{json>col2}"></Text>
</ColumnListItem>
</items>
</Table>
</Page>
</mvc:View>
</script>
<script>
// define a new (simple) Controller type
sap.ui.controller("my.own.controller", {
onInit: function(){
var oViewModelData = {
editModeEnabled: false
};
var oViewModel = new sap.ui.model.json.JSONModel();
this.getView().setModel(oViewModel, "viewModel")
},
onEditPressed: function() {
this.getView().getModel("viewModel").setProperty("/editModeEnabled", true);
},
onFinishEditPressed: function(){
this.getView().getModel("viewModel").setProperty("/editModeEnabled", false);
},
onUpPressed: function(oEvent){
var oSelectedItem = this.getView().byId("myTable").getSelectedItem();
var oCurrentIndex = this.getView().byId("myTable").indexOfItem(oSelectedItem);
if(oCurrentIndex > 0){
this.getView().byId("myTable").removeItem(oSelectedItem);
this.getView().byId("myTable").insertItem(oSelectedItem, oCurrentIndex-1);
}
},
onDownPressed: function(oEvent){
var oSelectedItem = this.getView().byId("myTable").getSelectedItem();
var oCurrentIndex = this.getView().byId("myTable").indexOfItem(oSelectedItem);
if(oCurrentIndex < this.getView().byId("myTable").getItems().length){
this.getView().byId("myTable").removeItem(oSelectedItem);
this.getView().byId("myTable").insertItem(oSelectedItem, oCurrentIndex+1);
}
}
});
/*** THIS IS THE "APPLICATION" CODE ***/
// create a Model and assign it to the View
//Using a small JSON model
var myData = {
rows: [
{
col1: "Row1Col1",
col2: "Row1Col2",
},{
col1: "Row2Col1",
col2: "Row2Col2",
},{
col1: "Row3Col1",
col2: "Row3Col2",
}
]
};
var oJSONModel = new sap.ui.model.json.JSONModel(myData);
// instantiate the View
var myView = sap.ui.xmlview({
viewContent: jQuery('#view1').html()
}); // accessing the HTML inside the script tag above
// Set the Models
myView.setModel(oJSONModel, 'json');
myView.placeAt('content');
</script>
</head>
<body id='content' class='sapUiBody'>
</body>
</html>

Get selected item from sap.m.Select from a sapui5 table column

I am using sap.m.Table, where I have 3 columns, as sap.m.text, sap.m.setect and the last one is button.
My model code
var oModel = new sap.ui.model.odata.OData("url");
sap.ui.getCore().setModel(oModel ,"data");
Table view code(cells)
var oTemplate = new sap.m.ColumnListItem({
cells : [
new sap.m.Text({
text: "{data>Address}"
}),
new sap.m.Select({
id:"sel",
items: {
path: "data>/OPERATORS", // this is a diffent table
template: new sap.ui.core.Item({
text: "{data>firstName} {data>lastName}"
})
},
forceSelection: false
}),
new sap.m.Button({
text : "Start",
press : [oController.onPressStart, oController]
})
]
});
oTable.bindItems("data>/ORDR", oTemplate); //differnt table
Working fine, getting all required data on the specific table.(Notice first column is coming from ORDR table and second one is coming from OPERATORS table).
Now on button click I wanted the specific row data. My code as follows -
onPressStart : function(oEvent){
var obj = oEvent.getSource().getBindingContext("data").getObject();
},
"obj" gives me ORDR table row objects(where I pressed the button).
Now I also want the value I will select on the dropdown box. How to get it.
Please suggest, Thank you
JSbin Link - http://jsbin.com/quhomoloqo/edit?html,console,output
See this working example:
Please note how (for the sake of this question) created two models:
One named 'orig' which holds your original OPERATOR and ODRD data, and
one named 'data' which holds a copy of the OPERATOR data, with an added Address property.
See the view code on how the two models are used (the new one for the table, the old one for populating the dropdown)
sap.ui.controller("view1.initial", {
onInit : function(oEvent) {
},
onAfterRendering : function() {
// your original model
var oModel = new sap.ui.model.json.JSONModel();
var oData = {
"ODRD":[
{"Address":"UK"},
{"Address":"US"}
],
"OPERATORS":[
{"firstName":"a","lastName":"b"},
{"firstName":"c","lastName":"d"}
]
};
oModel.setData(oData);
this.getView().setModel(oModel, "orig");
// the model you actually need
var oNewModel = new sap.ui.model.json.JSONModel();
var oNewData = oData.OPERATORS.map(function(result) {
return {
firstName : result.firstName,
lastName : result.lastName,
keyToAddress : null
}
})
oNewModel.setData({
"OPERATORS" : oNewData
});
this.getView().setModel(oNewModel, "data");
},
showData : function(oEvent) {
alert(JSON.stringify(oEvent.getSource().getBindingContext("data").getObject()));
}
});
sap.ui.xmlview("main", {
viewContent: jQuery("#view1").html()
})
.placeAt("uiArea");
<script id="sap-ui-bootstrap"
src="https://sapui5.hana.ondemand.com/resources/sap-ui-core.js"
data-sap-ui-theme="sap_bluecrystal"
data-sap-ui-xx-bindingSyntax="complex"
data-sap-ui-libs="sap.m"></script>
<div id="uiArea"></div>
<script id="view1" type="ui5/xmlview">
<mvc:View
controllerName="view1.initial"
xmlns="sap.m"
xmlns:core="sap.ui.core"
xmlns:mvc="sap.ui.core.mvc" >
<Table id="tbl" items="{data>/OPERATORS}">
<columns>
<Column>
<Text text="First" />
</Column>
<Column>
<Text text="Last" />
</Column>
<Column>
<Text text="ODRD" />
</Column>
<Column>
<Text text="" />
</Column>
</columns>
<items>
<ColumnListItem>
<cells>
<Input value="{data>firstName}" />
<Input value="{data>lastName}" />
<Select items="{orig>/ODRD}" selectedKey="{data>keyToAddress}">
<items>
<core:ListItem key="{orig>Address}" text="{orig>Address}" />
</items>
</Select>
<Button text="Show data" press="showData" />
</cells>
</ColumnListItem>
</items>
</Table>
</mvc:View>
</script>

sap.ui.table - FilterType on Column not working

The filterType property of sap.ui.table.Column does not appear to work for me. Here is my code:
<table:Column sortProperty="abc" filterProperty="abc" filterType="sap.ui.model.type.Integer">
<table:label>
<Label text="abc"></Label>
</table:label>
<table:template>
<Label text="{modelName>abc}"></Label>
</table:template>
</table:Column>
abc is containing a number as a string e.g. "10". The values are showing in the table so the bindings are correct.
Sorting also works but it does not respect the Integer type. I still get a String like sorting so that the entry "6" shows after "10" for an ascending sort. The column is even returning the filterType I set if I do sap.ui.getCore().byId("columnId").getFilterType(); What the heck is wrong here?
BR
Chris
It is working for the code snippet. You can click the column header to sort by descending or ascending and filter value.Please check.
<script id='sap-ui-bootstrap' type='text/javascript' src='https://sapui5.hana.ondemand.com/resources/sap-ui-core.js' data-sap-ui-libs="sap.m,sap.ui.commons,sap.ui.table,sap.viz" data-sap-ui-theme="sap_bluecrystal"></script>
<script id="view1" type="sapui5/xmlview">
<mvc:View xmlns:core="sap.ui.core" xmlns:layout="sap.ui.commons.layout" xmlns:mvc="sap.ui.core.mvc" xmlns="sap.ui.commons" xmlns:table="sap.ui.table" controllerName="my.own.controller" xmlns:html="http://www.w3.org/1999/xhtml">
<table:Table id="testTable" rows="{/}">
<table:Column sortProperty="abc" filterProperty="abc" filterType="sap.ui.model.type.Integer">
<table:label>
<Label text="abc"></Label>
</table:label>
<table:template>
<Label text="{abc}"></Label>
</table:template>
</table:Column>
<table:Column>
<table:label>
<Label text="abc2"></Label>
</table:label>
<table:template>
<Label text="{abc2}"></Label>
</table:template>
</table:Column>
</table:Table>
</mvc:View>
</script>
<script>
sap.ui.controller("my.own.controller", {
onInit: function() {
var aTableData = [{
abc: 1,
abc2: "a"
}, {
abc: 6,
abc2: "b"
}, {
abc: 10,
abc2: "c"
}, {
abc: 3,
abc2: "g"
}, {
abc: 12,
abc2: "h"
}];
var oTableModel = new sap.ui.model.json.JSONModel();
oTableModel.setData(aTableData);
var oTable = this.getView().byId("testTable");
oTable.setModel(oTableModel);
oTable.sort(oTable.getColumns()[0]);
}
});
var myView = sap.ui.xmlview("myView", {
viewContent: jQuery('#view1').html()
}); //
myView.placeAt('content');
</script>
</head>
<body class='sapUiBody'>
<div id='content'></div>
</body>
To finally answer this: The filterType is NOT taken into account for sorting, no matter which view type you use. If you also think there should be a way to easily influence the sort logic you can support the issue here: https://github.com/SAP/openui5/issues/192