Vaadin 10 Dialog emulating Vaadin 8 Window Caption

Using Vaadin Flow Java API I would like to emulate a Vaadin 8 Window feature: particularly I need to emulate Caption property. I mean a fixed top “Title” not scrollable as the real content of the Dialog.

This is the workaround I found.

public MainView() {
    Button button = new Button("Click me",
            event -> {
                Dialog dialog = new Dialog();
                HorizontalLayout horizontalLayout = new HorizontalLayout();
                VerticalLayout verticalLayout = new VerticalLayout();
                Div headerDiv = new Div();
                Div bodyDiv = new Div();
                bodyDiv.getElement().getStyle().set("overflow", "auto");
                bodyDiv.getElement().getStyle().set("max-height", "420px"); // !!!
                dialog.add(headerDiv, bodyDiv);
                headerDiv.add(horizontalLayout);
                bodyDiv.add(verticalLayout);
                horizontalLayout.add(new Label("Hi there !"));
                for (int i = 1; i <= 20; i++) {
                    verticalLayout.add(new TextField("TextField_" + i));                        
                }
                dialog.open();                  
            });
    add(button);
}

The trouble is that I have to fix max-height size to avoid scrolling of all the contained components. So I cannot take advantage from the auto-size behaviour of the Dialog Container. Also tried using setFlexGrow, but I did not reach the solution.

Anyone can tell me some example I could learn from ? Thanks in advance

I think you are going right direction, but your solution can be simplified.

  1. You can remove the horizontalLayout and add the title text directly to headerDiv. I would prefer Text, Span or Html component instead of Label for the title text.
  2. Instead of Div you could use VerticalLayout directly as body. Or alternatively place components directly to bodyDiv. Div is a layout component, the simplest one. Then you could use body.getElement().getStyle().set("overflow", "auto"); to get scrolling to body, and probably max-height is not needed.

First of all thanks for your reply.
But … No way out. If I have right understood what you mean.
Following my unsuccessful tests.
Without max-height setting all the components scroll together inside the Dialog.

import com.vaadin.flow.component.Text;
import com.vaadin.flow.component.button.Button;
import com.vaadin.flow.component.dialog.Dialog;
import com.vaadin.flow.component.html.Div;
import com.vaadin.flow.component.html.Label;
import com.vaadin.flow.component.orderedlayout.HorizontalLayout;
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
import com.vaadin.flow.component.textfield.TextField;
import com.vaadin.flow.router.Route;

@Route("")
public class MainView extends VerticalLayout {
    public MainView() {

    	// My original Code
    	Button button0 = new Button("Test 0",
                event -> {
                    Dialog dialog = new Dialog();
                    HorizontalLayout horizontalLayout = new HorizontalLayout();
                    VerticalLayout verticalLayout = new VerticalLayout();
                    Div headerDiv = new Div();
                    Div bodyDiv = new Div();
                    bodyDiv.getElement().getStyle().set("overflow", "auto");
                    bodyDiv.getElement().getStyle().set("max-height", "420px"); // !!!
                    dialog.add(headerDiv, bodyDiv);
                    headerDiv.add(horizontalLayout);
                    bodyDiv.add(verticalLayout);
                    horizontalLayout.add(new Label("Hi there !"));
                    for (int i = 1; i <= 20; i++) {
                        verticalLayout.add(new TextField("TextField_" + i));                        
                    }
                    dialog.open();          	
                });
        add(button0);

        // First simplification
        Button button1 = new Button("Test 1",
                event -> {
                	Dialog dialog = new Dialog();
            		VerticalLayout verticalLayout = new VerticalLayout();
                	Div headerDiv = new Div();
            		verticalLayout.getStyle().set("overflow", "auto");
            		dialog.add(headerDiv, verticalLayout);
            		headerDiv.add(new Text("Hi there !!"));
            		for (int i = 1; i <= 20; i++) {
						verticalLayout.add(new TextField("TextField_" + i));						
					}
                	dialog.open();                	
                });
        add(button1);
        
        // Second simplification
        Button button2 = new Button("Test 2",
                event -> {
                	Dialog dialog = new Dialog();
                	Div headerDiv = new Div();
                	Div bodyDiv = new Div();
            		bodyDiv.getElement().getStyle().set("overflow", "auto");
//            		bodyDiv.getElement().getStyle().set("max-height", "420px");
            		dialog.add(headerDiv, bodyDiv);
            		headerDiv.add(new Text("Hi there !!"));
            		for (int i = 1; i <= 20; i++) {
						bodyDiv.add(new TextField("TextField_" + i));						
					}
                	dialog.open();                   	
                });
        add(button2);
        
    }
}

Ok, now I understand, the overlay element of the Dialog has “overflow: auto” set by default, hence the scroll bar appears there instead of body Div

https://github.com/vaadin/vaadin-overlay/blob/master/src/vaadin-overlay.html#L62

You need to add in your global styles.html module a themable mixin of this kind to change it

   <dom-module theme-for="vaadin-dialog-overlay" id="my-dialog">
      <template>
         <style>
            :host(.my-dialog) [part="overlay"]
{
               overflow:initial
            }
         </style>
      </template>
   </dom-module>

Sorry Tatu, maybe there is some other setting to do …
Attached what I get adding your code to my style.html
Already tried using “overflow:hidden” and getting similar troubles …
Thanks anyway
17366515.png

I had the same issue. I found a solution with a “hack”. I have add a comment about, in the code below.

/**
 * @author Panos Bariamis (pbaris)
 */
@CssImport(value = "./mytheme/mytheme-dialog.css", themeFor = "vaadin-dialog-overlay")
public class MyDialog extends Composite<Dialog> {

    private final Dialog dialog;

    private Div body;

    public MyDialog() {
        dialog = getContent();
        dialog.getElement().getThemeList().add("mytheme-dialog-overlay");

        VerticalLayout vl = new VerticalLayout();
        vl.getStyle().set("background-color", "#f0f0fe");
        vl.setPadding(false);
        vl.setMargin(false);
        vl.add(new Span("title"));
        vl.add(new Span("buttons"));
        dialog.add(vl);
        dialog.add(getBody());
		
		/*
		Vaadin Dialog use a div as a container to add components. 
		This div is not accessible, and i didn't find a way to add style through the css file.
		The only way i managed to do it is through this "hack".
		*/
        Style style = dialog.getElement().getNode()
            .getFeature(VirtualChildrenList.class)
            .get(0)
            .getFeature(ElementStylePropertyMap.class)
            .getStyle();
        style.set("display", "flex");
        style.set("flex-direction", "column");
        style.set("height", "100%");
    }

    private Component getBody() {
        if (body == null) {
            body = new Div();
            body.getElement().getStyle().set("overflow", "auto");
            body.getElement().getStyle().set("padding-right", "var(--lumo-space-m)");
            body.add(new Div(new Span("aaaaaaaaaaaaaaaaaaaas")));
            for(int i=0; i<=100; i++) {
                body.add(new Div(new Span("ssss " + i)));
            }
        }
        return body;
    }

    public void open() {
        dialog.open();
    }

    public void close() {
        dialog.close();
    }
}

The content of the imported mytheme-dialog.css is

:host([theme~="mytheme-dialog-overlay"]
) [part="overlay"]
 {
	overflow:initial!important;
	height:100%
}

:host([theme~="mytheme-dialog-overlay"]
) [part="content"]
 {
	padding:0!important;
	height:100%;
}

and the result is in the attachment
17817766.png