Initial work on #13283

This commit is contained in:
Jeremy Stretch 2024-02-08 17:13:04 -05:00
parent d63e1dacbf
commit ff460c2829
4 changed files with 59 additions and 7 deletions

Binary file not shown.

Binary file not shown.

View File

@ -31,6 +31,13 @@ export class DynamicTomSelect extends TomSelect {
// Glean the REST API endpoint URL from the <select> element
this.api_url = this.input.getAttribute('data-url') as string;
// Override any field names set as widget attributes
this.valueField = this.input.getAttribute('ts-value-field') || this.settings.valueField;
this.labelField = this.input.getAttribute('ts-label-field') || this.settings.labelField;
this.parentField = this.input.getAttribute('ts-parent-field') || null;
this.depthField = this.input.getAttribute('ts-depth-field') || '_depth';
this.descriptionField = this.input.getAttribute('ts-description-field') || 'description';
// Set the null option (if any)
const nullOption = this.input.getAttribute('data-null-option');
if (nullOption) {
@ -82,10 +89,20 @@ export class DynamicTomSelect extends TomSelect {
// Make the API request
fetch(url)
.then(response => response.json())
.then(json => {
self.loadCallback(json.results, []);
.then(apiData => {
const results: Dict[] = apiData.results;
let options: Dict[] = []
for (let result of results) {
const option = self.getOptionFromData(result);
options.push(option);
}
return options;
})
// Pass the options to the callback function
.then(options => {
self.loadCallback(options, []);
}).catch(()=>{
self.loadCallback([], []);
self.loadCallback([], []);
});
}
@ -126,6 +143,21 @@ export class DynamicTomSelect extends TomSelect {
return queryString.stringifyUrl({ url, query });
}
// Compile TomOption data from an API result
getOptionFromData(data: Dict) {
let option: Dict = {
id: data[this.valueField],
display: data[this.labelField],
depth: data[this.depthField] || null,
description: data[this.descriptionField] || null,
};
if (data[this.parentField]) {
let parent: Dict = data[this.parentField] as Dict;
option['parent'] = parent[this.labelField];
}
return option
}
/**
* Transitional methods
*/

View File

@ -10,12 +10,31 @@ const MAX_OPTIONS = 100;
// Render the HTML for a dropdown option
function renderOption(data: TomOption, escape: typeof escape_html) {
// If the option has a `_depth` property, indent its label
if (typeof data._depth === 'number' && data._depth > 0) {
return `<div>${'─'.repeat(data._depth)} ${escape(data[LABEL_FIELD])}</div>`;
let html = '<div>';
// If the option has a `depth` property, indent its label
if (typeof data.depth === 'number' && data.depth > 0) {
html = `${html}${'─'.repeat(data.depth)} `;
}
return `<div>${escape(data[LABEL_FIELD])}</div>`;
html = `${html}${escape(data[LABEL_FIELD])}`;
if (data['parent']) {
html = `${html} <span class="text-secondary">${escape(data['parent'])}</span>`;
}
if (data['description']) {
html = `${html}<br /><small class="text-secondary">${escape(data['description'])}</small>`;
}
html = `${html}</div>`;
return html;
}
// Render the HTML for a selected item
function renderItem(data: TomOption, escape: typeof escape_html) {
if (data['parent']) {
return `<div>${escape(data['parent'])} > ${escape(data[LABEL_FIELD])}</div>`;
}
return `<div>${escape(data[LABEL_FIELD])}<div>`;
}
// Initialize <select> elements which are populated via a REST API call
@ -40,6 +59,7 @@ export function initDynamicSelects(): void {
// Define custom rendering functions
render: {
option: renderOption,
item: renderItem,
},
// By default, load() will be called only if query.length > 0