How to use BrowserWindowOpener together with ButtonRenderer in a Grid

Hi,

I have a Grid with a ButtonRenderer column:

ButtonRenderer<MyBean> renderer = new ButtonRenderer<>(event -> buttonClicked(event.getItem()));

The clicked item should be opened (immediately) in a new browser window.
So I tried to combine the ButtonRenderer with a BrowserWindowOpener.
Because a BrowserWindowOpener can’t extend a ButtonRenderer directly, I tried to use an invisible Button:

Button popItUp = new Button("Pop It Up");
    
private void buttonClicked(MyBean item) {
    System.out.println("Clicked on item " + item.getId());
    BrowserWindowOpener opener = new BrowserWindowOpener(MyPopupUI.class);
    opener.setParameter("id", item.getId());
    opener.extend(popItUp);
    popItUp.click();  // <- does not work!?
}

But the new window does not show up.
I have to make the Button visible AND click it manually.

Any ideas?
Thanks

You will need a custom Renderer (or a component Column) for that. You can probably mimic the relevant code from BrowserWindowOpener. An invisible Button probably won’t work, because popup blockers in browsers like to prevent opening of new windows unless it’s happening as a direct consequence of a user interaction (click).

-Olli

In Grid Renderers Collection Add-On’s Vaadin 8 version 2.2.7 there is now BrowserOpenRenderer


https://vaadin.com/directory/component/grid-renderers-collection-for-vaadin7

Cool!
Although it’s not exactly what I’m looking for.
I want to open another UI (see my code snippet) which is not possible with a BrowserOpenRenderer, or?

I want to open another UI (see my code snippet) which is not possible with a BrowserOpenRenderer, or?

Yes, the use case is different there. In your case is the UI to be opened the same on each row?

Yes. I want to show details about the selected row/item on a new UI. Therefore I set the parameter “id”.

When I was creating the add-on, I was thinking also about following idea: given UI as parameter for the renderer and using URI fragment string in the cell opening the window. That sounded like next natural improvement step and which would be generic enough to be in public add-on.

That would be the most flexible solution!

Check version 2.2.8 of the add-on, the feature is now added there.

I checked it out, but got this error on the browser console:

com.vaadin.DefaultWidgetSet-0.js:6157 Fri Feb 09 16:06:27 GMT+100 2018 com.vaadin.client.WidgetSet
SEVERE: Widgetset 'com.vaadin.DefaultWidgetSet' does not contain an implementation for org.vaadin.grid.cellrenderers.action.BrowserOpenerRenderer. Check the connector's @Connect mapping, the widgetset's GWT module description file and re-compile your widgetset. In case you have downloaded a vaadin add-on package, you might want to refer to <a href='http://vaadin.com/using-addons'>add-on instructions</a>.

Do I really have to re-compile any widgetsets?
I tried it according to
https://vaadin.com/docs/framework/clientside/clientside-compiling.html
, but nothing was compiled.
BTW:
http://vaadin.com/using-addons
gets a 440
I am using
vaadin-bom:8.2.0
and
vaadin-spring-boot-starter
in my POM

Do I really have to re-compile any widgetsets?

Yes.

Today I had some time for testing.
There are three issues:

  • BrowserOpenRenderer tries to open the PopupUI with URL /popup which leads to a 404, where a BrowserWindowOpener uses
    /vaadinServlet
    /popup which is o.k.
  • The URL fragment should be #1, #2 or #3, depending of the row that is clicked, but the fragment is always #3 !
  • I cannot access the fragment in PopupUI#init, can I? As I wrote: I want to show details about the selected row/item on the PopupUI.
@SpringBootApplication
public class VaadinSpringBootAddonExampleApplication {
    public static void main(String args) {
        SpringApplication.run(VaadinSpringBootAddonExampleApplication.class, args);
    }
}
@SpringUI(path = "")
@Theme("valo")
class MyUI extends UI {
    @Override
    public void init(VaadinRequest vaadinRequest) {
        BrowserOpenerRenderer<MyBean> renderer = new BrowserOpenerRenderer<>(PopupUI.class, "Pop Up", cl -> {});
        Grid<MyBean> grid = new Grid<>();
        grid.addColumn(e -> "" + e.id, renderer);
        grid.addColumn(MyBean::getId).setCaption("Id");
        grid.addColumn(MyBean::getData).setCaption("Data");
        grid.setItems(Arrays.asList(new MyBean(1, "foo"), new MyBean(2, "bar"), new MyBean(3, "zoo")));

        Button popItUp = new Button("Pop Up", c -> {});
        BrowserWindowOpener opener = new BrowserWindowOpener(PopupUI.class);
        opener.extend(popItUp);

        setContent(new VerticalLayout(grid, popItUp));
    }
    public static class PopupUI extends UI {
        @Override
        protected void init(VaadinRequest request) {
            setContent(new Label("I just popped up to say hi!"));
        }
    }
    @Data @AllArgsConstructor //Lomkok
    static class MyBean { int id; String data; }
}

Thanks for your time testing this, it is very valuable.

The URL fragment should be #1, #2 or #3, depending of the row that is clicked, but the fragment is always #3 !

This is clear bug, and I found the reason. I had a bit wrong thought process in one place there. I am testing a fix now.

Edit: The fix is in version 2.2.10

I cannot access the fragment in PopupUI#init, can I? As I wrote: I want to show details about the selected row/item on the PopupUI.

Yes you can, use getPage().getUriFragment().

Great! The URL fragment part is working now!
Do you have any hint about the different popup URLs?

Do you have any hint about the different popup URLs?

I updated the demo app to use this feature, but I did not encounter that issue, so I really do not have idea at the moment.

I think the reason is that your plugin assumes, that the Vaadin Servlet is always mapped to /*

vaadin-spring-boot uses a different URL:

com.vaadin.spring.boot.internal.VaadinServletConfiguration#DEFAULT_SERVLET_URL_BASE = "/vaadinServlet";

Quote: “the Vaadin servlet is not at context root to allow DispatcherServlet to work”

BrowserWindowOpener takes this URL mapping into account, when creating the URL for the PopupUI.