Set Width of "Dialog" Widget to a Percentage of The Page in Vaadin 14

Set width of Dialog widget to a percentage of the page in Vaadin 14

How can I get a Dialog to fill most but not all of the browser window, and be dynamic resized as the user grows/shrinks the window's width/height?

By setting width/height to overlay part of the vaadin-dialog-overlay using CSS.

A longer version


The behavior you see is a consequence of style being applied to the div inside a flow-component-renderer, not the overlay part as one would expect. The relevant tickets are:

  • setWidth and setHeight either not working, or are wrongly documented
  • Add a note that 'setWidth' sets a width to a 'flow-component-renderer', not an overlay/dialog itself

If you inspect the dialog having fixed width in DevTools, you will notice that the dialog itself is actually wider.

The correct (I mean it is correct, but not expected) way would be to style an overlay part of the dialog via css using:

[part="overlay"]{
width:80%;
}

and

@CssImport(
value= "./styles/dialogOverlay.css",
themeFor = "vaadin-dialog-overlay"
)

After that, the width is taking 80% as expected. I hope the screenshot above illustrates the issue better:

Sample Image


How to correctly specify dialog size in vaadin-flow

Fixed the problem by using Lumo theme instead of Material one.

How to layout a Dialog component in vaadin?

You do the layout of the dialog in the same manner that you would do the layout of any other component: you use the appropriate layout component, with whatever nested components and layouts give you the desired look. The styling of the dialog is done the same way as any other component.

Vaadin 14 dialog with tabs

Would something like this work?

@Route("dialogs-tabs")
public class DialogContainerTabs extends VerticalLayout {
public DialogContainerTabs(){
Dialog dialog=new Dialog();

Tab tab1 = new Tab("Tab one");
Div page1 = new Div();
page1.setText("Page#1");

Tab tab2 = new Tab("Tab two");
Div page2 = new Div();
page2.setText("Page#2");
page2.setVisible(false);

Tab tab3 = new Tab("Tab three");
Div page3 = new Div();
page3.setText("Page#3");
page3.setVisible(false);

Map<Integer, Component> tabsToPages = new HashMap<>();
tabsToPages.put(0, page1);
tabsToPages.put(1, page2);
tabsToPages.put(2, page3);
Tabs tabs = new Tabs(tab1, tab2, tab3);
Div pages = new Div(page1, page2, page3);
Set<Component> pagesShown = Stream.of(page1)
.collect(Collectors.toSet());

tabs.addSelectedChangeListener(event -> {
pagesShown.forEach(page -> page.setVisible(false));
pagesShown.clear();
Component selectedPage = tabsToPages.get(tabs.getSelectedIndex());
selectedPage.setVisible(true);
pagesShown.add(selectedPage);
});

Button back=new Button();
back.setIcon(VaadinIcon.ARROW_BACKWARD.create());
dialog.add(back);
back.addClickListener(e->{
if(tabs.getSelectedIndex()>0){
pagesShown.forEach(page -> page.setVisible(false));
pagesShown.clear();
tabs.setSelectedIndex(tabs.getSelectedIndex()-1);
Component selectedPage = tabsToPages.get(tabs.getSelectedIndex());
selectedPage.setVisible(true);
pagesShown.add(selectedPage);
}
else{
//Do what you want, maybe navigate to the last one? or NOOP
}
});

Button forward=new Button();
forward.setIcon(VaadinIcon.ARROW_FORWARD.create());
dialog.add(forward);
forward.addClickListener(e->{
if(tabs.getSelectedIndex()<tabsToPages.size()-1){
pagesShown.forEach(page -> page.setVisible(false));
pagesShown.clear();
tabs.setSelectedIndex(tabs.getSelectedIndex()+1);
Component selectedPage = tabsToPages.get(tabs.getSelectedIndex());
selectedPage.setVisible(true);
pagesShown.add(selectedPage);
}
else{
//Do what you want, maybe navigate to the first one one? or NOOP
}
});

dialog.add(tabs);
dialog.add(pages);
dialog.setOpened(true);
add(dialog);
}

}

I have buttons on top of tabs, but you could put them inside the view, if you want so, of course.
In Vaadin 14, tabs doesn't hold components, so once you have switched a tab, you should manually set previous component to hidden and the new one to visible

The result dialog looks like this:
Sample Image

And tabs code is taken directly from here : Tabs : Java Examples

P.S.
It's just a POC and this might not be exactly 1:1 with what you want, but you could get an idea from here, how to follow :) And this code should be refactored to not re-use the same logic three times (in tabs listener and back/forward buttons)

Horizontally centering a popup window in Vaadin

Solution 1: Use SizeReporter

Indeed, setPositionY() will reset the window's centered property to false. As the width of your pop-up and that of your browser window are not know before they appear on the screen, the only way I know to get those values is to use the SizeReporter add-on. Its use is quite straightforward:

public class MyUI extends UI {

private Window popUp;

private SizeReporter popUpSizeReporter;
private SizeReporter windowSizeReporter;

@Override
protected void init(VaadinRequest request) {

Button button = new Button("Content button");
VerticalLayout layout = new VerticalLayout(button);
layout.setMargin(true);

popUp = new Window("Pop-up", layout);
popUp.setPositionY(40);

addWindow(popUp);

popUpSizeReporter = new SizeReporter(popUp);
popUpSizeReporter.addResizeListenerOnce(this::centerPopUp);

windowSizeReporter = new SizeReporter(this);
windowSizeReporter.addResizeListenerOnce(this::centerPopUp);
}

private void centerPopUp(ComponentResizeEvent event) {

int popUpWidth = popUpSizeReporter.getWidth();
int windowWidth = windowSizeReporter.getWidth();

if (popUpWidth == -1 || windowWidth == -1) {
return;
}

popUp.setPositionX((windowWidth - popUpWidth) / 2);
}
}

This piece of code will be okay as long as you don't resize the pop-up. If you do, it will not be automatically recentered. If you replace addResizeListenerOnce() by addResizeListener() then it will automatically recenter the pop-up but you'll get some "UI glitches" as the add-on sends resize events almost continually while you're resizing your pop-up...

You could try to do it using CSS, but I personally avoid CSS as much as I can with Vaadin :).

You'll need to recompile the widgetset after you've added the add-on as a dependency.

Solution 2: Use com.vaadin.ui.JavaScript

I won't vouch for the portability of this solution but I guess it will work on most modern browsers.

public class MyUI extends UI {

private Window popUp;

@Override
protected void init(VaadinRequest request) {

Button button = new Button("Content button");
VerticalLayout layout = new VerticalLayout(button);
layout.setMargin(true);

popUp = new Window("Pop-up", layout);
popUp.setPositionY(40);
popUp.addStyleName("window-center");

addWindow(popUp);

// Add a JS function that can be called from the client.
JavaScript.getCurrent().addFunction("centerWindow", args -> {
popUp.setPositionX((int) ((args.getNumber(1) - args.getNumber(0)) / 2));
});

// Execute the function now. In real code you might want to execute the function just after the window is displayed, probably in your enter() method.
JavaScript.getCurrent().execute("centerWindow(document.getElementsByClassName('window-center')[0].offsetWidth, window.innerWidth)");
}
}


Related Topics



Leave a reply



Submit