Fix TomSelect dropdown ordering

This commit is contained in:
Arthur
2026-01-08 16:17:40 -08:00
parent f54ed8bb7f
commit e6300ee06d
4 changed files with 56 additions and 22 deletions

View File

@@ -733,9 +733,10 @@ class ModuleForm(ModuleCommonForm, PrimaryModelForm):
) )
module_bay = DynamicModelChoiceField( module_bay = DynamicModelChoiceField(
label=_('Module bay'), label=_('Module bay'),
queryset=ModuleBay.objects.all(), queryset=ModuleBay.objects.order_by('name'),
query_params={ query_params={
'device_id': '$device' 'device_id': '$device',
'ordering': 'name',
}, },
context={ context={
'disabled': 'installed_module', 'disabled': 'installed_module',

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -75,16 +75,21 @@ export class DynamicTomSelect extends TomSelect {
load(value: string) { load(value: string) {
const self = this; const self = this;
// Automatically clear any cached options. (Only options included // Save current selection before clearing
// in the API response should be present.) const currentValue = self.getValue();
// Clear cached options (only options from API response should be present)
self.clearOptions(); self.clearOptions();
// Populate the null option (if any) if not searching // Clear user_options to prevent the pre-selected option from being treated specially
(self as any).user_options = {};
// Populate the null option if not searching
if (self.nullOption && !value) { if (self.nullOption && !value) {
self.addOption(self.nullOption); self.addOption(self.nullOption);
} }
// Get the API request URL. If none is provided, abort as no request can be made. // Get the API request URL
const url = self.getRequestUrl(value); const url = self.getRequestUrl(value);
if (!url) { if (!url) {
return; return;
@@ -98,16 +103,44 @@ export class DynamicTomSelect extends TomSelect {
.then(response => response.json()) .then(response => response.json())
.then(apiData => { .then(apiData => {
const results: Dict[] = apiData.results; const results: Dict[] = apiData.results;
const options: Dict[] = [];
for (const result of results) { // Add each option and then set $order to match API response order
results.forEach((result, index) => {
const option = self.getOptionFromData(result); const option = self.getOptionFromData(result);
options.push(option); self.addOption(option);
// Set $order AFTER addOption() to prevent it from being overwritten
const key = option[self.settings.valueField as string] as string;
if (self.options[key]) {
(self.options[key] as any).$order = index;
}
});
// Debug: log the $order values
console.log('Options after adding:');
for (const key in self.options) {
const opt = self.options[key] as any;
console.log(` ${opt.display} -> $order: ${opt.$order}`);
} }
return options;
}) // Trigger loading complete
// Pass the options to the callback function self.loading = Math.max(self.loading - 1, 0);
.then(options => { if (self.loading === 0) {
self.loadCallback(options, []); self.wrapper.classList.remove(self.settings.loadingClass as string);
}
console.log('Before restore - currentValue:', currentValue, 'items:', self.items);
// Restore the selection
if (currentValue && !self.items.includes(currentValue as string)) {
self.items.push(currentValue as string);
}
console.log('After restore - items:', self.items);
// Refresh the dropdown display
self.refreshOptions(false);
console.log('After refreshOptions - items:', self.items);
}) })
.catch(() => { .catch(() => {
self.loadCallback([], []); self.loadCallback([], []);