Input assisted doesn't show all suggestions - sapui5

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

Related

Selector with filter or search option in SAPUI5

I am making a form and one part of it is to put the telephone number. I want to divide this input in two, on the one hand a selector with the prefixes of all the countries (I get the information from a json) and on the other hand a normal input with a restriction of numbers. The problem is that as there are many prefixes I would like to see if there is a way to filter the numbers with a select because with a comboBox I can filter the problem is that it gets out of the form and the sizes are not good, however with the select everything goes correctly. I have tried these three ways but, the first one I don't think is the best, then the second one I can't look for the result and the third one it overshoots the width of the cell. Any ideas for the select?
<VBox>
<Label class="label" text="{i18n>Phone}" required="true"/>
<HBox>
<SearchField id="prefix" placeholder="Prefijo" enableSuggestions="true" search=".onSearch" suggest=".onSuggest" suggestionItems="{ path: 'country>/Dato' }">
<SuggestionItem text="{country>prefix}" key="{country>code}"/>
</SearchField>
<!--<Select id="prefix" items="{ path: 'country>/Dato' }">
<core:ListItem key="{country>code}" text="{country>prefix}"/>
</Select>-->
<!--<ComboBox id="prefix" class="input" width="30%" required="true" items="{ path: 'country>/Dato' }">
<core:ListItem key="{country>code}" text="{country>prefix}"/>
</ComboBox>-->
<Input id="phone" placeholder="{i18n>Phone}" value="" class="input phone" type="Tel" required="true" maxLength="10" liveChange="handleLiveChange"></Input>
</HBox>
<layoutData>
<l:GridData span="L6 M6 S12"/>
</layoutData>
</VBox>
You could use sap.ui.layout.form.SimpleForm to encapsulate your UI elements.
Then add 2 elements such as sap.m.Select and sap.m.MaskInput inside your form.
Here an example : https://jsbin.com/xotokavamo/2
Feel free to edit it to fit your use case.
<script>
var oForm = new sap.ui.layout.form.SimpleForm({
layout: "ResponsiveGridLayout",
editable: true
});
var oLabel = new sap.m.Label({text: "Phone"});
var oInput = new sap.m.Input({placeholder: "Enter phone number"});
var oMaskInput = new sap.m.MaskInput({placeholderSymbol: "_", placeholder: "Enter a 10 digit number"})
var oSelect = new sap.m.Select({items: [
new sap.ui.core.Item({text:"+33"}),
new sap.ui.core.Item({text:"+81"}),
]});
var oHBox = new sap.m.HBox({
items: [oSelect, oMaskInput]
})
oForm.addContent(oLabel);
oForm.addContent(oHBox);
oForm.placeAt("content");
</script>

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.

How to add a Autofill filter in FilterBar

I'm trying to implement filters using SAPUI5 FilterBar. I want to add a field which works like a dropdown filter only when you type something in it. When you put the cursor, it should not show any results, but as you start typing something, the matching results should show up in the dropdown.
Here is a working example: Plunker
You could use a Input object in the filterGroupItems aggregation of the FilterBar control.
Note: The filterItems aggregation is deprecated as of version 1.48
<fb:FilterBar id="filterBar">
<fb:filterGroupItems>
<fb:FilterGroupItem
groupName="GroupExample"
name="regionGroup"
label="Example"
visibleInFilterBar="true">
<fb:control>
<Input showSuggestion="true">
<suggestionItems>
<core:Item key="001" text="Russia"/>
<core:Item key="002" text="America"/>
<core:Item key="003" text="Australia"/>
<core:Item key="004" text="Germany"/>
</suggestionItems>
</Input>
</fb:control>
</fb:FilterGroupItem>
</fb:filterGroupItems>
</fb:FilterBar>
Which produces:
Be sure to add the visibleInFilterBar="true" attribute if you want your input field to be visible without having to add it in the Filters prompt.
If you want to add the Input items dynamically, add an aggregation binding to the <items>.
To do that, change the Input control as follows:
<Input suggestionItems="{path: '/dropdownData'}" showSuggestion="true">
<suggestionItems>
<core:Item key="{key}" text="{text}"/>
</suggestionItems>
</Input>
And set the model according to your datasource (here it's a JSONModel) in the controller:
onInit: function() {
this.oModel = new JSONModel("/data.json");
var oView = this.getView();
oView.setModel(this.oModel);
}

How to edit an item which is created using a single form on Angular2?

I am new to angular2 & I have a form which can add more item to a page (item with name & decription). This works really well, I can keep on adding new item to my list.
However, each of this item has its own edit & delete. How can I edit and delete each of the item using that only 1 form?
<form #formExperiencesRef="ngForm">
<label for="name">name</label>
<input id="name" type="text" name="fruit [(ngModel)]="formData.name">
<label for="description">description</label>
<input id="description" type="text" name="fruit [(ngModel)]="formData.description">
<button (click)="onSubmit(formExperiencesRef.value)"></button>
</form>
This single form is what I use to keep on adding new item. And now I find it hard to edit the item that I created using this. Can someone help me?
Often I would advise to go with a reactive form for all it's benefits, but if your form is this simple a template driven approach can be sufficient.
First of all I see problem in your form. Your name attributes are the same for both fields, this will mean that they are evaluated as one and the same. I would actually name them as for how your formData object looks like, and then just push the form value as is to the array. I'll just use one way binding here for the sake of the editing of item. Also pass the form object in submit.
How we can edit can be done numerous ways. Here we'll utilize the index of your list (assumingly it's an array).
<form #formExperiencesRef="ngForm" (ngSubmit)="onSubmit(formExperiencesRef.value)">
<input name="name" [ngModel]="formData.name">
<input name="description" [ngModel]="formData.description">
<button type="submit">Submit</button>
</form>
Your list:
<div *ngFor="let item of items; let i = index">
{{item.name}} <button (click)="edit(item, i)">Edit</button>
</div>
And in the TS, we can use #ViewChild to reference our form, which I am using to reset the form:
#ViewChild('formExperiencesRef') formExperiencesRef: NgForm;
and your methods for editing and saving a new item:
formData = {};
items = [];
index = null; // used to store current index value of item (if exists)
edit(item, i) {
this.index = i;
this.formData = item;
}
onSubmit(val) {
// check if index exists, if not it's a new item
if(this.index == null) {
this.items.push(val)
} else {
this.items[this.index] = val;
}
// reset index & form
this.index = null;
this.formExperiencesRef.reset();
}
DEMO: http://plnkr.co/edit/ksHp10WwaDg4AQjwDf2d?p=preview
For the future, I really suggest you check out reactive forms, you have tighter control over your form, handle validations easier and a big,big advantage to me is especially if you are dealing with nested components. Reactive forms can be confusing in the beginning, but it's worth it! :)

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