diff --git a/src/webcomponents/commons/catalog-browser-grid-config.js b/src/webcomponents/commons/catalog-browser-grid-config.js
index 0fe96d27b1..aadee51598 100644
--- a/src/webcomponents/commons/catalog-browser-grid-config.js
+++ b/src/webcomponents/commons/catalog-browser-grid-config.js
@@ -228,9 +228,11 @@ export default class CatalogBrowserGridConfig extends LitElement {
dataFormFilterChange(e.detail.value)}">
`;
diff --git a/src/webcomponents/commons/filters/disease-panel-filter.js b/src/webcomponents/commons/filters/disease-panel-filter.js
index e3d539c9ad..7d80e3e7f8 100644
--- a/src/webcomponents/commons/filters/disease-panel-filter.js
+++ b/src/webcomponents/commons/filters/disease-panel-filter.js
@@ -17,6 +17,7 @@
import {LitElement, html, nothing} from "lit";
import LitUtils from "../utils/lit-utils.js";
import "../forms/select-field-filter.js";
+import "../forms/select-field-filter2.js";
import "../forms/toggle-switch.js";
import "../forms/toggle-radio.js";
@@ -210,16 +211,17 @@ export default class DiseasePanelFilter extends LitElement {
` : nothing
}
- 5}
- .multiple="${this.multiple || false}"
.classes="${this.classes}"
- .disabled="${this.disabled || false}"
- separator="\n"
+ .config="${{
+ tags: false,
+ multiple: this.multiple,
+ separator: "\n"
+ }}"
@filterChange="${e => this.filterChange(e, "panel")}">
-
+
${this.showSelectedPanels && this.panel?.length > 0 ? html`
diff --git a/src/webcomponents/commons/forms/select-field-filter2.js b/src/webcomponents/commons/forms/select-field-filter2.js
index cffa1bed30..b396704520 100644
--- a/src/webcomponents/commons/forms/select-field-filter2.js
+++ b/src/webcomponents/commons/forms/select-field-filter2.js
@@ -37,63 +37,34 @@ export default class SelectFieldFilter2 extends LitElement {
value: {
type: String
},
- title: {
- type: String
- },
- placeholder: {
- type: String
- },
- multiple: {
- type: Boolean
- },
- all: {
- type: Boolean
- },
- disabled: {
- type: Boolean
- },
- required: {
- type: Boolean
- },
- maxOptions: {
- type: Number
- },
- liveSearch: {
- type: Boolean
- },
- forceSelection: {
- type: Boolean
- },
- classes: {
- type: String
- },
- size: {
- type: Number,
- },
- separator: {
- type: String,
- },
// the expected format is either an array of string or an array of objects {id, name}
data: {
type: Object
+ },
+ config: {
+ type: Object
}
};
}
_init() {
this._prefix = UtilsNew.randomString(8);
- // $.fn.selectpicker.Constructor.BootstrapVersion = "5";
- this.multiple = false;
- this.all = false;
this.data = [];
this.classes = "";
- this.elm = this._prefix + "selectpicker";
- this.size = 20; // Default size
- this.separator = ","; // Default separator
}
firstUpdated() {
this.select = $("#" + this._prefix);
+ if (!this._config?.tags) {
+ this.customAdapter();
+ }
+ }
+
+ update(changedProperties) {
+ if (changedProperties.has("config")) {
+ this._config = {...this.getDefaultConfig(), ...this.config};
+ }
+ super.update(changedProperties);
}
updated(changedProperties) {
@@ -101,7 +72,8 @@ export default class SelectFieldFilter2 extends LitElement {
this.loadData();
}
- if (changedProperties.has("value") || changedProperties.has("disabled")) {
+ if (changedProperties.has("value")) {
+ // TODO: Figure out why this does not execute when config.tags are false.
this.loadValueSelected();
}
}
@@ -124,42 +96,167 @@ export default class SelectFieldFilter2 extends LitElement {
});
}
});
- this.select.select2({
+ const selectConfig = {
theme: "bootstrap-5",
+ dropdownParent: document.querySelector(`#${this._prefix}`).parentElement,
selectionCssClass: "select2--small",
- tags: this._config?.freeTag ?? false,
- multiple: this.multiple,
- separator: this.separator,
- placeholder: this.placeholder || "Select option(s)",
- disabled: this.disabled,
+ multiple: this._config?.multiple,
+ placeholder: this._config?.placeholder,
+ disabled: false,
width: "80%",
data: options,
- tokenSeparator: this.tokenSeparator,
- selectOnClose: false,
+ tokenSeparator: this._config?.separator,
+ closeOnSelect: false,
templateResult: e => this.optionsFormatter(e),
- })
- .on("select2:select", e => this.filterChange(e))
- .on("select2:unselect", e => this.filterChange(e));
+ ...this._config,
+ };
+
+ if (!this._config?.tags) {
+ const searchBox = {dropdownAdapter: $.fn.select2.amd.require("CustomDropdownAdapter")};
+ const selectAdapter = {
+ templateSelection: data => {
+ return `Selected ${data.selected.length} out of ${data.all.length}`;
+ },
+ // Make selection-box similar to single select
+ selectionAdapter: $.fn.select2.amd.require("CustomSelectionAdapter"),
+ ...this._config.liveSearch ? searchBox : {}
+ };
+
+ this.select.select2({...selectConfig, ...selectAdapter})
+ .on("select2:select", e => this.filterChange(e))
+ .on("select2:unselect", e => this.filterChange(e));
+
+ if (this.value) {
+ // temporal solution for now to load selected values
+ this.loadValueSelected();
+ }
+
+ } else {
+ this.select.select2({...selectConfig})
+ .on("select2:select", e => this.filterChange(e))
+ .on("select2:unselect", e => this.filterChange(e));
+
+ }
- this.querySelector("span.select2-search.select2-search--inline").style = "display: none";
+ // This hides the search field for basic select2 tags.
+ if (!this.config?.liveSearch && !this.config?.tags) {
+ this.querySelector("span.select2-search select2-search--dropdown").style.display = "none";
+ }
}
}
+ customAdapter() {
+
+ $.fn.select2.amd.define("CustomSelectionAdapter", [
+ "select2/utils",
+ "select2/selection/multiple",
+ "select2/selection/placeholder",
+ "select2/selection/eventRelay",
+ "select2/selection/single",
+ ], (Utils, MultipleSelection, Placeholder, EventRelay, SingleSelection) => {
+
+ // Decorates MultipleSelection with Placeholder
+ let adapter = Utils.Decorate(MultipleSelection, Placeholder);
+ // Decorates adapter with EventRelay - ensures events will continue to fire
+ // e.g. selected, changed
+ adapter = Utils.Decorate(adapter, EventRelay);
+
+ adapter.prototype.render = function () {
+ // Use selection-box from SingleSelection adapter
+ // This implementation overrides the default implementation
+ const $selection = SingleSelection.prototype.render.call(this);
+ return $selection;
+ };
+
+ adapter.prototype.update = function (data) {
+ // copy and modify SingleSelection adapter
+ this.clear();
+
+ const $rendered = this.$selection.find(".select2-selection__rendered");
+ const noItemsSelected = data.length === 0;
+ let formatted = "";
+
+ if (noItemsSelected) {
+ formatted = this.options.get("placeholder") || "";
+ } else {
+ const itemsData = {
+ selected: data || [],
+ all: this.$element.find("option") || []
+ };
+ // Pass selected and all items to display method
+ // which calls templateSelection
+ formatted = this.display(itemsData, $rendered);
+ }
+
+ $rendered.empty().append(formatted);
+ $rendered.prop("title", formatted);
+ };
+
+ return adapter;
+ });
+
+ $.fn.select2.amd.define("CustomDropdownAdapter", [
+ "select2/utils",
+ "select2/dropdown",
+ "select2/dropdown/attachBody",
+ "select2/dropdown/attachContainer",
+ "select2/dropdown/search",
+ "select2/dropdown/minimumResultsForSearch",
+ "select2/dropdown/closeOnSelect",
+ ], (Utils, Dropdown, AttachBody, AttachContainer, Search, MinimumResultsForSearch, CloseOnSelect) => {
+
+ // Decorate Dropdown with Search functionalities
+ const dropdownWithSearch = Utils.Decorate(Dropdown, Search);
+ dropdownWithSearch.prototype.render = function () {
+ // Copy and modify default search render method
+ const $rendered = Dropdown.prototype.render.call(this);
+ // Add ability for a placeholder in the search box
+ const placeholder = this.options.get("placeholderForSearch") || "";
+ const $search = $(
+ `
+
+ `
+ );
+
+ this.$searchContainer = $search;
+ this.$search = $search.find("input");
+
+ $rendered.prepend($search);
+ return $rendered;
+ };
+
+ // Decorate the dropdown+search with necessary containers
+ let adapter = Utils.Decorate(dropdownWithSearch, AttachContainer);
+ adapter = Utils.Decorate(adapter, AttachBody);
+
+ return adapter;
+ });
+
+ }
+
optionsFormatter(item) {
// optgroup elements
if (typeof item.children != "undefined") {
return $(`
- ${item.text}
+
+
+ ${item.text}
+
`);
}
return $(`
- ${item.text}
+
+ ${item.text}
+
+
`);
}
loadValueSelected() {
let val = "";
- if (this.value && this.multiple) {
+ if (this.value && this._config?.multiple) {
val = Array.isArray(this.value) ? this.value : this.value.split(",");
} else {
val = UtilsNew.isNotUndefinedOrNull(this.value) ? this.value : "";
@@ -192,7 +289,7 @@ export default class SelectFieldFilter2 extends LitElement {
let val = "";
if (selection && selection.length) {
- if (this.multiple) {
+ if (this._config?.multiple) {
val = selection.join(",");
}
}
@@ -229,13 +326,34 @@ export default class SelectFieldFilter2 extends LitElement {
`;
}
+ renderStyle() {
+ return html`
+
+ `;
+ }
+
render() {
return html`
-