enum item handler

This commit is contained in:
Yurii
2026-04-03 12:02:31 +03:00
parent 6e89073afc
commit 5c2fd0951e
5 changed files with 155 additions and 32 deletions

View File

@@ -1,11 +1,19 @@
{{#if isNotEmpty}}
{{#if style}}
<span class="{{class}}-{{style}}"
>{{/if}}{{valueTranslated}}{{#if style}}</span>{{/if}}
{{~#if hasColor~}}
<span
class="color-icon fas fa-square text-soft"
style=" {{#if color}} color: {{color}}; {{/if}} "
></span><span style="user-select: none">&nbsp;</span>
{{~/if~}}
{{~#if style~}}
<span class="{{class}}-{{style}}">
{{~/if~}}
{{valueTranslated}}
{{~#if style~}}</span>{{~/if~}}
{{else}}
{{#if valueIsSet}}
<span class="none-value">{{translate 'None'}}</span>
{{else}}
<span class="loading-value"></span>
{{/if}}
{{/if}}
{{~#if valueIsSet~}}
<span class="none-value">{{translate 'None'}}</span>
{{~else~}}
<span class="loading-value"></span>
{{~/if~}}
{{/if~}}

View File

@@ -1,7 +1,16 @@
{{#if isNotEmpty}}
{{#if style}}
<span
class="{{class}}-{{style}}"
title="{{valueTranslated}}"
>{{/if}}{{valueTranslated}}{{#if style}}</span>{{/if}}
{{/if}}
{{#if isNotEmpty~}}
{{~#if hasColor~}}
<span
class="color-icon fas fa-square text-soft"
style=" {{#if color}} color: {{color}}; {{/if}} "
></span><span style="user-select: none">&nbsp;</span>
{{~/if~}}
{{~#if style~}}
<span
class="{{class}}-{{style}}"
title="{{valueTranslated}}"
>
{{~/if~}}
{{valueTranslated}}
{{~#if style}}</span>{{~/if~}}
{{~/if~}}

View File

@@ -42,6 +42,13 @@ import Selectize from 'lib!selectize';
* @property {'value'|'text'|'$order'|'$score'} [sortBy='$order'] Item sorting.
* @property {'asc'|'desc'} [sortDirection='asc'] Sort direction.
* @property {function()} [onFocus] On-focus callback.
* @property {
* function({value: string}): {
* text?: string,
* style?: 'default'|'danger'|'success'|'warning'|'info'|null,
* color?: string|null,
* }
* } [itemHandler] Handles an item to override the label or add a style. As of v9.4.0.
*/
/**
@@ -107,6 +114,44 @@ const Select = {
$relativeParent = $modalBody;
}
/**
*
* @param {{value: string, text: string}} item
* @return {{
* className: string,
* text: string,
* prefixElement?: HTMLElement,
* }}
*/
const prepareItem = item => {
let className = itemClasses[item.value] ?? '';
let text = item.text;
let prefixElement;
if (options.itemHandler) {
const result = options.itemHandler({value: item.value});
if (result.style) {
className = 'text-' + result.style;
}
if (result.text != null) {
text = result.text;
}
if (result.color !== undefined) {
prefixElement = document.createElement('span');
prefixElement.className = 'color-icon fas fa-square text-soft';
if (result.color) {
prefixElement.style.color = result.color;
}
}
}
return {className, text, prefixElement};
};
// noinspection JSUnusedGlobalSymbols
const selectizeOptions = {
sortField: [{field: options.sortBy, direction: options.sortDirection}],
@@ -121,25 +166,42 @@ const Select = {
$relativeParent: $relativeParent,
render: {
item: function (data) {
return $('<div>')
.addClass('item')
.addClass(itemClasses[data.value] || '')
.text(data.text)
.get(0).outerHTML;
},
option: function (data) {
const $div = $('<div>')
.addClass('option')
.addClass(data.value === '' ? 'selectize-dropdown-emptyoptionlabel' : '')
.addClass(itemClasses[data.value] || '')
.val(data.value)
.text(data.text);
const item = prepareItem(data);
if (data.text === '') {
$div.html('&nbsp;');
const div = document.createElement('div');
div.className = item.className;
div.classList.add('item');
div.textContent = item.text;
if (item.prefixElement && data.text !== '') {
div.prepend(item.prefixElement);
}
return $div.get(0).outerHTML;
return div.outerHTML;
},
option: function (data) {
const item = prepareItem(data);
const div = document.createElement('div');
div.className = item.className;
div.classList.add('option');
div.textContent = item.text;
div.setAttribute('data-value', data.value);
if (data.value === '') {
div.classList.add('selectize-dropdown-emptyoptionlabel')
}
if (data.text === '') {
div.innerHTML = '&nbsp;';
}
if (item.prefixElement && data.text !== '') {
div.prepend(item.prefixElement);
}
return div.outerHTML;
},
},
onDelete: function (values) {

View File

@@ -46,6 +46,8 @@ class EnumFieldView extends BaseFieldView {
* module:views/fields/base~params &
* Object.<string, *>
* } [params] Parameters.
* @property {module:views/fields/enumeration~optionItemHandler} [optionItemHandler]
* Handles an option item to override the label or add a style. As of v9.4.0.
*/
/**
@@ -63,6 +65,16 @@ class EnumFieldView extends BaseFieldView {
* @property {Object.<string, string>} [translatedOptions] Option translations.
*/
/**
* @typedef {
* function({value: string}): {
* text?: string,
* style?: 'default'|'danger'|'success'|'warning'|'info'|null,
* color?: string|null,
* }
* } module:views/fields/enumeration~optionItemHandler
*/
/**
* @param {
* module:views/fields/enumeration~options &
@@ -103,6 +115,12 @@ class EnumFieldView extends BaseFieldView {
*/
nativeSelect = false;
/**
* @protected
* @type {module:views/fields/enumeration~optionItemHandler|null}
*/
optionItemHandler = null
// noinspection JSCheckFunctionSignatures
/** @inheritDoc */
data() {
@@ -159,6 +177,15 @@ class EnumFieldView extends BaseFieldView {
data.nativeSelect = this.nativeSelect;
}
if (this.isReadMode() && this.optionItemHandler && this.model.attributes[this.name]) {
const item = this.optionItemHandler({value: this.model.attributes[this.name]});
if (item.color != null) {
data.color = item.color;
data.hasColor = true;
}
}
// noinspection JSValidateTypes
return data;
}
@@ -172,6 +199,10 @@ class EnumFieldView extends BaseFieldView {
}
}
if (this.options.optionItemHandler) {
this.optionItemHandler = this.options.optionItemHandler;
}
this.styleMap = this.params.style || this.model.getFieldParam(this.name, 'style') || {};
let optionsPath = this.params.optionsPath;
@@ -435,6 +466,7 @@ class EnumFieldView extends BaseFieldView {
if ((this.isEditMode() || this.isSearchMode()) && !this.nativeSelect) {
Select.init(this.$element, {
matchAnyWord: true,
itemHandler: this.optionItemHandler,
});
}
}

View File

@@ -63,6 +63,10 @@
vertical-align: top;
text-overflow: ellipsis;
white-space: nowrap;
.color-icon {
padding-right: var(--5px);
}
}
cursor: default;
@@ -71,6 +75,14 @@
.selectize-dropdown {
z-index: 1031;
.selectize-dropdown-content {
.option {
.color-icon {
padding-right: var(--5px);
}
}
}
}
}