forked from extern/egroupware
Implement multi-select value as string[] or comma-separated
Had to overwrite some formMixin methods, which considered everything not string as invalid and set/get value to do the right thing for multi-select Not sure if code should go to Et2WidgetWithSelectMixing to be shared with TagList ...
This commit is contained in:
parent
940e1b12c1
commit
293e9f2fc6
@ -129,6 +129,79 @@ export class Et2Select extends Et2InvokerMixin(Et2WidgetWithSelect)
|
|||||||
this.multiple = multi;
|
this.multiple = multi;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reimplemented to return string[] for multiple
|
||||||
|
*/
|
||||||
|
get value() : string|string[]
|
||||||
|
{
|
||||||
|
if (!this._inputNode || !this.select_options?.length)
|
||||||
|
{
|
||||||
|
return this.__value || '';
|
||||||
|
}
|
||||||
|
if (!this.multiple)
|
||||||
|
{
|
||||||
|
return this._inputNode.value || this.__value || '';
|
||||||
|
}
|
||||||
|
// multi-selection value
|
||||||
|
const selected = this._inputNode.querySelectorAll('option:checked');
|
||||||
|
return Array.from(selected).map(el => (<HTMLOptionElement>el).value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reimplemented to select options for multiple
|
||||||
|
*
|
||||||
|
* @param value
|
||||||
|
*/
|
||||||
|
set value(value: string|string[])
|
||||||
|
{
|
||||||
|
// if not yet connected to dom can't change the value
|
||||||
|
if (this._inputNode && this.select_options?.length)
|
||||||
|
{
|
||||||
|
// split multiple comma-separated values for multiple or expand_multiple_rows
|
||||||
|
if (typeof value === 'string' && (this.multiple || this.expand_multiple_rows) && value.indexOf(',') !== -1)
|
||||||
|
{
|
||||||
|
value = value.split(',');
|
||||||
|
}
|
||||||
|
// if we get more than one value AND expand_multiple_rows is set --> switch to multiple
|
||||||
|
if (!this.multiple && this.expand_multiple_rows && Array.isArray(value) && value.length > 1)
|
||||||
|
{
|
||||||
|
this.multiple = true;
|
||||||
|
this.size = this.expand_multiple_rows;
|
||||||
|
}
|
||||||
|
if (!this.multiple)
|
||||||
|
{
|
||||||
|
this._inputNode.value = value;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this._inputNode.querySelectorAll('option').forEach((el : HTMLOptionElement) =>
|
||||||
|
{
|
||||||
|
el.selected = [].concat(value).find(val => val == el.value);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
/** @type {string | undefined} */
|
||||||
|
this.__value = undefined;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this.__value = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reimplemented to allow/keep string[] as value
|
||||||
|
*
|
||||||
|
* @param value string|string[]
|
||||||
|
*/
|
||||||
|
_callParser(value = this.formattedValue)
|
||||||
|
{
|
||||||
|
if (this.multiple && Array.isArray(value))
|
||||||
|
{
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
return super._callParser(value);
|
||||||
|
}
|
||||||
|
|
||||||
set expand_multiple_rows(rows)
|
set expand_multiple_rows(rows)
|
||||||
{
|
{
|
||||||
if (rows && !this.multiple)
|
if (rows && !this.multiple)
|
||||||
@ -145,6 +218,12 @@ export class Et2Select extends Et2InvokerMixin(Et2WidgetWithSelect)
|
|||||||
{
|
{
|
||||||
this._invokerLabel = undefined;
|
this._invokerLabel = undefined;
|
||||||
}
|
}
|
||||||
|
this.__expand_multiple_rows = rows;
|
||||||
|
}
|
||||||
|
|
||||||
|
get expand_multiple_rows()
|
||||||
|
{
|
||||||
|
return this.__expand_multiple_rows;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -170,15 +249,16 @@ export class Et2Select extends Et2InvokerMixin(Et2WidgetWithSelect)
|
|||||||
|
|
||||||
if(changedProperties.has('select_options') || changedProperties.has("value") || changedProperties.has('empty_label'))
|
if(changedProperties.has('select_options') || changedProperties.has("value") || changedProperties.has('empty_label'))
|
||||||
{
|
{
|
||||||
|
const modelValueArr = Array.isArray(this.modelValue) ? this.modelValue : this.modelValue.split(',');
|
||||||
// value not in options AND NOT (having an empty label and value)
|
// value not in options AND NOT (having an empty label and value)
|
||||||
if(this.get_select_options().length > 0 && this.get_select_options().filter((option) => option.value == this.modelValue).length === 0 &&
|
if(this.get_select_options().length > 0 && this.get_select_options().filter((option) => modelValueArr.find(val => val == option.value)).length === 0 &&
|
||||||
!(typeof this.empty_label !== 'undefined' && (this.modelValue || "") === ""))
|
!(typeof this.empty_label !== 'undefined' && (this.modelValue || "") === ""))
|
||||||
{
|
{
|
||||||
// --> use first option
|
// --> use first option
|
||||||
this.modelValue = "" + this.get_select_options()[0]?.value; // ""+ to cast value of 0 to "0", to not replace with ""
|
this.modelValue = "" + this.get_select_options()[0]?.value; // ""+ to cast value of 0 to "0", to not replace with ""
|
||||||
}
|
}
|
||||||
// Re-set value, the option for it may have just shown up
|
// Re-set value, the option for it may have just shown up
|
||||||
this._inputNode.value = this.modelValue || "";
|
this.value = this.modelValue || "";
|
||||||
}
|
}
|
||||||
|
|
||||||
// propagate multiple to selectbox
|
// propagate multiple to selectbox
|
||||||
|
Loading…
Reference in New Issue
Block a user