SapUi5 write text in many rows one under another without : - sapui5

I am trying to achive something like this in SapUi5:
First row
Second row
Third row
Fourth row
and actually all I can do is:
First Row:
Second row:
Third row:
Fourth row:
when I used:
<f:FormElement label="First Row"/>
<f:FormElement label="Second row"/>
<f:FormElement label="Third row"/>
<f:FormElement label="Fourth row"/>
Is there any chance to remove :? Should I use something other than label?

Option 1:
You can use a sap.ui.layout.VerticalLayout. As for the actual elements, a Label is normally more used as a caption to another element, like a form field or a table column. So for general text, you want to use sap.m.Text.
Sample (ignore the boilerplate of the XMLview creation):
sap.ui.require(["sap/ui/core/mvc/XMLView"], function(XMLView) {
XMLView.create({
definition: $('#myView').html()
}).then(function(oView) {
oView.placeAt('content');
});
});
<html>
<head>
<meta charset="utf-8">
<script id='sap-ui-bootstrap' src='https://sapui5.hana.ondemand.com/resources/sap-ui-core.js' data-sap-ui-libs='sap.m,sap.ui.layout'></script>
<script id="myView" type="sapui5/xmlview">
<mvc:View xmlns:mvc="sap.ui.core.mvc" xmlns="sap.m" xmlns:l="sap.ui.layout">
<Panel headerText="My Panel">
<l:VerticalLayout>
<Text text="First row" />
<Text text="Second row" />
<Text text="Third row" />
<Text text="Fourth row" />
</l:VerticalLayout>
</Panel>
</mvc:View>
</script>
</head>
<body class='sapUiBody'><div id='content'></div></body>
</html>
Option 2:
Put the text inside a proper Text instead of the label, eg:
<f:FormElement><Text text="First row" /></f:FormElement>
Option 3:
Hide the colon with CSS, but in this case you should prefer the other options since label is not meant to just display some independent text.

Using CSS
.sapUiForm.sapUiFormLblColon .sapUiFormElementLbl>.sapMLabel {
content: "" !important;
}
If you don't want to override the default CSS for all the form, you can give custom class to the form(like testForm) so that you can use the CSS to override only for the specific form.
.testForm.sapUiForm.sapUiFormLblColon .sapUiFormElementLbl>.sapMLabel {
content: "" !important;
}

Related

How to make out of input field a hyperlink?

As the title states, I would like to make out of an input a clickable hyperlink.
Code:
<Label text="Stackoverflow" />
<Input enabled="true" editable="false" name="Stackoverflow" value="Example" />
Issue: I want to display Example in the input as value, however, when clicking on the Example - to take you to stackoverflow.com.
Question: How to make it possible?
Without knowing what the use of the links are, generally, sap.m.InputBase controls can contain links within the value state message (Since 1.78).
sap.ui.getCore().attachInit(() => sap.ui.require([
"sap/ui/core/Fragment"
], Fragment => Fragment.load({
definition: `<Input xmlns="sap.m"
width="12rem"
valueState="Information"
placeholder="Input with links"
class="sapUiTinyMargin">
<formattedValueStateText>
<FormattedText htmlText="See %%0 and %%1.">
<controls>
<Link text="Link 1" press="alert('Link 1 clicked!')" />
<Link text="Link 2" press="alert('Link 2 clicked!')" />
</controls>
</FormattedText>
</formattedValueStateText>
</Input>`,
}).then(control => control.placeAt("content"))));
<script id="sap-ui-bootstrap"
src="https://openui5.hana.ondemand.com/resources/sap-ui-core.js"
data-sap-ui-libs="sap.ui.core, sap.m"
data-sap-ui-async="true"
data-sap-ui-theme="sap_fiori_3"
data-sap-ui-compatversion="edge"
data-sap-ui-excludejquerycompat="true"
data-sap-ui-xx-waitfortheme="init"
></script>
<body id="content" class="sapUiBody"></body>
Even if a link or button would be the better solution, here is my suggestion:
XML with custom attribute "url"
<Input enabled="true" editable="false" id="idInputStack" name="Stackoverflow" value="Example">
<customData>
<core:CustomData key="url" value="https://www.stackoverflow.com" writeToDom="true" />
</customData>
</Input>
Controller:
var oInput = this.getView().byId("idInputStack");
oInput.addEventDelegate({
onclick: function() {
document.location.href = oInput.data("url"); //get custom attribute url
}
})
First we would provide an id to the Input control so that we could refer to the same from the controller.
<Input enabled="true" editable="false" name="Stackoverflow" value="Example" id="myInputLinkId"/>
Now we could add the typical user click event to the Input field by attaching a Browser event to the same and place it in the onInit() hook method so that it is always accessible.
onInit: function () {
this.getView().byId("myInputLinkId").attachBrowserEvent('click',function(){ window.open("https://stackoverflow.com/");});
}

How can I bind a single property of my OData service to a Form?

Will you please tell me how to refer to the first tabular (and single) record?
There is a table with only one record:
<Table items="{WaybillsPlaces}" mode="SingleSelectMaster">
<columns>
<Column hAlign="Center">
<header>
<Text text="Number" />
</header>
</Column>
</columns>
<items>
<ColumnListItem>
<cells>
<Text text="{CoNumber}" />
</cells>
</ColumnListItem>
</items>
</Table>
How can I read the field of the first record without a table?
<Text text="{WaybillsPlaces[0]/>CoNumber}"/>
I get a table reply, but I do not want to display it in the table - I want to display it in the form in text boxes, so there will always be one line in the response.
<entry>
<id>
http://xxxxx.xxx.local:8000/sap/opu/odata/sap/LOGISTICS_SRV/WaybillsPlaces('4610103052')
</id>
<title type="text">WaybillsPlaces('4610103052')</title>
<updated></updated>
<content type="application/xml">
<m:properties xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata" xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices">
<d:CoNumber>46101030520001</d:CoNumber>
</m:properties>
</content>
</entry>
EDIT (As #Denis description in the comments):
I have an OData giving me the following entry
<entry>
<id>
http://xxxxx.xxx.local:8000/sap/opu/odata/sap/LOGISTICS_SRV/WaybillsPlaces('4610103052')
</id>
<title type="text">WaybillsPlaces('4610103052')</title>
<updated></updated>
<content type="application/xml">
<m:properties xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata" xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices">
<d:CoNumber>46101030520001</d:CoNumber>
</m:properties>
</content>
</entry>
How can I bind the CoNumber property with a Input within a From ??
give and ID to your table, get the table in your controller and call its 'getItems()' method. Then get the first object in the returned array:
In your view
<Table id="myTable" items="{WaybillsPlaces}" mode="SingleSelectMaster">
<columns>
<Column hAlign="Center">
<header>
<Text text="Number" />
</header>
</Column>
</columns>
<items>
<ColumnListItem>
<cells>
<Text text="{CoNumber}" />
</cells>
</ColumnListItem>
</items>
</Table>
In your controller
onCertainEvent(evt){
var oTable = this.getView().byId('myTable');
var oFirstItem = oTable.getItems()[0]; // This is your ColumnListItem object in the first row
var oFirstCellItem = oFirstItem.getCells()[0]; // This is your Text object in the first cell of the first row
var sCellText = oFirstCellItem.getText(); // This is the text string in your first cell of the first row
}
EDIT: bind only the first item in your model
In this case you can do aggregation binding. For aggregation binding you need multiplicity greater than 1. So do property binding in yout ColumnListItem with WaybillsPlaces/0/CoNumber
<Table id="myTable" mode="SingleSelectMaster">
<columns>
<Column hAlign="Center">
<header>
<Text text="Number" />
</header>
</Column>
</columns>
<items>
<ColumnListItem>
<cells>
<Text text="{WaybillsPlaces/0/CoNumber}" />
</cells>
</ColumnListItem>
</items>
</Table>
EDIT: Data Binding options in certain events
<!DOCTYPE html>
<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
controllerName="my.own.controller"
xmlns:l="sap.ui.layout"
xmlns:core="sap.ui.core"
xmlns:mvc="sap.ui.core.mvc"
xmlns:f="sap.ui.layout.form"
xmlns="sap.m">
<Panel headerText="Table Panel">
<Table id="myTable" items="{/WaybillsPlaces}" mode="SingleSelectMaster" select="onRowPressed" updateFinished="onUpdateFinished">
<columns>
<Column hAlign="Center">
<header>
<Text text="Number" />
</header>
</Column>
</columns>
<items>
<ColumnListItem>
<cells>
<Text text="{CoNumber}" />
</cells>
</ColumnListItem>
</items>
</Table>
</Panel>
<Panel id="Panel1" headerText="onAfterRendering Data Binding">
<Label text="First Item - Property binding:"></Label>
<Input id="Input1"></Input>
<Label text="First Item - Element binding:"></Label>
<Input value="{CoNumber}"></Input>
</Panel>
<Panel id="Panel2" headerText="onUpdateFinished Data Binding">
<Label text="First Item - Property binding:"></Label>
<Input id="Input2"></Input>
<Label text="First Item - Element binding:"></Label>
<Input value="{CoNumber}"></Input>
</Panel>
<Panel id="Panel3" headerText="onRowPressed Data Binding">
<Label text="Selected Item - Property binding:"></Label>
<Input id="Input3"></Input>
<Label text="Selected Item - Element binding:"></Label>
<Input value="{CoNumber}"></Input>
</Panel>
</mvc:View>
</script>
<script>
// define a new (simple) Controller type
sap.ui.controller("my.own.controller", {
onAfterRendering: function(){
var oTable = this.getView().byId('myTable');
var oFirstItem = oTable.getItems()[0]; // This is your ColumnListItem object in the first row
var oFirstCellItem = oFirstItem.getCells()[0]; // This is your Text object in the first cell of the first row
var sFirstItemDataPath = oFirstCellItem.getBindingContext().getPath();
this.getView().byId("Input1").bindProperty("value", sFirstItemDataPath + "/CoNumber");
this.getView().byId("Panel1").bindElement(sFirstItemDataPath);
},
onUpdateFinished: function(oEvent){
var oTable = oEvent.getSource();
var oFirstItem = oTable.getItems()[0]; // This is your ColumnListItem object in the first row
var oFirstCellItem = oFirstItem.getCells()[0]; // This is your Text object in the first cell of the first row
var sFirstItemDataPath = oFirstCellItem.getBindingContext().getPath();
this.getView().byId("Input2").bindProperty("value", sFirstItemDataPath + "/CoNumber");
this.getView().byId("Panel2").bindElement(sFirstItemDataPath);
},
onRowPressed: function(oEvent){
var oFirstItem = oEvent.getParameter("listItem"); // This is the pressed ColumnListItem object
var oFirstCellItem = oFirstItem.getCells()[0]; // This is your Text object in the first cell of the pressed row
var sFirstItemDataPath = oFirstCellItem.getBindingContext().getPath();
this.getView().byId("Input3").bindProperty("value", sFirstItemDataPath + "/CoNumber");
this.getView().byId("Panel3").bindElement(sFirstItemDataPath);
}
});
// instantiate the View
var myView = sap.ui.xmlview({viewContent:jQuery('#view1').html()}); // accessing the HTML inside the script tag above
// create some dummy JSON data
var data = {
WaybillsPlaces: [{
CoNumber: "Item 1",
},{
CoNumber: "Item 2",
},{
CoNumber: "Item 3",
}]
};
// create a Model and assign it to the View
var oModel = new sap.ui.model.json.JSONModel();
oModel.setData(data);
myView.setModel(oModel);
// put the View onto the screen
myView.placeAt('content');
</script>
</head>
<body id='content' class='sapUiBody'>
</body>
</html>
EDIT2: Bind a form input to a certain property in a OData Model
Here I'm gonna use Northwind OData service, for ease of use, but you just need to use your own model. I used the "Customers" entitySet (a.k.a "Customers" DB table), and the "CustomerName" property in this entitySet.
In your case (as per the given OData in the description, you should use the 'WaybillsPlaces' entity and your 'CoNumber' property. If you want to access one specific entry, provide the Key between parenthesis in the binding URL (in your case: WaybillsPlaces('4610103052')).
I highly recommend you to read more about OData binding in UI5 (here and here). In a productive application, please set your OData model in the manifest.json file, to be sure that the $metadata call is done when the application starts, avoiding this way performance and many other issues.
HERE THE SNIPPET

Concatenate data contained in a JSONModel

I am looking for a code, which allows me to concatenate two JSONModel attributes and then map to a table. For example if my JSON looks something like this.
[
{"FirstName","James", "LastName","Bond"},
{"FirstName","Robin", "LastName","Hood"},
{"FirstName","Peter", "LastName","Parker"}
]
I want my SAP UI table column to look something like
<table border=1>
<tr><th>Name</th></tr>
<tr><td>James Bond </td></tr>
<tr><td>Robin Hood </td></tr>
<tr><td>Peter Parker </td></tr>
</table>
First you have to put your json data into a model and assign that to your view or table (beware that your json data has syntax errors. below is the corrected version):
onInit:function(){
var data = [
{"FirstName":"James", "LastName":"Bond"},
{"FirstName":"Robin", "LastName":"Hood"},
{"FirstName":"Peter", "LastName":"Parker"}
];
this.getView().setModel(new sap.ui.model.json.JSONModel(data));
}
Second you need something like a table:
<t:Table rows="{/}">
<t:Column>
<Label text="Full Name"/>
<t:template>
<Label text="{FirstName} {LastName}"/>
</t:template>
</t:Column>
</t:Table>
The table binds its aggregation rows to your array (path '/'). For each item in the array the template will be cloned and displayed. The template is a label that displays firstname and lastname separated by space: Two databindings with relative path (relative to the array item of the row).
For this to work, you need to enable the "complex databinding" feature in the bootstrap script tag:
<script src="https://openui5.hana.ondemand.com/1.32.7/resources/sap-ui-core.js"
id="sap-ui-bootstrap"
data-sap-ui-theme="sap_bluecrystal"
data-sap-ui-libs="sap.m"
data-sap-ui-bindingSyntax="complex"></script>
You could also enable complex databinding by setting the required ui5 version to something up to date (or "edge" which is the newest available): data-sap-ui-compatVersion="edge"
sap.ui.core.mvc.Controller.extend("view1", {
onInit:function(){
var data = [
{"FirstName":"James", "LastName":"Bond"},
{"FirstName":"Robin", "LastName":"Hood"},
{"FirstName":"Peter", "LastName":"Parker"}
];
this.getView().setModel(new sap.ui.model.json.JSONModel(data));
}
});
var view = sap.ui.xmlview({viewContent: $("#view1").html()});
view.placeAt("content");
<script src="https://openui5.hana.ondemand.com/1.32.7/resources/sap-ui-core.js"
id="sap-ui-bootstrap"
data-sap-ui-theme="sap_bluecrystal"
data-sap-ui-libs="sap.m"
data-sap-ui-bindingSyntax="complex"></script>
<script type="sapui5/xmlview" id="view1">
<mvc:View xmlns="sap.m" xmlns:mvc="sap.ui.core.mvc" xmlns:t="sap.ui.table" controllerName="view1">
<t:Table rows="{/}">
<t:Column>
<Label text="Full Name"/>
<t:template>
<Label text="{FirstName} {LastName}"/>
</t:template>
</t:Column>
</t:Table>
</mvc:View>
</script>
<div id="content"></div>

How can I put icon and text in select items

I have an sap.m.Select control for a list of countries and I need to put flag near everyone. How can I do it? In XML, if it's possible.
Here is my XML code:
<m:Label text="{i18n>COUNTRY}" />
<m:Select width="100px"
fieldWidth="60%"
class="xcuiInputNoMargin"
enabled="{Edit>/EditOn}"
items="{countryList>/}"
>
<core:Item
key="{countryList>Country}"
text="{countryList>Country} - {countryList>Name}"
/>
</m:Select>
The sap.m.Select Object is restricted to display text (or Like #Jasper_07 said) icon only.
I think that the best solution for your problem is to use another object instead of your select. You can use Select Dialog and put inside whatever you want, like listItem with image.
This is an example:
<SelectDialog
noDataText="No Products Found"
title="Select Product"
search="handleSearch"
confirm="handleClose"
close="handleClose"
items="{
path: '/ProductCollection'
}" >
<StandardListItem
title="{Name}"
description="{ProductId}"
icon="{ProductPicUrl}"
iconDensityAware="false"
iconInset="false"
type="Active" />
</SelectDialog>
see link bellow
As of UI5 version 1.62, the following controls support displaying the icon on the left side.
sap.m.Select
sap.m.SelectList
And other controls based on the above mentioned ones, such as sap.m.ComboBox.
Here is an example:
sap.ui.getCore().attachInit(() => sap.ui.require([
"sap/ui/core/mvc/XMLView",
], XMLView => XMLView.create({
definition: `<mvc:View xmlns:mvc="sap.ui.core.mvc" height="100%">
<Select xmlns="sap.m" xmlns:core="sap.ui.core" class="sapUiTinyMargin">
<core:ListItem text="Paper plane" icon="sap-icon://paper-plane" />
<core:ListItem text="Stop Watch" icon="sap-icon://fob-watch" />
<core:ListItem text="Umbrella" icon="sap-icon://umbrella" />
</Select>
</mvc:View>`
}).then(view => view.placeAt("content"))));
<script id="sap-ui-bootstrap"
src="https://openui5nightly.hana.ondemand.com/resources/sap-ui-core.js"
data-sap-ui-libs="sap.ui.core, sap.m"
data-sap-ui-preload="async"
data-sap-ui-async="true"
data-sap-ui-theme="sap_belize"
data-sap-ui-compatversion="edge"
data-sap-ui-xx-waitfortheme="true"
data-sap-ui-xx-xml-processing="sequential"
></script>
<body id="content" class="sapUiBody sapUiSizeCompact"></body>
Keep in mind to use sap.ui.ListItem as an aggregation child in this case, instead of sap.ui.core.Item.
Limitation
Currently, the icon property only allows resource paths from "sap-icon://*". I.e. images, that are not icons such as country flags, are not possible. A possible workaround would be to make use of emoji flags as additionalText.
Otherwise, I'd recommend to look for alternative controls as shmoolki suggested.
from the documentation of sap.m.Select
The URI to the icon that will be displayed only when using the
IconOnly type
seems limiting, but try
<m:Select
type="sap.m.SelectType.IconOnly"
icon="sap-icon://cart">
</m:Select>

Strange sap.m.TextArea behavior inside a sap.m.List

I'm using sap.m.TextArea control inside sap.m.List where the values of each TextArea were mapped to a JSONModel. Here is the xml-view code:
<List id="otherPicList" growing="true" items="{ path : 'newRequest>/OtherPic' }" >
<items>
<CustomListItem type="Inactive">
<Image id="otherPic" src="{newRequest>pic}" width="90px" height="60px" />
<VBox>
<TextArea value="{newRequest>text}"/>
</VBox>
</CustomListItem>
</items>
</List>
When I start to type inside the sap.m.TextArea it freezes after the first character. I can only type one more character if I click outside the control and inside again. I think this bug happen because of the data binding inside a sap.m.List control.
If I set the value property without the model binding it works just fine. Is this a known bug or am I using wrong the control?
Data binding and growing list are not smart enough:
After the value of text area is changed and updated on the input event (after the key stroke), data binding is updated with the following diff:
1 item is deleted
2 item is updated
Growing List listens to data model change and does exactly the same: it deletes the changed item and creates it again.
When the text area inside of list item is deleted from DOM, focus is lost. The new text area does not get focus and any subsequent keystroke goes to nowhere.
I will report this issue to development.
It is working for my code snippet. Please run and check. Maybe there is something else causing your issue.
<script src="https://openui5.hana.ondemand.com/resources/sap-ui-core.js" id="sap-ui-bootstrap" data-sap-ui-theme="sap_bluecrystal" data-sap-ui-libs="sap.m,sap.ui.commons"></script>
<!-- define an XMLView - normally done in a separate file -->
<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.m"
controllerName="my.own.controller" xmlns:html="http://www.w3.org/1999/xhtml">
<List id="otherPicList" items="{/test}" >
<items>
<CustomListItem type="Inactive">
<Image id="otherPic" src="{pic}" width="90px" height="60px" />
<VBox>
<TextArea value="{text}"/>
</VBox>
</CustomListItem>
</items>
</List>
</mvc:View>
</script>
<script>
sap.ui.controller("my.own.controller", {
onInit:function() {
var data = {test:[{text:"123",pic:"https://www.gravatar.com/avatar/e25560c87abbbb90143653d98c9924dc?s=128&d=identicon&r=PG"},{text:"456",pic:"https://www.gravatar.com/avatar/e25560c87abbbb90143653d98c9924dc?s=128&d=identicon&r=PG"},{text:"789",pic:"https://www.gravatar.com/avatar/e25560c87abbbb90143653d98c9924dc?s=128&d=identicon&r=PG"},{text:"101112",pic:"https://www.gravatar.com/avatar/e25560c87abbbb90143653d98c9924dc?s=128&d=identicon&r=PG"}]};
var oModel = new sap.ui.model.json.JSONModel();
oModel.setData(data);
this.getView().setModel(oModel);
}
});
var myView = sap.ui.xmlview("myView", {viewContent:jQuery('#view1').html()}); //
myView.placeAt('content');
</script>
<body class='sapUiBody'>
<div id='content'></div>
</body>
I found out the problem, check out your code snippet including the property growing="true" inside the sap.m.List control. This property cause the strange behavior I was talking about.
<script src="https://openui5.hana.ondemand.com/resources/sap-ui-core.js" id="sap-ui-bootstrap" data-sap-ui-theme="sap_bluecrystal" data-sap-ui-libs="sap.m,sap.ui.commons"></script>
<!-- define an XMLView - normally done in a separate file -->
<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.m"
controllerName="my.own.controller" xmlns:html="http://www.w3.org/1999/xhtml">
<List id="otherPicList" growing="true" items="{/test}" >
<items>
<CustomListItem type="Inactive">
<Image id="otherPic" src="{pic}" width="90px" height="60px" />
<VBox>
<TextArea value="{text}"/>
</VBox>
</CustomListItem>
</items>
</List>
</mvc:View>
</script>
<script>
sap.ui.controller("my.own.controller", {
onInit:function() {
var data = {test:[{text:"123",pic:"https://www.gravatar.com/avatar/e25560c87abbbb90143653d98c9924dc?s=128&d=identicon&r=PG"},{text:"456",pic:"https://www.gravatar.com/avatar/e25560c87abbbb90143653d98c9924dc?s=128&d=identicon&r=PG"},{text:"789",pic:"https://www.gravatar.com/avatar/e25560c87abbbb90143653d98c9924dc?s=128&d=identicon&r=PG"},{text:"101112",pic:"https://www.gravatar.com/avatar/e25560c87abbbb90143653d98c9924dc?s=128&d=identicon&r=PG"}]};
var oModel = new sap.ui.model.json.JSONModel();
oModel.setData(data);
this.getView().setModel(oModel);
}
});
var myView = sap.ui.xmlview("myView", {viewContent:jQuery('#view1').html()}); //
myView.placeAt('content');
</script>
<body class='sapUiBody'>
<div id='content'></div>
</body>