sap.ui.table.Column Regards Only Last Control and Expression Binding Doesn't Work - sapui5

I have a column in a sap.ui.table.Table. In this column, I want to display my template control depending on the value. If I have a typeof DateTime, I want to use the DatePicker, typeof DateTime a DateTimePicker, and so on.
Now I want to differ it in my XMLView / Fragment but it only checks my last control (DateTimePicker):
<table:template>
<Input id="masterDataValueInput"
value="{thingDetail>value}"
placeholder="{path:'thingDetail>type', formatter:'.formatter.placeHolderFormatter'}"
visible="{= ! ${path: 'thingDetail>properties'} && ${path: 'thingDetail>type', formatter: '.formatter.inputVisibility'}}"
enabled="{appView>/isCurrentTenant}"
type="{path:'thingDetail>type', formatter:'.formatter.inputTypeFormatter'}"
/>
<DatePicker id="masterDataValueDate"
value="{thingDetail>value}"
displayFormat="short"
visible="{= ! ${path: 'thingDetail>properties'} && ${path: 'thingDetail>type', formatter: '.formatter.dateVisibility'}}"
enabled="{appView>/isCurrentTenant}"
change="handleChange"
/>
<DateTimePicker id="masterDataValueDateTime"
value="{thingDetail>value}"
displayFormat="short"
visible="{= ! ${path: 'thingDetail>properties'} && ${path: 'thingDetail>type', formatter: '.formatter.datetimeVisibility'}}"
enabled="{appView>/isCurrentTenant}"
change="handleChange"
/>
</table:template>
So the <Input> and the <DatePicker> controls are never displayed..
The methods in my formatter are never called either.

The reason why only the last control (DateTimePicker) is taken into account is because the template aggregation of sap.ui.table.Column awaits only a single control (0..1).
In order to make use of all three controls, you'll have to wrap them together in another container / layout control such as HorizontalLayout:
<table:template>
<layout:HorizontalLayout>
<!-- your controls -->
</layout:HorizontalLayout>
<table:template>
About the expression binding..
Try with parts:
visible="{= !${thingDetail>properties} && ${parts: [{path: 'thingDetail>type'}], formatter: '.formatter.inputVisibility'}}"
If that didn't call the formatter, toss that expression binding (as it's become hard to read anyway) and go for the usual property binding with the appropriate formatter:
visible="{
parts: [
'thingDetail>properties',
'thingDetail>type'
],
formatter: '.formatter.myFormatter'
}"

Related

How can I create a single Datepicker in svelte with carbon-components with german locale

When I try to use the "Datepicker" in svelte with carbon-components I can configure the output to be set in a german locale style but after sending the form, the datepicker only shows "Please match the requested format." I am missing something but I really don`t now what I am missing.
Here is my code
<script lang="ts">
import { DataTable, DatePicker, DatePickerInput, NumberInput, Grid, Row, Column, Button, FluidForm } from "carbon-components-svelte";
let datum: Date;
</script>
<Grid>
<Row>
<Column>
<form>
<DatePicker
format="de-CH"
dateFormat="d.m.Y"
locale="de"
datePickerType="single"
flatpickrProps={
{
locale:
{firstDayOfWeek: 1},
dateFormat: "d.m.Y",
}
}
on:change bind:value={datum}
>
<DatePickerInput labelText="Datum" placeholder="dd.mm.yyyy" />
</DatePicker>
<Button size="small" type="submit">Submit</Button>
</form>
</Column>
</Row>
</Grid>
Screenshot of the error message:
When I remove the formatting stuff, the form works and the date is getting send.
This is a example without formatting with german locale
<script lang="ts">
import { DataTable, DatePicker, DatePickerInput, NumberInput, Grid, Row, Column, Button, FluidForm } from "carbon-components-svelte";
let datum: Date;
</script>
<Grid>
<Row>
<Column>
<form>
<DatePicker
datePickerType="single"
flatpickrProps={
{
locale:
{firstDayOfWeek: 1},
}
}
on:change bind:value={datum}
>
<DatePickerInput labelText="Datum" placeholder="dd.mm.yyyy" />
</DatePicker>
<Button size="small" type="submit">Submit</Button>
</form>
</Column>
</Row>
</Grid>
What am I missing? How can I use german locale with a german date format without getting the Error "Please match the requested format."?
These locale settings consist of various direct props that should be set:
DatePicker: locale & dateFormat
DatePickerInput: pattern
The flatpickr package also provides a large set of locales, I would recommend passing the German one directly to get day and month names.
import { German } from 'flatpickr/dist/l10n/de.js'; // there also is an ESM dir
<DatePicker locale={German} dateFormat="d.m.Y" ...>
<DatePickerInput pattern={'\\d{2}\\.\\d{2}\\.\\d{4}'} .../>
</DatePicker>
REPL
The pattern determines the regular expression used to check the value, so that has to match the input/dateFormat. (Pattern is passed in a string because of the curly braces within, which would cause Svelte to interpolate the number literals otherwise.)

SAP UI5 : Unable to bind a controller variable in xml

Button on click of which the variable is getting changed:
<f:content>
<Button icon="sap-icon://edit" press="editClick" type="Transparent"></Button>
</f:content>
xml code where i need 2-way binding:
<VBox class="sapUiSmallMargin">
<form:SimpleForm id="SimpleFormDisplayColumn_oneGroup">
<form:content>
<Label text="{i18n>contextofusage}"/>
<Text text="{contextofusagetext}" visible="{!isInfoEditable}"/>
<Input type="Text" visible="{isInfoEditable}" value="{contextofusagetext}"></Input>
</form:content>
</form:SimpleForm>
</VBox>
controller:
var isInfoEditable=false;
return Controller.extend("abc.controller.Detail", {
editInfoClick: function(event){
if(isInfoEditable){
isInfoEditable=false;
}
else{
isInfoEditable=true;
}
}
});
It seems like you have tried nothing, but I will try to guide you:
You cannot simply declare a variable in your controller and then use it in your view. That's not how UI5 works. Instead create a model and bind it to your view. I also give my models a name, in this case "view":
onInit: function() {
var oViewModel = new sap.ui.model.json.JSONModel({
isInfoEditable: false
});
this.getView().setModel(oViewModel, "view");
}
Then use it in your view. Make sure that you use the name of your model ("view") in your bindings. If you want to do more than simply use the raw value (e.g. negate it) you have to use expression binding. Also you have to use an absolute path starting with /:
<form:SimpleForm id="SimpleFormDisplayColumn_oneGroup">
<form:content>
<Label text="{i18n>contextofusage}"/>
<Text text="{contextofusagetext}" visible="{= !${view>/isInfoEditable} }"/>
<Input type="Text" visible="{view>/isInfoEditable}" value="{contextofusagetext}"></Input>
</form:content>
</form:SimpleForm>
When you click on the button you have to modify/toggle the value in your model:
editClick: function (oEvent) {
var oViewModel = this.getView().getModel("view");
var bIsEditable = oViewModel.getProperty("/isInfoEditable");
// negate the current value and set it as the new value
oViewModel.setProperty("/isInfoEditable", !bIsEditable);
}
I suggest strongly reading on the basics of UI5. Your approach looks more like Vue.js, but UI5 has its own paradigms.

Input assisted doesn't show all suggestions

I have input field i need suggest items from odata model.
<Input
id="productInput"
type="Text"
placeholder="Enter Product ..."
showSuggestion="true"
showValueHelp="true"
valueHelpRequest="handleValueHelp"
suggestionItems="{/ProductCollection}" >
<suggestionItems>
<core:Item text="{Name}" />
</suggestionItems>
</Input>
the problem is there are missing items : not all items are displayed (you can check this link
https://sapui5.hana.ondemand.com/#/sample/sap.m.sample.InputAssisted/preview
it is the same behaviour when you put a for example it shows some items in the search it shows more with a )
What you are trying to do is basically show all items that contains the value in the input. SAPUI5 has a convenient filter for this called sap.ui.model.FilterOperator.Contains.
The problem with the sap.m.Input is that it will only work one way, even if you manually set the Contains filter in the Suggest event, it will show suggestions that will start with the provided letter instead, just like sap.ui.model.FilterOperator.StartsWith filter operator. That's why it is showing you less suggestions.
Using the same products.json model in your question, we can do the following:
XML Input:
<Label text="Product" labelFor="productInput"/>
<Input
id="productInput"
type="Text"
placeholder="Enter Product ..."
showSuggestion="true"
showValueHelp="false"
suggest="handleSuggest"
suggestionItems="{productsModel>/ProductCollection}" >
<suggestionItems>
<core:Item text="{productsModel>Name}" />
</suggestionItems>
</Input>
Controller:
handleSuggest: function (oEvent) {
var aFilters = [];
var sTerm = oEvent.getParameter("suggestValue");
if (sTerm) {
aFilters.push(new sap.ui.model.Filter("Name", sap.ui.model.FilterOperator.Contains, sTerm));
}
oEvent.getSource().getBinding("suggestionItems").filter(aFilters);
//do not filter the provided suggestions before showing them to the user - important
oEvent.getSource().setFilterSuggests(false);
}
It is very important to set the setFilterSuggests() method to false in order not to filter the provided suggestions before showing them to the user, this would go against we just did previously.
Using this approach, the suggested item will show only those values filtered by the specified filter condition which is sap.ui.model.FilterOperator.Contains.
Other SAPUI5 Filter Operators

Traverse results in TreeTable binding - SAP UI5

I have an XML view with TreeTable. The binding is with an oData which returns something like results--> then in every result something called as "ABC" which is in itself an array.
In my table I want to display the results--> fields for parent and for the row ( which does not have child). For the child rows, need to display, results--> ABC --> then the property binding. But, the way I did coding, it works fine for rows that have children (parent and child binding is fine) but for rows without children also some controls are being made visible. I am not sure how to set visible syntax.
XML View:
<table:TreeTable rows="{path:'List>/results', parameters:{arrayNames:['ABC']}}" >
<table:Column id="t1" width="200px">
<Label text="Column1"/>
<table:template>
<HBox>
//want to make visible only for parent and the row which does not have child
<Text text="{path: 'List>', formatter: '.formatCoumn1'}" visible="{= !${List>?????}}"/>
//want to make visible only for child row
<DatePicker value="{List>ExpiryDate}" visible="{List>?????}"/>
</HBox>
</table:template>
</table:Column>
<Text text="{path: 'List>ABC'}" visible="{= ${List>switch} !== undefined}"/>
<DatePicker value="{List>ExpiryDate}" visible="{= ${List>switch} === undefined}" />
The Expression Binding in the Demo Kit has some additional examples, that might work for you:
enabled="{= ${/orderStatus} !== null }"
enabled="{= ${/items}.length > 0 }"

Attach browser event to a control using XML-View

My REST service send me a lot of data. Every property contains the value and a help-attribute that contains a long description of the field property.
Ok, I have data (a list of property with value and help) in a JSONModel and I use data-binding XML https://openui5.hana.ondemand.com/#docs/guide/91f0f3cd6f4d1014b6dd926db0e91070.html to map data value in forms and tables.
Now I want show somehow help message for each property.
My idea is show a message dialog when the user double-click on the Label or on the Text of the column header in a table
Both Label and Text have attachBrowserEvent method but I don't know how use the function to attach the event wrinting only in the XML-views
I would like something like this:
In XML-View:
<Label text="Language"
attachBrowserEvent:"function("click",showMessageHelp({model>/language/help}))">
<Input value="{model>/language/value}"/>
In the controller:
showMessageHelp:function(sMessage){
//show message dialog with sMessage
...........
}
You can achieve this using onAfterRendering method.
Have CustomData in the XML:
<Label id="label" text="Language">
<customData>
<core:CustomData key="type" value="{/language/help}" />
</customData>
</Label>
Then in controller use this customData:
onAfterRendering: function () {
var showValueHelp = function () {
var text = this.getCustomData()[0].getValue();
sap.m.MessageToast.show(text);
event.preventDefault();
event.stopPropagation();
return false;
};
this.byId("label").attachBrowserEvent("click", showValueHelp);
}
JS fiddle is here
PS:I am not sure this is viable solution for you.
This is the best I could come up with, currently.
Attach a browser event for each label is possible but I can't find a way to do it without repeat each label id.
I have found an alternative solution: my data are shown in forms and tables.
I have added on the right of each form couple of label: value a Text element with the help info:
<Label text="Field duck"/>
<Text text="{model>/elements/mainFields1/duck/value}"/>
<Text text="{model>/elements/mainFields1/duck/ATTR/help/description}" visible="{ui>/bShowHelp}" />
In tables I have divided each column title in two group: header and footer; in the footer I have placed the help info:
<Column>
<header>
<Text text="Name"/>
</header>
<footer>
<Text text="{model>/elements/airports/templateNewRow/name/ATTR/help/description}" visible="{ui>/bShowHelp}"/>
</footer>
</Column>
I change the value of bShowHelp showing and hiding all help infos