vaadin-component-factory / tooltip

Java API for vcf-tooltip
https://incubator.app.fi/tooltip-demo/tooltip
Apache License 2.0
3 stars 2 forks source link

Tooltip in Vaadin 19 is not working #16

Open jcgueriaud1 opened 3 years ago

jcgueriaud1 commented 3 years ago

This code is working in Vaadin 14 but not in Vaadin 19 (the tooltip does not pop):


@Route("hello")
public class HelloView extends HorizontalLayout {

    private TextField name;
    private Button sayHello;

    public HelloView() {
        addClassName("hello-world-flow-view");
        name = new TextField("Your name");
        sayHello = new Button("Say hello");
        setVerticalComponentAlignment(Alignment.END, name, sayHello);
        sayHello.addClickListener(e -> {
            Notification.show("Hello " + name.getValue());
        });
        Tooltip tooltip = new Tooltip();

        tooltip.attachToComponent(sayHello);

        tooltip.setPosition(TooltipPosition.RIGHT);
        tooltip.setAlignment(TooltipAlignment.LEFT);

        tooltip.add(new H5("Hello"));
        tooltip.add(new Paragraph("This is an example of how to use it"));
        // Tooltip should be added to layout as well
        add(name, sayHello);
        add(tooltip);
    }
}
theshoeshiner commented 3 years ago

I can report that tooltip is having issues in v18 as well. The demo works fine, but when used inside a real application, e.g. inside the AppLayout, the tooltips only appear if the page is navigated to after the initial page load. A subsequent full page refresh will again break the tooltips since it causes a full UI rebuild. My best guess is that there is an issue with how the tooltips are attached to components.

theshoeshiner commented 3 years ago

A very nasty workaround, if you have no other choice, is to attach the tooltips from a background thread and push them to the UI. e.g. in a spring boot app using an AsynTaskExecutor.

It is necessary to put the Thread to sleep for a short time because otherwise the UI access may happen on the current vaadin UI thread. This is also why calling attachToComponentfrom an AttachListener does not work because it will still get called from the initial UI thread,

@Autowired
AsyncTaskExecutor executor;
...
UI ui = UI.getCurrent();
Span ind = new Span("Tooltip");
add(ind);
Tooltip tt = new Tooltip();
tt.setPosition(TooltipPosition.TOP);
tt.add(new Span("This is the tip"));
add(tt);

executor.execute(() -> {
    ThreadUtils.sleepSafe(500);
    ui.access(() -> {
                // This runs on a background thread and is pushed to UI after the page is loaded
        tt.attachToComponent(ind);
    });
});
Sam-k-Elliott commented 2 years ago

I can confirm that this issue still persists in Vaadin 21.0.2 for an initial page reload, navigation (even back to the landing page) does resolve the issue. Thank you @theshoeshiner for the workaround! Though I had to increase the thread sleep somewhat in case others are having issues with the workaround.

Sam-k-Elliott commented 2 years ago

We were facing some issues with the delay in the above workaround not being properly timed in different environments of ours. We ended up using an alternative workaround after speaking with Vaadin support some that does not make use of sleep but rather alters how the tooltip is attached in the constructor:

tooltip.element.node.runWhenAttached { ui: UI ->
            ui.page.executeJs(
                "requestAnimationFrame(function() {$0.targetElement = $1; }.bind(this))",
                tooltip.element, icon.element
            )
        }

the above is Kotlin code but the general gist is to execute the JS that is being executed in Tooltip.java::attachToComponent but put it in requestAnimationFrame(function() { ... }.bind(this)

A little more consistent and a bit cleaner if others are looking for a workaround to this issue.

norbertroamsys commented 2 years ago

Are there any plans for updating this really useful component to newer Vaadin versions? We are using the latest version 1.3.7 together with Vaadin 22.0.3. This works for almost all simple use cases.

But we discovered a really ugly dependency problem: When using npm referencing this component ends up in an unresolved dependency problem: The front end does no longer work and the following error is reported:

NotSupportedError: CustomElementRegistry.define: 'vaadin-lumo-styles' has already been defined as a custom element

A look into the generated package-lock.json shows the problem:

"node_modules/@vaadin-component-factory/vcf-tooltip": {
      "version": "1.3.15",
      "resolved": "https://registry.npmjs.org/@vaadin-component-factory/vcf-tooltip/-/vcf-tooltip-1.3.15.tgz",
      "integrity": "sha512-/kwEj0v7YdkU3R9Rs3oHsy8ajBnjLCNwqmqeWZi/qYVWg0GOmzTENfMVC0kBxnkd9pu3x/+dS9WEcj8gvmPwVQ==",
      "dependencies": {
        "@polymer/polymer": "^3.2.0",
        "@vaadin/vaadin-element-mixin": "^2.1.3",
        "@vaadin/vaadin-license-checker": "^2.1.2",
        "@vaadin/vaadin-lumo-styles": "^1.5.0",
        "@vaadin/vaadin-themable-mixin": "^1.5.1"
      }
    },   

A 1.* version of vaadin-lumo-styles is referenced but 22.0.3 has already been resolved and referenced before!

By using pnpn (vaadin.pnpm.enable = true) we are able to "solve" the problem: pnpm "avoids" this version clash and uses the latest version. Snippet from pnpm-lock.yaml:

/@vaadin-component-factory/vcf-tooltip/1.3.15:
    dependencies:
      '@polymer/polymer': 3.2.0
      '@vaadin/vaadin-element-mixin': 2.4.2
      '@vaadin/vaadin-license-checker': 2.1.2
      '@vaadin/vaadin-lumo-styles': 22.0.3
      '@vaadin/vaadin-themable-mixin': 22.0.3
    dev: false

But this can only be called a workaround and the reported rendering problems in this issue may be part of this broken dependency?!

jcgueriaud1 commented 2 years ago

Vaadin 23 will require node 16.14.0 or newer: https://github.com/vaadin/flow/issues/12995

This will solve dependency issue that is solved with pnpm: https://github.com/vaadin/flow/pull/12635

So normally in Vaadin 23 it should be solved with pnpm and npm. You can already try Vaadin 23 beta and npm 8.3