diff --git a/packages/main/src/Input.js b/packages/main/src/Input.js
index 7c873c662b7c..957b07a4472c 100644
--- a/packages/main/src/Input.js
+++ b/packages/main/src/Input.js
@@ -804,7 +804,7 @@ class Input extends UI5Element {
_handleEnter(event) {
const itemPressed = !!(this.Suggestions && this.Suggestions.onEnter(event));
-
+ const innerInput = this.getInputDOMRefSync();
// Check for autocompleted item
const matchingItem = this.suggestionItems.find(item => {
return (item.text && item.text === this.value) || (item.textContent === this.value);
@@ -820,8 +820,12 @@ class Input extends UI5Element {
}
}
+ if (this._isPhone && !this.suggestionItems.length) {
+ innerInput.setSelectionRange(this.value.length, this.value.length);
+ }
+
if (!itemPressed) {
- this.fireEventByAction(this.ACTION_ENTER);
+ this.fireEventByAction(this.ACTION_ENTER, event);
this.lastConfirmedValue = this.value;
if (this.FormSupport) {
@@ -902,7 +906,6 @@ class Input extends UI5Element {
this.focused = true; // invalidating property
this.previousValue = this.value;
this.valueBeforeItemPreview = this.value;
- this._shouldAutocomplete = false;
this._inputIconFocused = event.target && event.target === this.querySelector("[ui5-icon]");
}
@@ -995,7 +998,9 @@ class Input extends UI5Element {
_handleInput(event) {
const inputDomRef = this.getInputDOMRefSync();
const emptyValueFiredOnNumberInput = this.value && this.isTypeNumber && !inputDomRef.value;
+ const eventType = event.inputType || event.detail.inputType;
+ this._shouldAutocomplete = eventType !== "deleteContentBackward" && !this.noTypeahead;
this.suggestionSelectionCanceled = false;
if (emptyValueFiredOnNumberInput && !this._backspaceKeyDown) {
@@ -1030,7 +1035,7 @@ class Input extends UI5Element {
this.valueBeforeItemPreview = newValue;
// fire events
- this.fireEvent(this.EVENT_INPUT);
+ this.fireEvent(this.EVENT_INPUT, { inputType: event.inputType });
this.fireEvent("value-changed");
return;
}
@@ -1049,7 +1054,7 @@ class Input extends UI5Element {
*/
const skipFiring = (inputDomRef.value === this.value) && isIE() && !this._keyDown && !!this.placeholder;
- !skipFiring && this.fireEventByAction(this.ACTION_USER_INPUT);
+ !skipFiring && this.fireEventByAction(this.ACTION_USER_INPUT, event);
this.hasSuggestionItemSelected = false;
this._isValueStateFocused = false;
@@ -1090,7 +1095,11 @@ class Input extends UI5Element {
this.value = value;
innerInput.value = value;
- innerInput.setSelectionRange(filterValue.length, value.length);
+ setTimeout(() => {
+ innerInput.setSelectionRange(filterValue.length, value.length);
+ }, 0);
+
+ this._shouldAutocomplete = false;
}
_handleResize() {
@@ -1242,7 +1251,7 @@ class Input extends UI5Element {
return this.getSuggestionByListItem(this._previewItem);
}
- async fireEventByAction(action) {
+ async fireEventByAction(action, event) {
await this.getInputDOMRef();
if (this.disabled || this.readonly) {
@@ -1268,7 +1277,7 @@ class Input extends UI5Element {
}
if (isUserInput) { // input
- this.fireEvent(this.EVENT_INPUT);
+ this.fireEvent(this.EVENT_INPUT, { inputType: event.inputType });
// Angular two way data binding
this.fireEvent("value-changed");
return;
@@ -1300,8 +1309,8 @@ class Input extends UI5Element {
}
getInputDOMRefSync() {
- if (isPhone() && this.Suggestions) {
- return this.Suggestions && this.Suggestions.responsivePopover.querySelector(".ui5-input-inner-phone");
+ if (isPhone() && this.Suggestions && this.Suggestions.responsivePopover) {
+ return this.Suggestions.responsivePopover.querySelector(".ui5-input-inner-phone").shadowRoot.querySelector("input");
}
return this.nativeInput;
diff --git a/packages/main/src/InputPopover.hbs b/packages/main/src/InputPopover.hbs
index 294abbc683cf..831219a13e23 100644
--- a/packages/main/src/InputPopover.hbs
+++ b/packages/main/src/InputPopover.hbs
@@ -30,7 +30,7 @@
.value="{{value}}"
?show-clear-icon={{showClearIcon}}
placeholder="{{placeholder}}"
- @input="{{_handleInput}}"
+ @ui5-input="{{_handleInput}}"
@change="{{_handleChange}}"
>
diff --git a/packages/main/test/specs/Input.mobile.spec.js b/packages/main/test/specs/Input.mobile.spec.js
new file mode 100644
index 000000000000..55788b50395d
--- /dev/null
+++ b/packages/main/test/specs/Input.mobile.spec.js
@@ -0,0 +1,37 @@
+const assert = require("chai").assert;
+const PORT = require("./_port.js");
+
+describe("Typeahead", () => {
+ before(async () => {
+ await browser.url(`http://localhost:${PORT}/test-resources/pages/Input.html`);
+ await browser.emulateDevice('iPhone X');
+ });
+
+ it("Should autocomplete the first matched suggestion item", async () => {
+ const input = await browser.$("#myInput2");
+ const sExpected = "Cozy";
+ const staticAreaItemClassName = await browser.getStaticAreaItemClassName("#myInput2")
+
+ await input.scrollIntoView();
+ await input.click();
+
+ const dialogInput = await browser.$(`.${staticAreaItemClassName}`).shadow$("ui5-responsive-popover").$(".ui5-input-inner-phone");
+ await dialogInput.keys("c");
+ assert.strictEqual(await dialogInput.getProperty("value"), sExpected, "Value is autocompleted");
+ });
+
+ it("Should not perform typeahead when it is disabled", async () => {
+ await browser.url(`http://localhost:${PORT}/test-resources/pages/Input.html`);
+
+ const input = await browser.$("#input-disabled-autocomplete");
+ const staticAreaItemClassName = await browser.getStaticAreaItemClassName("#input-disabled-autocomplete")
+
+ await input.scrollIntoView();
+ await input.click();
+
+ const dialogInput = await browser.$(`.${staticAreaItemClassName}`).shadow$("ui5-responsive-popover").$(".ui5-input-inner-phone");
+ await dialogInput.keys("c");
+
+ assert.strictEqual(await dialogInput.getProperty("value"), "c", "Value is not autocompleted");
+ });
+});
\ No newline at end of file
diff --git a/packages/main/test/specs/Input.spec.js b/packages/main/test/specs/Input.spec.js
index 9f4a1f823bed..56a5c68634dd 100644
--- a/packages/main/test/specs/Input.spec.js
+++ b/packages/main/test/specs/Input.spec.js
@@ -345,11 +345,11 @@ describe("Input general interaction", () => {
it("handles suggestions selection cancel with ESC", async () => {
await browser.url(`http://localhost:${PORT}/test-resources/pages/Input.html`);
- const suggestionsInput = await browser.$("#myInputEsc").shadow$("input");
+ const suggestionsInput = await browser.$("#myInputEsc");
// act
await suggestionsInput.click();
- await suggestionsInput.keys("ch");
+ await suggestionsInput.keys("c");
await suggestionsInput.keys("ArrowDown");
// assert
@@ -360,7 +360,7 @@ describe("Input general interaction", () => {
await suggestionsInput.keys("Escape");
// assert
- assert.strictEqual(await suggestionsInput.getValue(), "ch",
+ assert.strictEqual(await suggestionsInput.getProperty("value"), "c",
"The value is restored as ESC has been pressed.");
});
@@ -379,19 +379,20 @@ describe("Input general interaction", () => {
assert.strictEqual(await suggestionsInput.getValue(), "", "The value is restored as ESC has been pressed.");
- await suggestionsInput.keys("Some value");
+ await suggestionsInput.keys(["a", "b", "c"]);
await suggestionsInput.keys("Enter");
- await suggestionsInput.keys("Another value");
+ await suggestionsInput.keys(["c", "b", "a"]);
// Close sugggestions
await suggestionsInput.keys("Escape");
// Clear value
await suggestionsInput.keys("Escape");
- assert.strictEqual(await suggestionsInput.getValue(), "Some value", "The value is restored to the last confirmed by 'ENTER' press one.");
+ assert.strictEqual(await suggestionsInput.getValue(), "abc", "The value is restored to the last confirmed by 'ENTER' press one.");
});
it("handles group suggestion item via keyboard", async () => {
+
const suggestionsInput = await browser.$("#myInputGrouping").shadow$("input");
const inputResult = await browser.$("#inputResultGrouping").shadow$("input");
const staticAreaItemClassName = await browser.getStaticAreaItemClassName("#myInputGrouping");
@@ -539,19 +540,19 @@ describe("Input general interaction", () => {
it("Tests suggestions highlighting", async () => {
await browser.url(`http://localhost:${PORT}/test-resources/pages/Input.html`);
- const input = await browser.$("#myInputHighlighted").shadow$("input");
+ const input = await browser.$("#myInputHighlighted");
const staticAreaItemClassName = await browser.getStaticAreaItemClassName("#myInputHighlighted");
const EXPTECTED_TEXT = "Adam";
await input.click();
- await input.keys("ad");
+ await input.keys(["a", "d"]);
const respPopover = await browser.$(`.${staticAreaItemClassName}`).shadow$("ui5-responsive-popover");
const firstListItem = await respPopover.$("ui5-list").$("ui5-li-suggestion-item");
assert.ok(await respPopover.isDisplayedInViewport(), "The popover is visible");
const firstItemHtml = await firstListItem.getHTML();
- assert.include(firstItemHtml, EXPTECTED_TEXT, "The suggestions is highlighted.");
+ assert.include(firstItemHtml, "Adam", "The suggestions is highlighted.");
});
it("Doesn't remove value on number type input even if locale specific delimiter/multiple delimiters", async () => {