Fixes #7081: Properly handle pre-selected values even when they're outside of pagination limits

This commit is contained in:
thatmattlove 2021-08-31 15:13:42 -07:00
parent 5b87232f59
commit 093a86bc38
3 changed files with 29 additions and 10 deletions

Binary file not shown.

Binary file not shown.

View File

@ -389,6 +389,19 @@ export class APISelect {
} }
} }
/**
* Get all options from the native select element that are already selected and do not contain
* placeholder values.
*/
private getPreselectedOptions(): HTMLOptionElement[] {
return Array.from(this.base.options)
.filter(option => option.selected)
.filter(option => {
if (option.value === '---------' || option.innerText === '---------') return false;
return true;
});
}
/** /**
* Process a valid API response and add results to this instance's options. * Process a valid API response and add results to this instance's options.
* *
@ -398,13 +411,19 @@ export class APISelect {
data: APIAnswer<APIObjectBase>, data: APIAnswer<APIObjectBase>,
action: ApplyMethod = 'merge', action: ApplyMethod = 'merge',
): Promise<void> { ): Promise<void> {
// Get all non-placeholder (empty) options' values. If any exist, it means we're editing an // Get all already-selected options.
// existing object. When we fetch options from the API later, we can set any of the options const preSelected = this.getPreselectedOptions();
// contained in this array to `selected`.
const selectOptions = Array.from(this.base.options) // Get the values of all already-selected options.
.filter(option => option.selected) const selectedValues = preSelected.map(option => option.getAttribute('value')).filter(isTruthy);
.map(option => option.getAttribute('value'))
.filter(isTruthy); // Build SlimSelect options from all already-selected options.
const preSelectedOptions = preSelected.map(option => ({
value: option.value,
text: option.innerText,
selected: true,
disabled: false,
})) as Option[];
let options = [] as Option[]; let options = [] as Option[];
@ -441,12 +460,12 @@ export class APISelect {
} }
// Set option to disabled if it is contained within the disabled array. // Set option to disabled if it is contained within the disabled array.
if (selectOptions.some(option => this.disabledOptions.includes(option))) { if (selectedValues.some(option => this.disabledOptions.includes(option))) {
disabled = true; disabled = true;
} }
// Set pre-selected options. // Set pre-selected options.
if (selectOptions.includes(value)) { if (selectedValues.includes(value)) {
selected = true; selected = true;
// If an option is selected, it can't be disabled. Otherwise, it won't be submitted with // If an option is selected, it can't be disabled. Otherwise, it won't be submitted with
// the rest of the form, resulting in that field's value being deleting from the object. // the rest of the form, resulting in that field's value being deleting from the object.
@ -469,7 +488,7 @@ export class APISelect {
this.options = [...this.options, ...options]; this.options = [...this.options, ...options];
break; break;
case 'replace': case 'replace':
this.options = options; this.options = [...preSelectedOptions, ...options];
break; break;
} }