Selector with filter or search option in SAPUI5 - select

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>

Related

CanĀ“t to bind or show data from ModelData.read to form in SapUi5

i have a big trouble that's freaking me out, check it out:
This is my xml for a View, program is divided in two differents Views, first of them, a table with navigation and second one is the details, involved in a form.
<mvc:View xmlns:core="sap.ui.core" xmlns:mvc="sap.ui.core.mvc" xmlns="sap.m" controllerName="Hello_World.Hello_World.controller.View2"
xmlns:html="http://www.w3.org/1999/xhtml" xmlns:form="sap.ui.layout.form">
<App>
<pages>
<Page title="Detalles" showHeader="true">
<Button type="Back" press="patras" tooltip="test"/>
<VBox>
</VBox>
<form:SimpleForm id="formPruebas" maxContainerCols="2" layout="ResponsiveGridLayout" labelSpanL="5" labelSpanM="4" labelSpanS="6" title="Formulario">
<Label text="CustomerID"/>
<Text text="{jsonmodel>CustomerID}"/>
<Label text="CompanyName"/>
<Text text="{CompanyName}"/>
<Label text="ContactTitle" />
<Text text="{ContactTitle}"/>
<Label text="Adress"/>
<Text text="{Adress}"/>
<Label text="City"/>
<Text text="{City}"/>
<Label text="PostalCode"/>
<Text text="{PostalCode}"/>
<Label text="Country" />
<Text text="{i18n>Country}"/>
<Button text="Aceptar" type="Accept">
<layoutData>
<FlexItemData growFactor="1" />
</layoutData>
</Button>
<Button text="Editar" width="100px">
<layoutData>
<FlexItemData growFactor="1" />
</layoutData>
</Button>
</form:SimpleForm>
</Page>
</pages>
</App>
Alright so this is my controller:
onInit: function() {
var oRouter = sap.ui.core.UIComponent.getRouterFor(this);
oRouter.getRoute("View2").attachMatched(this._onRouteMatched, this);
},
_onRouteMatched: function(oEvent) {
var idDevuelto = oEvent.getParameter("arguments").data;
var idCompleto = "/Customers('" + idDevuelto + "')";
//var oForm = this.getView().byId("formPruebas");
var oForm = this.getView().byId("formPruebas");
var serviceUrl = "myurl";
var oModelData = new sap.ui.model.odata.ODataModel(serviceUrl,{
JSON:true,
useBatch: false
});
oModelData.read(idCompleto, {
success: function (oData) {
sap.m.MessageToast.show(oData.CustomerID);
var oModel = new JSONModel(oData.results);
oForm.setModel(oModel.results);
},
error: function (oError) {
sap.m.MessageToast.show("No funca");
}
});
},
However the result is not showing on my view when i run the program, any idea?
PD: I'm pretty noob on sapui5
Finally i found the solution of the problem, if you check the XML code at the beginning of the question , you realize there is not path in Form element.
In mi first view i have a table with id and a PATH which i don't have in the Form so the fastest way i solve it is to put in the XML a slash, an example:
<form:SimpleForm id="formPruebas" maxContainerCols="2" layout="ResponsiveGridLayout" labelSpanL="5" labelSpanM="4" labelSpanS="6" title="Formulario">
<Label text="CustomerID"/>
<Text text="{/CustomerID}"/> // the slash i mean
With that fix, i only do oForm.setModel(oModel) so everything is connected and works
fine, i want to share this information if more people deal with the same error as i did.
Thanks all ideas.

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

Data Binding from TableSelectDialog to Form

I'm using TableSelectDialog to view some Carrier details. All I need is: If I select any item (row), then all the values from that row should get automatically populated to the form input fields.
In the attached image, if Carrier Name is selected from TableSelectDialog, then the remaining fields should be populated based on that value.
You can achieve the required functionality using the Binding context that you receive from the TableSelcect Dialog.
But for binding context to work properly, both form and the table select dialog should refer to the same Model.
Below is the working code:
VIEW.XML:
Has a Button to trigger the table select dialog.
Has a form.
<l:VerticalLayout class="sapUiContentPadding" width="100%">
<l:content>
<Button class="sapUiSmallMarginBottom" text="Show Table Select Dialog"
press="handleTableSelectDialogPress">
</Button>
<VBox class="sapUiSmallMargin">
<f:SimpleForm id="SimpleFormDisplay354">
<f:content>
<Label text="Supplier Name" />
<Text id="nameText" text="{SupplierName}" />
<Label text="Description" />
<Text text="{Description}" />
<Label text="ProductId" />
<Text text="{ProductId}" />
<Label text="Quantity" />
<Text id="countryText" text="{Quantity}" />
</f:content>
</f:SimpleForm>
</VBox>
</l:content>
</l:VerticalLayout>
Controller:
onInit: function () {
// set explored app's demo model on this sample
var oModel = new JSONModel(jQuery.sap.getModulePath("sap.ui.demo.mock", "/products.json"));
this.getView().setModel(oModel);
},
handleTableSelectDialogPress: function (oEvent) {
if (!this._oDialog) {
this._oDialog = sap.ui.xmlfragment("sap.m.sample.TableSelectDialog.Dialog", this);
}
this.getView().addDependent(this._oDialog);
// toggle compact style
this._oDialog.open();
},
handleClose: function (oEvent) {
var aContexts = oEvent.getParameter("selectedContexts");
if (aContexts && aContexts.length) {
// MessageToast.show("You have chosen " + aContexts.map(function(oContext) { return oContext.getObject().Name; }).join(", "));
this.byId('SimpleFormDisplay354').setBindingContext(aContexts[0]);
}
oEvent.getSource().getBinding("items").filter([]);
}
Now, we also have a Select dialog and on click of any Item we call method : handleClose
In handleClose, we obtain the clicked Item binding context and then tell the form : hey! refer to this context ( which is present in the model). Binding context has a path which tells the form from where to do the relative binding.
Please feel free to contact for more information.

oData binding to Simple Form

I'm creating a read only form that will be used to display a summary of information. I need to send a parameter to the backend first before getting the information but I don't seem to see that parameter is reaching it.
It does reach the entity set but it does not show the parameter. Am I binding correctly?
This is on the controller:
onInit: function() {
var urlEnding = "1000012233";
var oFilterDist = new sap.ui.model.Filter("ID",
sap.ui.model.FilterOperator.EQ, urlEnding);
var summaryText = this.getView().byId("summaryForm");
summaryText.bindElement({
path: "/SummaryScreenSet",
filters: [oFilterDist]
});
}
This is on the View
<VBox class="sapUiSmallMargin" fitContainer="true"
height="100%" width="100%" justifyContent="End"
displayInline="true" id="leftVBox" items="{/SummaryScreenSet}">
<items>
<f:SimpleForm editable="true" layout="ResponsiveGridLayout" id="summaryForm" columnsL="1" columnsXL="1" labelSpanL="5" title="Account Summary" labelSpanM="5">
<f:content>
<Label text="Status" id="__label6" design="Bold" class="sizeText"/>
<ObjectStatus text="{CONTRACT_STATUS}" id="__status6" state="Success" class="boldText"/>
<Label text="Permit Required" id="__label10" design="Bold" class="sizeText"/>
<Text text="{PERMIT_REQD}" id="__text32" wrapping="false" class="sizeText"/>
<Label text="Bill Date | Due Date" id="__label11" design="Bold" class="sizeText"/>
<Text text="{BILL_DATE} | {DUE_DATE}" id="__text33" wrapping="false" class="sizeText"/>
<Label text="Last Estimated Date | Next MR Date" id="__label17" design="Bold" class="sizeText"/>
<Text text="{LAST_PAYMENT_DATE} | {nextMRDate}" id="__text39" wrapping="false" class="sizeText"/>
</f:content>
</f:SimpleForm>
</items>
</VBox>
Going to assume you want a single, specific entry. In that case, what you're looking for is the Entity, not the EntitySet + filter. Coincidentally, here's one I wrote yesterday that works. I've changed the paths and ID's to reflect yours:
var form = this.getView().byId('summaryForm');
form.bindElement({
path: "/SummaryScreenSet('" + urlEnding + "')",
events: {
change: function() {
//triggers on error too I think
form.setBusy(false);
},
dataRequested: function() {
form.setBusy(true);
}
}
});
In that case you don't need the VBOX either, just the form. Don't forget to implement SUMMARYSCREEN_GET_ENTITY or whatever the method is on your DPC_EXT.
Edit: might want to set editable on the form to false, it shrinks the layout to suit text instead of inputs.

SAPUI5 - add Fragment in SimpleForm

i have a problem with adding an fragment to an SimpleForm in SAPUI5. I have an SimpleForm and want to add content in the form with fragments. The result should look like this:
what i want done
my fragment:
<core:FragmentDefinition
xmlns="sap.m"
xmlns:core="sap.ui.core"
xmlns:mvc="sap.ui.core.mvc"
xmlns:html="http://www.w3.org/1999/xhtml"
xmlns:l="sap.ui.layout"
xmlns:f="sap.ui.layout.form"
xmlns:tnt="sap.tnt"
xmlns:custom="http://schemas.sap.com/sapui5/extension/sap.ui.core.CustomData/1">
<core:Title text="{i18n>beauskunftung.suche.address}"/>
<Label text="{i18n>beauskunftung.suche.streetNo}"/>
<Input editable="false" fieldGroupIds="Address" value="{AddressStreet}" id="inputStreetID"></Input>
<Input editable="false" fieldGroupIds="Address" value="{AddressStreetNumber}" id="inputNumberID">
<layoutData>
<l:GridData span="L3 M3 S4"/>
</layoutData>
</Input>
<Label text="{i18n>beauskunftung.suche.zipCity}"/>
<Input editable="false" fieldGroupIds="Address" value="{AddressZipCode}" id="inputZipID">
<layoutData>
<l:GridData span="L3 M3 S4"/>
</layoutData>
</Input>
<Input editable="false" fieldGroupIds="Address" value="{AddressCity}" id="inputCityID"/>
</core:FragmentDefinition>
if i add the fragment with javacript
var oFragment = sap.ui.xmlfragment("testistest", "com.natuvion.ddi.fragments.select.address");
var oLayout = this.getView().byId("AddressIDandSoOn");
oLayout.insertContent(oFragment, -1);
i get the following error:
Uncaught (in promise) Error: "Element sap.ui.core.Title#__title0,Element sap.m.Label#__label0,Element sap.m.Input#testistest--inputStreetID,Element sap.m.Input#testistest--inputNumberID,Element sap.m.Label#__label1,Element sap.m.Input#testistest--inputZipID,Element sap.m.Input#testistest--inputCityID" is not valid for aggregation "content" of Element sap.ui.layout.form.SimpleForm#__xmlview1--AddressIDandSoOn
I think the problem is that the add method can just add one element (if I have just a label in the fragment it works!). I looked for some element which should contains all the elements from the fragment but I didn't find one. If I add the fragment via XML on the page
<core:Fragment id="addressFragment1"
fragmentName="com.natuvion.ddi.fragments.select.address" type="XML">
</core:Fragment>
it works. At this point I have no idea how to add fragments inside an SimpleForm. I need the dynamic generation of the elements, as I have to add this depending on the given data, possibly also several times
My Question:
- How can i add an Fragment to an SimpleForm?
The programatic APIs add/insert content support only single element and not an array. So you could try looping over the array and add one by one:
var aFragment = sap.ui.xmlfragment("testistest", "com.natuvion.ddi.fragments.select.address");
var oLayout = this.getView().byId("AddressIDandSoOn");
aFragment.forEach(function (oElement) {oLayout.addContent(oElement);});
Another option you can consider is moving to sap.ui.layout.form.Form. It has composed aggregations inside: Form -> formContainers -> formElements -> label,fields[].
It looks like the address fragment could be a single FormContainer and then you could add it to the Form in a single call to addFormContainer().