/** * EGroupware eTemplate2 - WidgetWithSelectMixin * * @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License * @package api * @link https://www.egroupware.org * @author Nathan Gray */ import {Et2InputWidget, Et2InputWidgetInterface} from "../Et2InputWidget/Et2InputWidget"; import {html, LitElement, PropertyValues, render, TemplateResult} from "@lion/core"; import {et2_readAttrWithDefault} from "../et2_core_xml"; import {cleanSelectOptions, find_select_options, SelectOption} from "./FindSelectOptions"; import {SearchMixinInterface} from "./SearchMixin"; /** * Base class for things that do selectbox type behaviour, to avoid putting too much or copying into read-only * selectboxes, also for common handling of properties for more special selectboxes. * * As with most other widgets that extend Lion components, do not override render(). * To extend this mixin, override: * - _optionTargetNode(): Return the HTMLElement where the "options" go. * - _optionTemplate(option:SelectOption): Renders the option. To use a special widget, use its tag in render. * Select option: * ```js * return html` * `; * ``` * * * or pass it off to a different WebComponent: * * ```js * _optionTemplate(option:SelectOption) : TemplateResult * { * return html` * `; * } * ``` * * Optionally, you can override: * - _emptyLabelTemplate(): How to render the empty label * - slots(): Most Lion components have an input slot where the tag is created. * You can specify something else, or return {} to do your own thing. This is a little more complicated. You should * also override _inputGroupInputTemplate() to do what you normally would in render(). * * * Technical note: * LionSelect (and any other LionField) use slots to wrap a real DOM node. ET2 doesn't expect this, * so we have to create the input node (via slots()) and respect that it is _external_ to the Web Component. * This complicates things like adding the options, since we can't just override _inputGroupInputTemplate() * and include them when rendering - the parent expects to find the tag (this._inputNode) but in a more * complicated widget, this could be anything. * * @overridable * @returns {HTMLElement} */ get _optionTargetNode() : HTMLElement { return this; } /** * Render the "empty label", used when the selectbox does not currently have a value * * @overridable * @returns {TemplateResult} */ _emptyLabelTemplate() : TemplateResult { return html`${this.emptyLabel}`; } /** * Render a single option * * Override this method to specify how to render each option. * In a normal selectbox, this would be something like: *``` * `; * ``` * but you can do whatever you need. To use a different WebComponent, just use its tag instead of "option". * We should even be able to pass the whole SelectOption across * ``` * * ``` * * @overridable * @param {SelectOption} option * @returns {TemplateResult} */ _optionTemplate(option : SelectOption) : TemplateResult { return html` Override _optionTemplate(). ${option.value} => ${option.label}`; } _groupTemplate(option) : TemplateResult { if(!Array.isArray(option.value)) { return this._optionTemplate(option); } return html` ${option.label} ${option.value.map(this._optionTemplate.bind(this))} `; } /** * Load extra stuff from the template node. In particular, we're looking for any