diff --git a/packages/main/src/Input.ts b/packages/main/src/Input.ts index a17b552cb953..b9ddc965ff5d 100644 --- a/packages/main/src/Input.ts +++ b/packages/main/src/Input.ts @@ -154,6 +154,11 @@ type InputEventDetail = { inputType: string; } +// // Option 2 +// type InputChangeEventDetail = { +// validity?: ValidityState; +// } + type InputSelectionChangeEventDetail = { item: IInputSuggestionItem | null; } @@ -297,7 +302,10 @@ type InputSuggestionScrollEventDetail = { class Input extends UI5Element implements SuggestionComponent, IFormInputElement { eventDetails!: { - "change": InputEventDetail, + + // Option 2 + // "change": InputChangeEventDetail, + "change": InputEventDetail "input": InputEventDetail, "select": void, "_request-submit": void, @@ -539,6 +547,14 @@ class Input extends UI5Element implements SuggestionComponent, IFormInputElement @property({ type: Boolean, noAttribute: true }) _inputIconFocused = false; + // Option 1 + @property({ type: Boolean }) + _isDash = false; + + // Option 1 + @property({ type: Boolean }) + _wasDash = false; + /** * Constantly updated value of texts collected from the associated labels * @private @@ -1193,16 +1209,25 @@ class Input extends UI5Element implements SuggestionComponent, IFormInputElement return; } + let validity = undefined; + if( this.isTypeNumber) { + validity = this.nativeInput?.validity; + } + const fireChange = () => { if (!this._isChangeTriggeredBySuggestion) { + // Option 2: Propagate native input validity state to the change event so customers will decide what to do with invalid numeric input + // this.fireDecoratorEvent(INPUT_EVENTS.CHANGE, { validity: validity}); this.fireDecoratorEvent(INPUT_EVENTS.CHANGE); } + this.previousValue = this.value; this.typedInValue = this.value; this._isChangeTriggeredBySuggestion = false; }; - if (this.previousValue !== this.getInputDOMRefSync()!.value) { + // Option 1 + if (this.previousValue !== this.getInputDOMRefSync()!.value || this._isDash || this._wasDash) { // if picker is open there might be a selected item, wait next tick to get the value applied if (this.Suggestions?._getPicker()?.open && this._flattenItems.some(item => item.hasAttribute("ui5-suggestion-item") && (item as SuggestionItem).selected)) { this._changeToBeFired = true; @@ -1263,7 +1288,24 @@ class Input extends UI5Element implements SuggestionComponent, IFormInputElement this._input(e, eventType); } + // // Option 3: keep track of the dash symbol at onBeforeInput + // _onBeforeInput(e: any) { + // // e.data is null when text is deleted + // // e.data is the pressed symbol otherwise + // console.log(e.data, this.getInputDOMRefSync()?.value); + // } + + // Option 1 + get isValidNumber(){ + return this.isTypeNumber && !this._isDash; + } + _input(e: CustomEvent | InputEvent, eventType: string) { + // Option 1 + this._wasDash = (e as InputEvent)?.data === null && this._isDash && this.getInputDOMRefSync()?.value === ""; + this._isDash = (e as InputEvent)?.data === "-" && this.getInputDOMRefSync()?.value === ""; + + const inputDomRef = this.getInputDOMRefSync(); const allowedEventTypes = [ @@ -1404,7 +1446,7 @@ class Input extends UI5Element implements SuggestionComponent, IFormInputElement this.open = false; } - _confirmMobileValue() { + _confirmMobileValue(e: any) { this._closePicker(); this._handleChange(); } @@ -1434,6 +1476,8 @@ class Input extends UI5Element implements SuggestionComponent, IFormInputElement if (this._changeToBeFired && !this._isChangeTriggeredBySuggestion) { this.previousValue = this.value; + // Option 2 + // this.fireDecoratorEvent(INPUT_EVENTS.CHANGE, {validity: this.nativeInput?.validity}); this.fireDecoratorEvent(INPUT_EVENTS.CHANGE); } else { this._isChangeTriggeredBySuggestion = false; @@ -1558,6 +1602,9 @@ class Input extends UI5Element implements SuggestionComponent, IFormInputElement this._performTextSelection = true; + + //Option 2 + // this.fireDecoratorEvent(INPUT_EVENTS.CHANGE, {validity: this.nativeInput?.validity}); this.fireDecoratorEvent(INPUT_EVENTS.CHANGE); this._isChangeTriggeredBySuggestion = true; diff --git a/packages/main/src/InputTemplate.tsx b/packages/main/src/InputTemplate.tsx index 4a6ce63f14fc..80cb628b97ec 100644 --- a/packages/main/src/InputTemplate.tsx +++ b/packages/main/src/InputTemplate.tsx @@ -54,6 +54,7 @@ export default function InputTemplate(this: Input, hooks?: { preContent: Templat min={this.nativeInputAttributes.min} max={this.nativeInputAttributes.max} onInput={this._handleNativeInput} + // onBeforeInput={this._onBeforeInput} onChange={this._handleChange} onSelect={this._handleSelect} onKeyDown={this._onkeydown} diff --git a/packages/main/test/pages/Input.html b/packages/main/test/pages/Input.html index e0c9cca883a2..32119cbc5f68 100644 --- a/packages/main/test/pages/Input.html +++ b/packages/main/test/pages/Input.html @@ -199,7 +199,8 @@

Input required

Input type 'Number'

- + + @@ -1233,6 +1234,17 @@

Capitalization suggestions

}); } }); + + document.getElementById("input-number").addEventListener("ui5-change", event => { + const input = event.target; + + // Option 1: Set value state based on validity of the number input + event.target.valueState = input.isValidNumber ? "None" : "Negative"; + + // // Option 2 + // const validity = event.detail.validity; + // event.target.valueState = validity.valid ? "None" : "Negative"; + });