vaadin / flow

Vaadin Flow is a Java framework binding Vaadin web components to Java. This is part of Vaadin 10+.
Apache License 2.0
589 stars 164 forks source link

UI.getCurrent().getComponent() in WebComponent returns body-Element #19133

Open contradictioned opened 2 months ago

contradictioned commented 2 months ago

Description of the bug

When I embed a Vaadin application as WebComponent, I get the following:

The UI class level documentation says:

There is one UI for every Vaadin instance in a browser window. A UI may either represent an entire browser window (or tab) or some part of a html page where a Vaadin application is embedded.

The UI::getElement documentation says:

Gets the element for this UI. The UI element corresponds to the tag on the page

This is a problem, when developing an application that can be standalone and embedded at the same time. A standalone app typically can do whatever it wants with the body-element. The embedded component is expected to be a "polite guest" on the hosting page, and e.g., do not add styles to the body element but only to and below.

When developing a webcomponent-only app, UI.getCurrent().getElement() seems useless.. what should I do with it? It's in the territory of the host page. Also consider having more Vaadin-Webcomponents on the same page: their UI-objects represent the different parts where the apps are embedded, but these parts cannot be accessed as one can only access the body.

Expected behavior

UI.getCurrent().getElement() should return a representation of the web-component DOM-element that belongs to that UI. This way, developers can use UI.getCurrent().getElement() to access a top level element for the current application instance without thinking about if this might be interfer with some host-application.

Minimal reproducible example

Call UI.getCurrent().getElement().executeJs("console.warn(this)")in Vaadin-Application exported as web-component.

Versions

Legioth commented 2 months ago

Could you give some examples of the kind of operation that you would want to do for the root of the DOM structure when running as a regular UI and for the web component root when running as an embedded web component?

mshabarov commented 2 months ago

I think this have to be changed to return the element that corresponds to the embedded Vaadin app, or at least documented.

Legioth commented 2 months ago

I lean towards just updating documentation unless we discover some specific use case that would really necessitate a change. The reason for this is that I suspect I suspect there's lots of code out there that is already making assumptions based on how it has worked so far.

contradictioned commented 2 months ago

Could you give some examples of the kind of operation that you would want to do for the root of the DOM structure when running as a regular UI and for the web component root when running as an embedded web component?

Two things already present in the codebase: We set styles (especially custom properties) programmatically that are valid for the entire app, thus we target the root. And we associate javascript functions with that element that are either of global nature (and thus could live in any div), or that react to size changes (and thus should logically reside on the root).

We can build around this by adding a "custom" root, but I think, at least updating the documentation would help, and in genereral having a way to access the root Element of a web component would make the Vaadin-embedding-story more complete.

Legioth commented 2 months ago

Those examples do indeed point towards a direction where the current UI.getElement() would remain as it is today and we should just supplement documentation to encourage considering whether it's the most appropriate target specifically with exported web components.

contradictioned commented 2 months ago

Another point, that I think is related to the root-component debate: Right now, when a window is attached to the UI, it is effectively placed as a child of UI.getCurrent().getComponent() (if my code browsing serves correct), similar, when form-overlays like the DatePicker's overlay or the Combobox' overlay opens, right now it is below <body>.

For the documentation, I think this sentence in the documentation threw me off most: "A UI may either represent an entire browser window (or tab) or some part of a html page where a Vaadin application is embedded." Because if getElement() does return more than this part (and also add(Component components...) adds to the body-element and not the WebComponent), then the object I get from UI.getCurrent() does only represent the entire page. I hope that makes sense ;)

knoobie commented 2 months ago

when form-overlays like the DatePicker's overlay or the Combobox' overlay opens, right now it is below <body>.

Related to: https://github.com/vaadin/web-components/issues/6325

contradictioned commented 1 month ago

Also related to https://github.com/vaadin/flow/issues/5330