fix: enable search in document select/multiselect editables by keeping label as string#3357
fix: enable search in document select/multiselect editables by keeping label as string#3357daniel-travix wants to merge 3 commits intopimcore:2025.4from
Conversation
|
CLA Assistant Lite bot All contributors have signed the CLA ✍️ ✅ |
0f0f10f to
975c981
Compare
|
I have read the CLA Document and I hereby sign the CLA |
|
Hi, Thanks a lot! |
The select editable rendered by pimcore_select with a store configuration shows a search box (showSearch + optionFilterProp="label"), but typing never narrows the options — every query returns zero matches. Root cause: transformDocumentEditableStoreToOptions wraps every label in <SanitizeHtml>, producing a React element. antd filters options by String(option.label), so for a React element the comparison becomes '[object Object]' and no user query ever matches. Fix: keep label as a plain string so the built-in filter works; move HTML sanitization to render time via a new renderSanitizedLabel helper, exported alongside the transform and wired into the SelectEditable via labelRender / optionRender. XSS protection is unchanged — the label is still wrapped in <SanitizeHtml> at every point it becomes DOM. The helper is exported (not defined locally in the component) so the adjacent MultiSelectEditable, which shares the same transform, can reuse it without duplication.
Follow-up to the previous commit. The multiselect editable uses the same transformDocumentEditableStoreToOptions as the single select, so after switching the transform to return plain strings, its labels would render unsanitized without explicit render props. Wire the shared renderSanitizedLabel helper into labelRender and optionRender, restoring XSS protection for the multi-select case while keeping the built-in search filter working (optionFilterProp="label" against a plain string).
bd3f052 to
7f457c9
Compare
5872002 to
7f457c9
Compare
|
|
Thanks @markus-moser! I hadn't noticed you already changed the base branch to 2025.4 yourself - my last force-pushes were me trying to clean up the local branch and re-target 2025.4 (hence the extra pipeline runs). All good now from my end, ready when you are. |
|
@daniel-travix Yes, looks good now - thanks a lot. Will check it and then merge it if everything is fine! |



Problem
pimcore_selectandpimcore_multiselectrender antdSelect/CreatableSelectwithshowSearch+optionFilterProp="label", but typing into the dropdown never narrows the options - every query returns zero matches.{{ pimcore_select('pick', { 'store': [['a', 'Apple'], ['b', 'Banana'], ['c', 'Cherry']] }) }}Open in the document editor, click the dropdown, type any character: list becomes empty.
Scope: document editables only (
SelectEditable,MultiSelectEditable). DataObject selects and grid cell selects are unaffected - they already keep the label as a string when there is no HTML.Root cause
transformDocumentEditableStoreToOptionswraps every label in<SanitizeHtml>:antd filters via
String(option.label).toLowerCase().includes(input). For a React element that is"[object Object]", so nothing ever matches. The transform is shared by both editables, so both are broken.Regression from #2031 (merged 2025-09-08), which introduced
<SanitizeHtml>inside the transform. No existing issue found.Fix
Keep
labelas a plain string, move sanitization to render time via a sharedrenderSanitizedLabelhelper, wire it into both consumers'labelRender/optionRender. Helper lives inutils/select-options.tsxnext to the transform, so there is one place for XSS logic.Applying render props to both editables is required: changing the transform alone would silently drop XSS protection from the multiselect, which used to rely on
<SanitizeHtml>being embedded in the label.Diff (trimmed)
utils/select-options.tsx:select-editable.tsxandmultiselect-editable.tsx:Screenshots
Test brick with four
pimcore_select/pimcore_multiselectinstances, typingfrin the multiselect:Before:

After:

Testing
Covered both transform branches (array-of-pairs and plain list) for both editables:
pimcore_selectwith[['at','Austria'], ...]and with['Apple','Banana',...]pimcore_multiselectwith[['at','Austria'], ...]and with['Apple','Banana',...]Before: all four return 0 hits on any input. After: all four filter correctly.
XSS check with
store: [['xss', '<b>X</b><script>alert(1)</script>']]:<b>renders bold,<script>dropped from DOM, no alert. Works for both editables.