diff --git a/docs/release-notes/version-3.0.md b/docs/release-notes/version-3.0.md index ddf23432a..1e7a3022d 100644 --- a/docs/release-notes/version-3.0.md +++ b/docs/release-notes/version-3.0.md @@ -13,6 +13,7 @@ * [#7179](https://github.com/netbox-community/netbox/issues/7179) - Prevent obscuring "connect" pop-up for interfaces under device view * [#7188](https://github.com/netbox-community/netbox/issues/7188) - Fix issue where select fields with `null_option` did not render or send the null option * [#7189](https://github.com/netbox-community/netbox/issues/7189) - Set connection factory for django-redis when Sentinel is in use +* [#7191](https://github.com/netbox-community/netbox/issues/7191) - Fix issue where API-backed multi-select elements cleared selected options when adding new options * [#7193](https://github.com/netbox-community/netbox/issues/7193) - Fix prefix (flat) template issue when viewing child prefixes with prefixes available * [#7205](https://github.com/netbox-community/netbox/issues/7205) - Fix issue where selected fields with `null_option` set were not added to applied filters * [#7209](https://github.com/netbox-community/netbox/issues/7209) - Allow unlimited API results when `MAX_PAGE_SIZE` is disabled diff --git a/netbox/project-static/dist/netbox.js b/netbox/project-static/dist/netbox.js index e4d0f8d8c..a60f4eaa8 100644 Binary files a/netbox/project-static/dist/netbox.js and b/netbox/project-static/dist/netbox.js differ diff --git a/netbox/project-static/dist/netbox.js.map b/netbox/project-static/dist/netbox.js.map index 10b2b5ae5..984391b01 100644 Binary files a/netbox/project-static/dist/netbox.js.map and b/netbox/project-static/dist/netbox.js.map differ diff --git a/netbox/project-static/src/select/api/apiSelect.ts b/netbox/project-static/src/select/api/apiSelect.ts index 690608113..6d83daaac 100644 --- a/netbox/project-static/src/select/api/apiSelect.ts +++ b/netbox/project-static/src/select/api/apiSelect.ts @@ -5,7 +5,7 @@ import SlimSelect from 'slim-select'; import { createToast } from '../../bs'; import { hasUrl, hasExclusions, isTrigger } from '../util'; import { DynamicParamsMap } from './dynamicParams'; -import { isStaticParams } from './types'; +import { isStaticParams, isOption } from './types'; import { hasMore, isTruthy, @@ -156,11 +156,6 @@ export class APISelect { */ private preSorted: boolean = false; - /** - * This instance's available options. - */ - private _options: Option[] = [EMPTY_PLACEHOLDER]; - /** * Array of options values which should be considered disabled or static. */ @@ -295,7 +290,7 @@ export class APISelect { * This instance's available options. */ private get options(): Option[] { - return this._options; + return this.slim.data.data.filter(isOption); } /** @@ -329,7 +324,6 @@ export class APISelect { // If there is not a placeholder, add one to the front. deduplicated.unshift(this.emptyOption); } - this._options = deduplicated; this.slim.setData(deduplicated); } @@ -381,7 +375,12 @@ export class APISelect { const fetcher = debounce((event: Event) => this.handleSearch(event), 300, false); // Query the API when the input value changes or a value is pasted. - this.slim.slim.search.input.addEventListener('keyup', event => fetcher(event)); + this.slim.slim.search.input.addEventListener('keyup', event => { + // Only search when necessary keys are pressed. + if (!event.key.match(/^(Arrow|Enter|Tab).*/)) { + return fetcher(event); + } + }); this.slim.slim.search.input.addEventListener('paste', event => fetcher(event)); // Watch every scroll event to determine if the scroll position is at bottom. @@ -470,7 +469,7 @@ export class APISelect { for (const result of data.results) { let text = result.display; - if (typeof result._depth === 'number') { + if (typeof result._depth === 'number' && result._depth > 0) { // If the object has a `_depth` property, indent its display text. if (!this.preSorted) { this.preSorted = true; diff --git a/netbox/project-static/src/select/api/types.ts b/netbox/project-static/src/select/api/types.ts index a6ab12794..8179f4a3a 100644 --- a/netbox/project-static/src/select/api/types.ts +++ b/netbox/project-static/src/select/api/types.ts @@ -1,4 +1,5 @@ import type { Stringifiable } from 'query-string'; +import type { Option, Optgroup } from 'slim-select/dist/data'; /** * Map of string keys to primitive array values accepted by `query-string`. Keys are used as @@ -187,3 +188,12 @@ export function isStaticParams(value: unknown): value is DataStaticParam[] { } return false; } + +/** + * Type guard to determine if a SlimSelect `dataObject` is an `Option`. + * + * @param data Option or Option Group + */ +export function isOption(data: Option | Optgroup): data is Option { + return !('options' in data); +}