Add support for static parameters

This commit is contained in:
Jeremy Stretch 2024-01-29 16:09:12 -05:00
parent 35966cb988
commit 36824d16e0
3 changed files with 114 additions and 16 deletions

Binary file not shown.

Binary file not shown.

View File

@ -1,15 +1,124 @@
import { getElements } from './util';
import { TomOption } from 'tom-select/src/types';
import { RecursivePartial, TomInput, TomOption, TomSettings } from 'tom-select/src/types';
import { addClasses } from 'tom-select/src/vanilla'
import queryString from 'query-string';
import TomSelect from 'tom-select';
import type { Stringifiable } from 'query-string';
// Transitional
import { QueryFilter } from './select/api/types'
class DynamicTomSelect extends TomSelect {
// Override load() to automatically clear any cached options. (Only options included
// in the API response should be present.)
/*
* Transitional code from APISelect
*/
private readonly queryParams: QueryFilter = new Map();
private readonly staticParams: QueryFilter = new Map();
/**
* Overrides
*/
constructor( input_arg: string|TomInput, user_settings: RecursivePartial<TomSettings> ) {
super(input_arg, user_settings);
this.api_url = this.input.getAttribute('data-url') as string;
// Populate static query parameters.
this.getStaticParams();
for (const [key, value] of this.staticParams.entries()) {
this.queryParams.set(key, value);
}
}
load(value: string) {
this.clearOptions();
super.load(value);
const self = this;
// Automatically clear any cached options. (Only options included
// in the API response should be present.)
if (value) {
self.clearOptions();
}
addClasses(self.wrapper, self.settings.loadingClass);
self.loading++;
const callback = self.loadCallback.bind(self);
const url = self.getRequestUrl(value);
// Make the API request
fetch(url)
.then(response => response.json())
.then(json => {
callback(json.results);
}).catch(()=>{
callback();
});
}
/**
* Custom methods
*/
/**
* Formulate and return the complete URL for an API request, including any query parameters.
*/
getRequestUrl(search: string): string {
const url = this.api_url;
// Create new URL query parameters based on the current state of `queryParams` and create an
// updated API query URL.
const query = {} as Dict<Stringifiable[]>;
for (const [key, value] of this.queryParams.entries()) {
query[key] = value;
}
// Append the search query, if any
if (search) {
query['q'] = [search];
}
// Enable "brief" mode
query['brief'] = ['True'];
return queryString.stringifyUrl({ url, query });
}
/**
* Transitional methods
*/
/**
* Determine if this instance's options should be filtered by static values passed from the
* server.
*
* Looks for the DOM attribute `data-static-params`, the value of which is a JSON array of
* objects containing key/value pairs to add to `this.staticParams`.
*/
private getStaticParams(): void {
const serialized = this.input.getAttribute('data-static-params');
try {
if (serialized) {
const deserialized = JSON.parse(serialized);
if (deserialized) {
for (const { queryParam, queryValue } of deserialized) {
if (Array.isArray(queryValue)) {
this.staticParams.set(queryParam, queryValue);
} else {
this.staticParams.set(queryParam, [queryValue]);
}
}
}
}
} catch (err) {
console.group(`Unable to determine static query parameters for select field '${this.name}'`);
console.warn(err);
console.groupEnd();
}
}
}
@ -29,7 +138,6 @@ function initStaticSelects(): void {
function initDynamicSelects(): void {
for (const select of getElements<HTMLSelectElement>('select.api-select')) {
const api_url = select.getAttribute('data-url') as string;
new DynamicTomSelect(select, {
plugins: ['clear_button'],
valueField: 'id',
@ -39,16 +147,6 @@ function initDynamicSelects(): void {
dropdownParent: 'body',
controlInput: '<input>',
preload: 'focus',
load: function(query: string, callback: Function) {
let url = api_url + '?brief=True&q=' + encodeURIComponent(query);
fetch(url)
.then(response => response.json())
.then(json => {
callback(json.results);
}).catch(()=>{
callback();
});
},
});
}