ComboBox in UI5 does not display ValueState - sapui5

ComboBox is not showing state like Error, Warning with highlight around the borders. But it does change the state. For example, if it is error state, and if I try to enter new value in combobox, it will show that "invalid Entry" tip near the box. But the box borders are never highlighted in red. Below is the code:
XML.view
<core:FragmentDefinition xmlns="sap.m" xmlns:core="sap.ui.core" xmlns:l="sap.ui.layout">
<Dialog id......>
<ComboBox id="combo1" change="cChanged" items="{path: '/results'}">
<items>
<core:Item key="{ID}" text="{Name}"/>
</items>
</ComboBox>
</Dialog>
Controller.js
cChanged: function(oEvent) {
var newval = oEvent.getParameter("newValue");
var key = oEvent.getSource().getSelectedItem();
if (newval !== "" && key === null) {
sap.ui.getCore().byId("combo1").setValueState("Error");
oEvent.getSource().setValue("");
sap.m.MessageToast.show("Please select from existing IDs")
flag = false;
} else {
oEvent.getSource().setValueState('None');
}

You can also access combo1 control instance by using oEvent.getSource() event OR use byId() from the sap.ui.core.Fragment class and not sap.ui.getCore().byId()
Also, if you are writing a logic only to validate if what the user input in the combobox is a valid item, consider replacing your ComboBox by the sap.m.Select control.
Both ComboBox and Select has same look and feel, but Select does not allow a manual input. It can also have an empty option if you use the property forceSelection

Related

How to register contextmenu event if cell of sap.ui.table is of type input

I try to get an context menu on a table cell which is of type input.
The right mouse click only works in the part outside of the input field.
Is there a way to propergate the event from the input field to the cell below?
Also there does not seem to be an click event on an input field.
My tries can be seen in the plnkr
https://plnkr.co/edit/BMozXm7uRPNlgzUf
codewise:
<t:Table rows="{/}" visibleRowCount="100"
minAutoRowCount="10" visibleRowCountMode="Auto" id="table0"
filter="onTableFilter" class="sapUiNoMargin sapUiNoContentPadding"
beforeOpenContextMenu="onContextMenu">
<t:columns>
<t:Column width="4em" filterProperty="CompCode"
sortProperty="CompCode" resizable="true" autoResizable="true"
class="sapUiLargeNegativeMarginBeginEnd"
click="oninputclick"
press="oninputclick">
<Label text="Comp Code" wrapping="true" class="test_maybe_he"/>
<t:template>
<Input value="{CompCode}" class="test_maybe_he" click="oninputclick"
press="oninputclick"/>
</t:template>
</t:Column>
I have the beforeOpenContextMenu="onContextMenu" in the table tag.
And click="oninputclick" press="oninputclick" in the input tag.
right click is only registerd outside of the input field. (In the sapui5 samples with an Text tag it seems to work.)
I suggest a custom control which inherits from sap.m.Input.
This control should have a new event (e.g. rightPress) and this event should be fired when the native browser event onContextMenu is triggered. Also the native context menu should not be shown.
sap.ui.define([
"sap/m/Input"
], function (Input) {
"use strict";
return Input.extend("gsan.ruleedit.control.MyInput", {
metadata: {
events: {
rightPress: {}
}
},
renderer: {},
oncontextmenu: function(oEvent) {
this.fireRightPress();
oEvent.preventDefault();
}
});
});
You can then use your custom control like any other
<mvc:View xmlns:my="gsan.ruleedit.control"
... />
<my:MyInput value="{CompCode}" rightPress="onContextMenu" />
Working sample: https://plnkr.co/edit/XAfC7SGpdf3RxiDF

How to set the input of a combobox to read-only

In one of my UI5-Dialogs, I implemented a combobox which is invisible when the screen is initially loaded.
In the method onAfterRendering, I start with setting the input to read-only:
onAfterRendering: function(oEvent) {
var oShovel = this.getView("View0200").byId("comboShovel");
oShovel.$().find("input").attr("readonly", true);
this.setVisibleByListKey();
},
After this the method setVisibleByListKey is called, the property visibleShovel will be set to false.
setVisibleByListKey: function(oEvent) {
var oModel = this.getView("View0200").getModel("Data0200");
this.setVisibleByListKey1(oModel);
// ...
},
setVisibleByListKey1: function(oModel) {
oModel.setProperty("/visibleShovel", false);
},
The property is bound to the attribute visible on my combobox.
Because of this behavior, the method onAfterRendering will be called again, the attribute readonly is not available (because of invisibility).
<ComboBox id="comboShovel"
editable="true"
enabled="true"
visible="{Data0200>/visibleShovel}"
valueState="None"
change=".changeCombo">
<items>
<core:Item text="Ja" enabled="true" key="0" />
<core:Item text="Nein" enabled="true" key="1" />
<core:Item text="Nicht erforderlich" enabled="true" key="2" />
</items>
</ComboBox>
I tried to call the set method in onInit or onBeforeRendering but at this time the input attributes can not be changed (because of invisibility again).
So how can I set the input of the combobox to read-only when I set the named visible property?
Solution would be either to use sap.m.Select or to implement a "change" event handler for the sap.m.Combobox and use a coding similar to this sample:
handleChange: function(oEvent) {
var oValidatedComboBox = oEvent.getSource();
var sSelectedKey = oValidatedComboBox.getSelectedKey();
var sValue = oValidatedComboBox.getValue();
if (!sSelectedKey && sValue) {
oValidatedComboBox.setValueState("Error");
oValidatedComboBox.setValueStateText("Please enter a valid country!");
} else {
oValidatedComboBox.setValueState("None");
}
},
Instead of using jquery, use UI5 control's methods and properties:
The sap.m.ComboBox borrows the following two methods from sap.m.InputBase:
setEditable
setEnabled
or since you are using property binding for the visibility, do the same for the editable property, e.g. {Data0200>/editableShovel}

ColumnListItem - Event Handler "press" NOT Triggered

I am using ColumnListItem to display a list of Sales Orders in Overview.view.xml. When the user clicks on an item of the list (of Sales Orders), the App should navigate to the Detail.view.xml.
I have defined the onPress event handler in Overview.Controller.js. But the App did not execute the function (I put an alert() there and it was not triggered). Why the onPress() is not triggered? How do I debug?
<Table items="{myOdata>/SalesOrderSet}">
<ColumnListItem type="Navigation" detailPress=".onPress">
<!-- ... -->
</ColumnListItem>
<columns>
<!-- ... -->
</columns>
</Table>
onPress: function (oEvent) {
//This code was generated by the layout editor.
alert("In");
var loOverview = "Data from Overview";
var oItem = oEvent.getSource();
var loRouter = sap.ui.core.UIComponent.getRouterFor(this);
loRouter.navTo("Detail", {
value: oItem.getBindingContext("oModel").getPath().substr(1)
});
},
The press function is not working as you have not written the correct handler for it. As per your code, the handler is written for detailPress. Just a typo, change the handler to press and it should just work.
Current:
<ColumnListItem type="Navigation" detailPress=".onPress">
Change required:
<ColumnListItem type="Navigation" press=".onPress">
the property that you should bind on the Table control is itemPress and your ColumnListItem need to have the type equals to Navigation
Can you check those?

Method getPath called in onBeforeRendering returns undefined

I have a List Report which, once selected an item, prompts to an Object Page. I am using no FIORI Elements, everything was created from scratch.
The object page has a static header, but its body changes from item to item. In essence, the body uses different fragments that depends on a field (Position Type) of the selected item. In other words:
Pos Type 1 ---> fragment A
Pos Type 2 ---> fragment B
To do all this, on the controller of the object page, I have implemented the following withing the onBeforeRendering lifecycle method:
onBeforeRendering: function() {
// // Set Fragment to be used
var oLayout = this.getView().byId("ObjectPageLayout"),
oFragment = sap.ui.xmlfragment(this._fragmentName());
oLayout.addSection(oFragment);
},
_fragmentName: function() {
var oModel = this.getView().getModel();
var sPosType = oModel.getProperty(this.getView().getObjectBinding().getPath() + "/PositionType");
var sFragment;
if (sPosType === "1") {
sFragment = "A";
} else if (sPosType === "2") {
sFragment = "B";
}
return sFragment;
},
The problem I am facing is that this code is throwing the following error message: "Uncaught (in promise) TypeError: Cannot read property 'getPath' of undefined"
The only way I found to make this to work is by, instead of using method onBeforeRendering, I used onInit. This way, getPath() works fine. But if the user goes back to the List Report, and then selects an item of a different Position Type, then the Object Page displays the same fragment used in the previous item selected.
In case you wonder, bellow you will find the object view:
<mvc:View height="100%" xmlns="sap.uxap" xmlns:core="sap.ui.core" xmlns:mvc="sap.ui.core.mvc" xmlns:m="sap.m" xmlns:semantic="sap.m.semantic"
xmlns:forms="sap.ui.layout.form" xmlns:layout="sap.ui.layout" controllerName="objectview.controller"
xmlns:aud="sap.uxap.sample.SharedBlocks.fragmentblocks">
<semantic:FullscreenPage id="page" navButtonPress="onNavBack" showNavButton="true" title="{i18n>ObjectPageTitle}">
<m:Page title="Object Page Title">
<m:content>
<ObjectPageLayout id="ObjectPageLayout">
<headerTitle>
<ObjectPageHeader id="ItemTitle" objectTitle="Item Title">
<actions>
Some actions defined
</actions>
</ObjectPageHeader>
</headerTitle>
<headerContent>
Some Header Content
</headerContent>
<sections>
</sections>
</ObjectPageLayout>
</m:content>
<m:footer>
<m:Bar>
<m:contentRight>
Buttons added to the Footer
</m:contentRight>
</m:Bar>
</m:footer>
</m:Page>
</semantic:FullscreenPage>
What happens is that each time you go to the page you add a new section on the container of sections.
You can remove all the existent sections before adding the new one.
oLayout.removeAllSections();
oLayout.addSection(oFragment);

Get value from checkbox in SapUI5

I have a main.controller.js where I want to check the value of a Checkbox. If the checkbox has been checked, the first flexbox will be shown and the second flexbox will not be shown in the fragment.
This my controller.js:
checkDone: function () {
var checkV = this.byId("ch1").getSelected();// not working
}
This my fragment.xml
<CheckBox id="ch1" select ="checkDone" text="Check"></CheckBox>
<FlexBox class="sapUiSmallMarginEnd" id="f1">
<Input value=""></Input>
</FlexBox>
<FlexBox direction="Column" id="f2">
<Input value=""></Input>
</FlexBox>
This code works (see example with sap.m.Checkbox here).
Just a recommendation: in your checkbox's 'select' handler you use:
this.byId("ch1").getSelected();
in order to whether the checkbox is selected or not, but this value is already given as a parameter of the select handler:
checkDone: function (oEvent) {
var bSelected = oEvent.getParameter('selected'));
}
Simmilar is for the sap.ui.commons.Checkbox API. Check change event.
It looks like the View.byId function returns an element in its initial form. When you find element from DOM, getSelected() function works as expected.
Instead of getSelected() try getChecked().
getChecked() will return true or false based on checked/unchecked.