EEZ Studio Dashboard Dropdowns: Keep Option Filtering from Shifting Selection Indices
A mixed-type options array can create two index spaces inside an EEZ Studio Dashboard Dropdown. The widget renders only string elements, but other parts of its implementation still refer to the original array. An index captured from the displayed list can consequently name a different original element.
The Dashboard Dropdown documentation identifies Options and the selected-index Data property. This article examines the concrete filtering path in the pinned widget source, at EEZ Studio v0.29.0 commit 3000161d09d40a5c1dc2477ddc30b38037b3a612.
The issue is narrower than preserving a selection across translated captions. It can arise before any translation or list update, simply because a non-string element disappears during rendering.
One array becomes a shorter option list
The renderer evaluates Options and substitutes an empty array if the result is absent or not an array. It then creates option elements from entries whose JavaScript type is string. A number between two strings is omitted rather than converted into a caption.
However, the select element's current value comes from options[selectedIndex] on the original array. When the user changes the selection, the handler assigns event.target.selectedIndex to Data and passes that same DOM index in the ON_CHANGE event.
The source therefore combines an original-array lookup with a filtered-list selection index. When all entries are strings, those positions align. When filtering removes an earlier entry, they do not.

A three-element fixture exposes the mismatch
Consider an upstream value containing ["Alpha", 7, "Beta"]. The rendered options are Alpha and Beta. Beta occupies original position 2 but displayed position 1.
Selecting Beta produces a DOM selectedIndex of 1. The handler writes 1 to Data. A subsequent original-array lookup at index 1 yields the number 7, rather than Beta. The resulting select rendering may depend on how React and the browser handle a controlled value without a matching option, so a specific visible fallback is not claimed here.
The useful observation is earlier: the stored index already changed meaning at the boundary. Log the original array, the rendered captions and the assigned index, instead of diagnosing the outcome solely from which caption remains on screen.
This mixed-type fixture may need a dynamic or deliberately instrumented input path. If the project's type checks prevent it from reaching the widget, that prevention is a successful boundary, not a reason to weaken the type declaration. The source path matters when external or dynamically typed data can supply an array at runtime.
Normalize before binding the widget
Produce one canonical all-string options array before assigning it to the widget. Any parallel application data should be derived from the same filtering decision. Filtering captions while keeping an unfiltered parallel array merely moves the mismatch into the application.
For example, start with records containing an identifier and a caption. Validate the caption type, construct the accepted record list, then derive the widget captions from that accepted list. Interpret the selected index against the accepted records, not against the original unfiltered response.
Converting every non-string to text is an alternative only if those values are genuinely intended choices. Turning the number 7 into "7" changes the product's option set. It is not automatically the right repair for malformed data.
The important invariant is that the displayed list and the list used to interpret Data have the same membership and order. Keep that invariant at one explicit adapter boundary rather than recreating several slightly different filters.
Check the normalized path separately
Repeat the proposed fixture using ["Alpha", "Beta"] and select each option. The expected alignment is straightforward: Beta's displayed index and canonical-array index are both 1. Also verify that an input rejected as malformed does not silently replace a valid current list with an unintended empty choice set.
No browser interaction or EEZ runtime experiment was performed for this article. The mismatch is derived from the pinned render and change-handler code. Recheck those two paths after an upgrade: a future implementation might normalize once or maintain an explicit index mapping, changing the diagnosis without changing the application's visible design.