fix(native-filters): persist created/pasted default values in select filter#40984
fix(native-filters): persist created/pasted default values in select filter#40984yousoph wants to merge 2 commits into
Conversation
Three bugs prevented default values typed/pasted into a creatable native filter from being stored and rendered correctly: 1. Paste tokenization did not trim whitespace, so "10107, 10121" split into ["10107", " 10121"] — the leading space caused label mismatch and stored wrong option values. 2. The options useMemo in SelectFilterPlugin guarded new-option injection with !multiSelect, so typed search terms never appeared as selectable options in multi-select mode. Also fixed the mutation bug (unshift on a memoized array). 3. uniqueOptions excluded values from filterState.value that are not in the dataset (i.e., user-created values). Added them back when creatable !== false so the Select can display them correctly. Adds a test for the whitespace-trimming fix.
The options useMemo was missing the `creatable !== false` check after the multi-select guard was removed, allowing new option entries to appear in the dropdown even when creatable=false. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
| if (search && creatable !== false && !hasOption(search, uniqueOptions, true)) { | ||
| return [{ label: search, value: search, isNewOption: true }, ...uniqueOptions]; | ||
| } |
There was a problem hiding this comment.
Suggestion: The new-option injection condition does not check searchAllOptions, so a "create new" option is still shown when remote search mode disables creation (allowNewOptions={!searchAllOptions && creatable !== false}). In that mode users can pick a synthetic value that should not be creatable, causing inconsistent filter state and incorrect queries. Add the same !searchAllOptions guard here so option creation behavior matches the Select props. [incorrect condition logic]
Severity Level: Major ⚠️
- ⚠️ Remote-search value filters still allow synthetic created options.
- ⚠️ Dashboards may apply filters on non-existent, user-typed values.Steps of Reproduction ✅
1. In the native filter configuration UI implemented by `FiltersConfigForm.tsx` (see
`controlsOrder` including `'creatable'` and `'searchAllOptions'` at
`superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/FiltersConfigForm.tsx:149-154`),
create a `filter_select` filter, leave `creatable` at its default `true`, and enable
`searchAllOptions` so that remote search is active.
2. Load a dashboard with this filter, which renders the `PluginFilterSelect` component
(`superset-frontend/src/filters/components/Select/SelectFilterPlugin.tsx:119-151`) and
passes `formData.searchAllOptions` and `formData.creatable` into the component; note that
the Select control is configured with `allowNewOptions={!searchAllOptions && creatable !==
false}` at lines 600-605, disabling built-in new-option creation when `searchAllOptions`
is true.
3. Type a value into the filter's search box that is not present in the current option
list while `searchAllOptions` remains true; `onSearch` at lines 265-279 updates the local
`search` state and, because `searchAllOptions` is true, dispatches `ownState.search` for
remote querying, but regardless of remote results the component's local `search` variable
now contains the typed text.
4. Because `options` is computed at lines 339-344 without checking `searchAllOptions`
(only `search && creatable !== false && !hasOption(search, uniqueOptions, true)`), the
typed term is injected as `{ label: search, value: search, isNewOption: true }` even when
`searchAllOptions` is true; the `Select` at lines 600-633 receives this synthetic option
in its `options` prop despite `allowNewOptions` being false, so the user can select a
"created" value in a mode where creation should be disabled, leading to inconsistent
filter state and queries built via `updateDataMask` at lines 216-245 containing that
synthetic value.Fix in Cursor | Fix in VSCode Claude
(Use Cmd/Ctrl + Click for best experience)
Prompt for AI Agent 🤖
This is a comment left during a code review.
**Path:** superset-frontend/src/filters/components/Select/SelectFilterPlugin.tsx
**Line:** 340:342
**Comment:**
*Incorrect Condition Logic: The new-option injection condition does not check `searchAllOptions`, so a "create new" option is still shown when remote search mode disables creation (`allowNewOptions={!searchAllOptions && creatable !== false}`). In that mode users can pick a synthetic value that should not be creatable, causing inconsistent filter state and incorrect queries. Add the same `!searchAllOptions` guard here so option creation behavior matches the Select props.
Validate the correctness of the flagged issue. If correct, How can I resolve this? If you propose a fix, implement it and please make it concise.
Once fix is implemented, also check other comments on the same PR, and ask user if the user wants to fix the rest of the comments as well. if said yes, then fetch all the comments validate the correctness and implement a minimal fix
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #40984 +/- ##
==========================================
- Coverage 64.30% 64.30% -0.01%
==========================================
Files 2657 2657
Lines 144060 144070 +10
Branches 33216 33219 +3
==========================================
+ Hits 92641 92647 +6
- Misses 49797 49801 +4
Partials 1622 1622
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
Code Review Agent Run #5cfb3b
Actionable Suggestions - 1
-
superset-frontend/packages/superset-ui-core/src/components/Select/Select.tsx - 1
- Paste handling inconsistency · Line 693-695
Filtered by Review Rules
Bito filtered these suggestions based on rules created automatically for your feedback. Manage rules.
-
superset-frontend/src/filters/components/Select/SelectFilterPlugin.tsx - 1
- CWE-710: Missing Hook Dependency · Line 344-344
Review Details
-
Files reviewed - 3 · Commit Range:
9667ae5..f03ff98- superset-frontend/packages/superset-ui-core/src/components/Select/Select.test.tsx
- superset-frontend/packages/superset-ui-core/src/components/Select/Select.tsx
- superset-frontend/src/filters/components/Select/SelectFilterPlugin.tsx
-
Files skipped - 0
-
Tools
- Whispers (Secret Scanner) - ✔︎ Successful
- Detect-secrets (Secret Scanner) - ✔︎ Successful
Bito Usage Guide
Commands
Type the following command in the pull request comment and save the comment.
-
/review- Manually triggers a full AI review. -
/pause- Pauses automatic reviews on this pull request. -
/resume- Resumes automatic reviews. -
/resolve- Marks all Bito-posted review comments as resolved. -
/abort- Cancels all in-progress reviews.
Refer to the documentation for additional commands.
Configuration
This repository uses Superset You can customize the agent settings here or contact your Bito workspace admin at evan@preset.io.
Documentation & Help
| const array = token | ||
| ? uniq(pastedText.split(token).map(s => s.trim()).filter(Boolean)) | ||
| : [pastedText.trim()].filter(Boolean); |
There was a problem hiding this comment.
The paste handler in Select.tsx now trims whitespace and filters empty strings from token-separated values, but AsyncSelect.tsx (line 673) retains the original unprocessed split logic. This inconsistency means users pasting identical text into these two components receive different tokenization results. Align AsyncSelect.tsx with the corrected behavior in Select.tsx.
Code Review Run #5cfb3b
Should Bito avoid suggestions like this for future reviews? (Manage Rules)
- Yes, avoid them
Summary
Fixes three compounding bugs that prevented native filter default values from persisting when typed or pasted (rather than selected from the dropdown) in a creatable multi-select filter.
Bug: A Value (
filter_select) native filter with Allow creation of new values enabled silently dropped default values that were typed or pasted. The chips appeared in the config modal but after clicking Save the filter rendered empty on the dashboard, and reopening the config showed no default value.Fix 1 —
Select.tsx: trim whitespace from pasted tokens (primary fix)"10107, 10121".split(",")previously produced["10107", " 10121"]— the leading space caused label-match failure against the existing option{value: 10107, label: "10107"}, resulting in the value being stored as a new string literal" 10121"rather than the correct matched option value.Fix 2 —
SelectFilterPlugin.tsx: multi-select typed values in options (secondary fix)!multiSelectguard prevented typed search terms from appearing as selectable new options in multi-select filters. Also fixed a mutation bug whereunshiftwas called on the memoizeduniqueOptionsarray.Fix 3 —
SelectFilterPlugin.tsx: include created values inuniqueOptions(tertiary fix)uniqueOptionswas built only from DB data. WhenfilterState.valuecontained created values not in the dataset, they were absent fromoptionsand relied on the Select component's internalfullSelectOptionsfallback which could lose them across re-renders.Test plan
order_numbercolumn — paste10107, 10121, 10134, 10145, 10159, 10168, 10180, 10188, 10201, 10211as default value, Save, verify filter chips appear on dashboardjest Select.test.tsx— new test'trims whitespace from pasted comma-separated values'should pass🤖 Generated with Claude Code