Fix hiding server-side messages for selectboxes

Messages were not properly hidden & displayed, and setting handleFocus & handleBlur accidentally overwrote them in Shoelace widgets
This commit is contained in:
nathan 2023-01-11 11:10:25 -07:00
parent 1229b1ad65
commit a699117b1b
2 changed files with 35 additions and 24 deletions

View File

@ -170,11 +170,12 @@ const Et2InputWidgetMixin = <T extends Constructor<LitElement>>(superclass : T)
this._messagesHeldWhileFocused = []; this._messagesHeldWhileFocused = [];
this.__readonly = false; this.__readonly = false;
this._oldValue = this.getValue();
this.isSlComponent = typeof (<any>this).handleChange === 'function'; this.isSlComponent = typeof (<any>this).handleChange === 'function';
this.handleFocus = this.handleFocus.bind(this); this.et2HandleFocus = this.et2HandleFocus.bind(this);
this.handleBlur = this.handleBlur.bind(this); this.et2HandleBlur = this.et2HandleBlur.bind(this);
} }
connectedCallback() connectedCallback()
@ -186,8 +187,8 @@ const Et2InputWidgetMixin = <T extends Constructor<LitElement>>(superclass : T)
{ {
this.addEventListener(this.isSlComponent ? 'sl-change' : 'change', this._oldChange); this.addEventListener(this.isSlComponent ? 'sl-change' : 'change', this._oldChange);
}); });
this.addEventListener("focus", this.handleFocus); this.addEventListener("focus", this.et2HandleFocus);
this.addEventListener("blur", this.handleBlur); this.addEventListener("blur", this.et2HandleBlur);
} }
disconnectedCallback() disconnectedCallback()
@ -195,8 +196,8 @@ const Et2InputWidgetMixin = <T extends Constructor<LitElement>>(superclass : T)
super.disconnectedCallback(); super.disconnectedCallback();
this.removeEventListener(this.isSlComponent ? 'sl-change' : 'change', this._oldChange); this.removeEventListener(this.isSlComponent ? 'sl-change' : 'change', this._oldChange);
this.removeEventListener("focus", this.handleFocus); this.removeEventListener("focus", this.et2HandleFocus);
this.removeEventListener("blur", this.handleBlur); this.removeEventListener("blur", this.et2HandleBlur);
} }
/** /**
@ -255,33 +256,44 @@ const Et2InputWidgetMixin = <T extends Constructor<LitElement>>(superclass : T)
* *
* If the value is the same on blur, we'll put them back * If the value is the same on blur, we'll put them back
* The ones from the server (ManualMessage) can interfere with submitting. * The ones from the server (ManualMessage) can interfere with submitting.
*
* Named et2HandleFocus to avoid overwriting handleFocus() in Shoelace components
*
* @param {FocusEvent} _ev * @param {FocusEvent} _ev
*/ */
handleFocus(_ev : FocusEvent) et2HandleFocus(_ev : FocusEvent)
{ {
if(this._messagesHeldWhileFocused.length > 0) if(this._messagesHeldWhileFocused.length > 0)
{ {
return; return;
} }
this._oldValue = this.value;
// Collect any ManualMessages // Collect any ManualMessages
this._messagesHeldWhileFocused = (this.validators || []).filter((validator) => (validator instanceof ManualMessage)); 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 * If the value is unchanged, put any held validation messages back
*
* Named et2HandleBlur to avoid overwriting handleBlur() in Shoelace components
*
* @param {FocusEvent} _ev * @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.validators = this.validators.concat(this._messagesHeldWhileFocused);
this._messagesHeldWhileFocused = []; this._messagesHeldWhileFocused = [];
this.validate(); this.updateComplete.then(() =>
{
this.validate();
});
} }
} }
@ -289,6 +301,9 @@ const Et2InputWidgetMixin = <T extends Constructor<LitElement>>(superclass : T)
{ {
this.value = new_value; this.value = new_value;
// Save this so we can compare against any user changes
this._oldValue = this.getValue();
if(typeof this._callParser == "function") if(typeof this._callParser == "function")
{ {
this.modelValue = this._callParser(new_value); this.modelValue = this._callParser(new_value);

View File

@ -182,6 +182,12 @@ export class Et2Select extends Et2WithSearchMixin(Et2WidgetWithSelect)
{ {
super.connectedCallback(); 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.addEventListener("mousewheel", this._handleMouseWheel);
this.updateComplete.then(() => this.updateComplete.then(() =>
@ -199,6 +205,8 @@ export class Et2Select extends Et2WithSearchMixin(Et2WidgetWithSelect)
this.removeEventListener("sl-clear", this._triggerChange) this.removeEventListener("sl-clear", this._triggerChange)
this.removeEventListener("sl-change", this._triggerChange); this.removeEventListener("sl-change", this._triggerChange);
this.removeEventListener("sl-after-show", this._doResize); this.removeEventListener("sl-after-show", this._doResize);
this.removeEventListener("sl-after-show", this.et2HandleFocus);
this.removeEventListener("sl-after-hide", this.et2HandleBlur);
} }
firstUpdated(changedProperties?) firstUpdated(changedProperties?)
@ -402,18 +410,6 @@ export class Et2Select extends Et2WithSearchMixin(Et2WidgetWithSelect)
<sl-menu-item value="">${this.emptyLabel}</sl-menu-item>`; <sl-menu-item value="">${this.emptyLabel}</sl-menu-item>`;
} }
/**
* 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 * Tag used for rendering options