Skip to content

[Toolbar]: querySelector fails with '#' selector when using non-Toolbar item elements #12855

@Na1k

Description

@Na1k

Describe the bug

After upgrading to the most recent version (2.17.x), using non-ToolbarItem elements (e.g. regular HTML elements or framework components) inside Toolbar causes a JS error:

Uncaught (in promise) SyntaxError: Failed to execute 'querySelector' on 'DocumentFragment': '#' is not a valid selector.

Important note: I have multiple runtimes of UI5 in my app, due to a micro frontend architecture. Scoping is implemented.

I am aware that only Toolbar components should be used as children. However, please note that in v1 you were able to use any component and this did not break until now. It would require loads of effort to refactor this everywhere and I would loose some needed functionality.
So I am asking to still consider this as an issue and provide a small fix.

Isolated Example

No response

Reproduction steps

This is the stack trace, it should provide all the necessary information to get an idea of the issue:

Uncaught (in promise) SyntaxError: Failed to execute 'querySelector' on 'DocumentFragment': '#' is not a valid selector.
    at DocumentFragment.querySelector (<anonymous>:15:19)
    at Toolbar.getItemWidth (Toolbar.js:348:1) // <-- This one
    at Toolbar.js:170:1
    at Array.reduce (<anonymous>)
    at Toolbar.onInvalidation (Toolbar.js:170:1)
    at Toolbar._invalidate (UI5Element.js:74:1)
    at Toolbar._onChildChange (UI5Element.js:448:1)
    at EventProvider.js:44:1
    at Array.map (<anonymous>)
    at EventProvider.fireEvent (EventProvider.js:43:1)

The marked line of code:

const renderedItem = this.shadowRoot.querySelector(`#${item.slot}`);

item.slot is undefined leading to the described error

Expected Behaviour

There should not be a JS error in the described case.

Proposed Fix in ui5-webcomponents:

Use item._individualSlot instead of item.slot:

current: const renderedItem = this.shadowRoot!.querySelector<HTMLElement>(`#${item.slot}`);
updated: const renderedItem = this.shadowRoot!.querySelector<HTMLElement>(`#${item._individualSlot}`);

The _individualSlot property is set by the framework on all slotted children and matches the id used in ToolbarTemplate.tsx

Alternatively, check if item.slot is undefined before the query.

Screenshots or Videos

No response

UI5 Web Components for React Version

2.17

UI5 Web Components Version

2.17

Browser

Chrome

Operating System

MacOS

Additional Context

No response

Relevant log output

Organization

No response

Declaration

  • I’m not disclosing any internal or sensitive information.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    Projects

    Status

    Issues

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions