From a699117b1b17e3b2ab64acdd7535a333479dede6 Mon Sep 17 00:00:00 2001 From: nathan Date: Wed, 11 Jan 2023 11:10:25 -0700 Subject: [PATCH] Fix hiding server-side messages for selectboxes Messages were not properly hidden & displayed, and setting handleFocus & handleBlur accidentally overwrote them in Shoelace widgets --- .../Et2InputWidget/Et2InputWidget.ts | 39 +++++++++++++------ api/js/etemplate/Et2Select/Et2Select.ts | 20 ++++------ 2 files changed, 35 insertions(+), 24 deletions(-) diff --git a/api/js/etemplate/Et2InputWidget/Et2InputWidget.ts b/api/js/etemplate/Et2InputWidget/Et2InputWidget.ts index 258d4818c0..4b569de294 100644 --- a/api/js/etemplate/Et2InputWidget/Et2InputWidget.ts +++ b/api/js/etemplate/Et2InputWidget/Et2InputWidget.ts @@ -170,11 +170,12 @@ const Et2InputWidgetMixin = >(superclass : T) this._messagesHeldWhileFocused = []; this.__readonly = false; + this._oldValue = this.getValue(); this.isSlComponent = typeof (this).handleChange === 'function'; - this.handleFocus = this.handleFocus.bind(this); - this.handleBlur = this.handleBlur.bind(this); + this.et2HandleFocus = this.et2HandleFocus.bind(this); + this.et2HandleBlur = this.et2HandleBlur.bind(this); } connectedCallback() @@ -186,8 +187,8 @@ const Et2InputWidgetMixin = >(superclass : T) { this.addEventListener(this.isSlComponent ? 'sl-change' : 'change', this._oldChange); }); - this.addEventListener("focus", this.handleFocus); - this.addEventListener("blur", this.handleBlur); + this.addEventListener("focus", this.et2HandleFocus); + this.addEventListener("blur", this.et2HandleBlur); } disconnectedCallback() @@ -195,8 +196,8 @@ const Et2InputWidgetMixin = >(superclass : T) super.disconnectedCallback(); this.removeEventListener(this.isSlComponent ? 'sl-change' : 'change', this._oldChange); - this.removeEventListener("focus", this.handleFocus); - this.removeEventListener("blur", this.handleBlur); + this.removeEventListener("focus", this.et2HandleFocus); + this.removeEventListener("blur", this.et2HandleBlur); } /** @@ -255,33 +256,44 @@ const Et2InputWidgetMixin = >(superclass : T) * * If the value is the same on blur, we'll put them back * The ones from the server (ManualMessage) can interfere with submitting. + * + * Named et2HandleFocus to avoid overwriting handleFocus() in Shoelace components + * * @param {FocusEvent} _ev */ - handleFocus(_ev : FocusEvent) + et2HandleFocus(_ev : FocusEvent) { if(this._messagesHeldWhileFocused.length > 0) { return; } - this._oldValue = this.value; // Collect any ManualMessages this._messagesHeldWhileFocused = (this.validators || []).filter((validator) => (validator instanceof ManualMessage)); - this.set_validation_error(false); + this.updateComplete.then(() => + { + this.set_validation_error(false); + }); } /** * If the value is unchanged, put any held validation messages back + * + * Named et2HandleBlur to avoid overwriting handleBlur() in Shoelace components + * * @param {FocusEvent} _ev */ - handleBlur(_ev : FocusEvent) + et2HandleBlur(_ev : FocusEvent) { - if(this._messagesHeldWhileFocused.length > 0 && this.value == this._oldValue) + if(this._messagesHeldWhileFocused.length > 0 && this.getValue() == this._oldValue) { this.validators = this.validators.concat(this._messagesHeldWhileFocused); this._messagesHeldWhileFocused = []; - this.validate(); + this.updateComplete.then(() => + { + this.validate(); + }); } } @@ -289,6 +301,9 @@ const Et2InputWidgetMixin = >(superclass : T) { this.value = new_value; + // Save this so we can compare against any user changes + this._oldValue = this.getValue(); + if(typeof this._callParser == "function") { this.modelValue = this._callParser(new_value); diff --git a/api/js/etemplate/Et2Select/Et2Select.ts b/api/js/etemplate/Et2Select/Et2Select.ts index 815e08f27f..78a324b47d 100644 --- a/api/js/etemplate/Et2Select/Et2Select.ts +++ b/api/js/etemplate/Et2Select/Et2Select.ts @@ -182,6 +182,12 @@ export class Et2Select extends Et2WithSearchMixin(Et2WidgetWithSelect) { super.connectedCallback(); + // Re-bind focus/blur to after show/hide to avoid buggy behaviour like menu won't hide + this.removeEventListener("blur", this.et2HandleBlur); + this.removeEventListener("focus", this.et2HandleFocus); + this.addEventListener("sl-after-show", this.et2HandleFocus); + this.addEventListener("sl-after-hide", this.et2HandleBlur); + this.addEventListener("mousewheel", this._handleMouseWheel); this.updateComplete.then(() => @@ -199,6 +205,8 @@ export class Et2Select extends Et2WithSearchMixin(Et2WidgetWithSelect) this.removeEventListener("sl-clear", this._triggerChange) this.removeEventListener("sl-change", this._triggerChange); this.removeEventListener("sl-after-show", this._doResize); + this.removeEventListener("sl-after-show", this.et2HandleFocus); + this.removeEventListener("sl-after-hide", this.et2HandleBlur); } firstUpdated(changedProperties?) @@ -402,18 +410,6 @@ export class Et2Select extends Et2WithSearchMixin(Et2WidgetWithSelect) ${this.emptyLabel}`; } - /** - * Override Et2InputWidget blur handler to avoid doing our blur stuff when internal controls blur - * - * @param {FocusEvent} ev - */ - handleBlur(ev : FocusEvent) - { - if(ev.target == this) - { - super.handleBlur(ev); - } - } /** * Tag used for rendering options