mirror of
https://github.com/EGroupware/egroupware.git
synced 2024-11-29 11:23:54 +01:00
More fixing of missing search options / tags
Fixes new free entries don't show up after removing a free entry
This commit is contained in:
parent
0424836ba8
commit
5a8f7c3c70
@ -8,7 +8,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import {Et2InputWidget, Et2InputWidgetInterface} from "../Et2InputWidget/Et2InputWidget";
|
import {Et2InputWidget, Et2InputWidgetInterface} from "../Et2InputWidget/Et2InputWidget";
|
||||||
import {html, LitElement, PropertyValues, render, repeat, TemplateResult} from "@lion/core";
|
import {html, LitElement, PropertyValues, render, TemplateResult} from "@lion/core";
|
||||||
import {et2_readAttrWithDefault} from "../et2_core_xml";
|
import {et2_readAttrWithDefault} from "../et2_core_xml";
|
||||||
import {cleanSelectOptions, find_select_options, SelectOption} from "./FindSelectOptions";
|
import {cleanSelectOptions, find_select_options, SelectOption} from "./FindSelectOptions";
|
||||||
import {SearchMixinInterface} from "./SearchMixin";
|
import {SearchMixinInterface} from "./SearchMixin";
|
||||||
@ -134,13 +134,39 @@ export const Et2widgetWithSelectMixin = <T extends Constructor<LitElement>>(supe
|
|||||||
protected _renderOptions()
|
protected _renderOptions()
|
||||||
{
|
{
|
||||||
// Add in options as children to the target node
|
// Add in options as children to the target node
|
||||||
if(this._optionTargetNode)
|
if(!this._optionTargetNode)
|
||||||
{
|
{
|
||||||
render(html`${this._emptyLabelTemplate()}
|
return Promise.resolve();
|
||||||
${repeat(<SelectOption[]>this.select_options, (option : SelectOption) => option.value, this._optionTemplate.bind(this))}`,
|
|
||||||
this._optionTargetNode
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* Doing all this garbage to get the options to always show up.
|
||||||
|
* If we just do `render(options, target)`, they only show up in the DOM the first time. If the
|
||||||
|
* same option comes back in a subsequent search, map() does not put it into the DOM.
|
||||||
|
* If we render into a new target, the options get rendered, but we have to wait for them to be
|
||||||
|
* rendered before we can do anything else with them.
|
||||||
|
*/
|
||||||
|
let temp_target = document.createElement("div");
|
||||||
|
|
||||||
|
let options = html`${this._emptyLabelTemplate()}${this.select_options.map(this._optionTemplate.bind(this))}`;
|
||||||
|
|
||||||
|
render(options, temp_target);
|
||||||
|
return Promise.all(([...temp_target.querySelectorAll(":scope > *")].map(item => item.render)))
|
||||||
|
.then(() =>
|
||||||
|
{
|
||||||
|
temp_target.querySelectorAll(":scope > *").forEach((item) =>
|
||||||
|
{
|
||||||
|
// Avoid duplicate error
|
||||||
|
if(!this._optionTargetNode.querySelector("[value='" + item.value + "']"))
|
||||||
|
{
|
||||||
|
this._optionTargetNode.appendChild(item);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if(typeof this.handleMenuSlotChange == "function")
|
||||||
|
{
|
||||||
|
this.handleMenuSlotChange();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -437,11 +437,46 @@ export const Et2WithSearchMixin = <T extends Constructor<LitElement>>(superclass
|
|||||||
return this.querySelectorAll(this.optionTag + ":not(.remote)");
|
return this.querySelectorAll(this.optionTag + ":not(.remote)");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Only remote options from search results
|
||||||
|
* @returns {NodeList}
|
||||||
|
* @protected
|
||||||
|
*/
|
||||||
protected get remoteItems() : NodeList
|
protected get remoteItems() : NodeList
|
||||||
{
|
{
|
||||||
return this.querySelectorAll(this.optionTag + ".remote");
|
return this.querySelectorAll(this.optionTag + ".remote");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Only free entries
|
||||||
|
* @returns {NodeList}
|
||||||
|
* @protected
|
||||||
|
*/
|
||||||
|
protected get freeEntries() : NodeList
|
||||||
|
{
|
||||||
|
return this.querySelectorAll(this.optionTag + ".freeEntry");
|
||||||
|
}
|
||||||
|
|
||||||
|
get search_options() : SelectOption[]
|
||||||
|
{
|
||||||
|
let options = [];
|
||||||
|
|
||||||
|
if(this.allowFreeEntries)
|
||||||
|
{
|
||||||
|
this.freeEntries.forEach((item) =>
|
||||||
|
{
|
||||||
|
options.push({value: item.value, label: item.textContent, class: item.classList.toString()});
|
||||||
|
})
|
||||||
|
}
|
||||||
|
// Any provided options
|
||||||
|
options = options.concat(this.__search_options);
|
||||||
|
|
||||||
|
// Any kept remote options
|
||||||
|
options = options.concat(this._selected_remote);
|
||||||
|
|
||||||
|
return options;
|
||||||
|
}
|
||||||
|
|
||||||
get value()
|
get value()
|
||||||
{
|
{
|
||||||
return super.value;
|
return super.value;
|
||||||
@ -897,6 +932,11 @@ export const Et2WithSearchMixin = <T extends Constructor<LitElement>>(superclass
|
|||||||
// Remove "no suggestions"
|
// Remove "no suggestions"
|
||||||
target.querySelector(".no-results")?.remove();
|
target.querySelector(".no-results")?.remove();
|
||||||
|
|
||||||
|
// Remove any previously selected remote options that aren't used anymore
|
||||||
|
this._selected_remote = this._selected_remote.filter((option) =>
|
||||||
|
{
|
||||||
|
return this.value.indexOf(option.value) != -1;
|
||||||
|
});
|
||||||
// Remove remote options that aren't used
|
// Remove remote options that aren't used
|
||||||
let keepers = this._selected_remote.reduce((prev, current) =>
|
let keepers = this._selected_remote.reduce((prev, current) =>
|
||||||
{
|
{
|
||||||
@ -1005,9 +1045,8 @@ export const Et2WithSearchMixin = <T extends Constructor<LitElement>>(superclass
|
|||||||
let target = this._optionTargetNode || this;
|
let target = this._optionTargetNode || this;
|
||||||
if(target)
|
if(target)
|
||||||
{
|
{
|
||||||
// Keep local options first, add in remote options
|
// Add in remote options, avoiding duplicates
|
||||||
// Include already selected remote entries, or they will be removed and we lose icon/class
|
this.select_options.filter(function(item)
|
||||||
this.select_options.concat(this._selected_remote).filter(function(item)
|
|
||||||
{
|
{
|
||||||
let i = entries.findIndex(x => (x.value == item.value));
|
let i = entries.findIndex(x => (x.value == item.value));
|
||||||
if(i <= -1)
|
if(i <= -1)
|
||||||
@ -1020,11 +1059,8 @@ export const Et2WithSearchMixin = <T extends Constructor<LitElement>>(superclass
|
|||||||
let options = html`${entries.map(this._optionTemplate.bind(this))}`;
|
let options = html`${entries.map(this._optionTemplate.bind(this))}`;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Doing all this garbage to get the options to always show up.
|
* Add in new options.
|
||||||
* If we just do `render(options, target)`, they only show up in the DOM the first time. If the
|
* Rendering directly into target will remove existing options, which we don't need to do
|
||||||
* same option comes back in a subsequent search, it map() does not put it into the DOM.
|
|
||||||
* If we render into a new target, the options get rendered, but we have to wait for them to be
|
|
||||||
* rendered before we can do anything else with them.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
let temp_target = document.createElement("div");
|
let temp_target = document.createElement("div");
|
||||||
@ -1087,7 +1123,8 @@ export const Et2WithSearchMixin = <T extends Constructor<LitElement>>(superclass
|
|||||||
{
|
{
|
||||||
this.__select_options.push(<SelectOption>{
|
this.__select_options.push(<SelectOption>{
|
||||||
value: text,
|
value: text,
|
||||||
label: text
|
label: text,
|
||||||
|
class: "freeEntry"
|
||||||
});
|
});
|
||||||
this.requestUpdate('select_options');
|
this.requestUpdate('select_options');
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user