7

The AbsoluteLayout in Vaadin 8 (Framework) enables pixel-position-oriented placement of widgets within a layout. While not my first layout of choice, the AbsoluteLayout is suited to porting code from other UI-building platforms that use pixel-position-oriented layout.

Example code from the manual:

// A 400x250 pixels size layout
AbsoluteLayout layout = new AbsoluteLayout();
layout.setWidth("400px");
layout.setHeight("250px");

// A component with coordinates for its top-left corner
TextField text = new TextField("Somewhere someplace");
layout.addComponent(text, "left: 50px; top: 50px;");

I can see that the passed argument is simply CSS coding. But I am no HTML/CSS wizard, that’s why I am using Java-based Vaadin in the first place.

The migration guide for moving from Vaadin 8 (Framework) to Vaadin 10 (Flow) says in this list of components that the AbsoluteLayout from 8 is not included in 10, nor do they plan to add it in the future. But that page does offer this note about replacement for AbsoluteLayout:

Very easy to achieve the same in V10 using e.g. Div

  • Can someone explain what this would mean in a Java-based Vaadin app? Perhaps an example?
  • How might a person conveniently and routinely do pixel-positioning of widgets in a Vaadin 10 Flow app?
Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154
  • Tip: For a list of Vaadin 8 components versus their Vaadin Flow counterparts, see [*Components in Vaadin 10*](https://vaadin.com/docs/v11/flow/migration/5-components.html) page in the manual. – Basil Bourque Oct 20 '18 at 21:54

2 Answers2

8

As your request for an "Hello World" example app, I downloaded the Project Starter with Spring Starter from https://vaadin.com/start and combined Tatu's solution with your example usage code. You can find it at https://github.com/Peppe/absolute-layout-demo.

You can test it live with the following commands in terminal / command line:

https://github.com/Peppe/absolute-layout-demo.git
cd absolute-layout-demo
mvn spring-boot:run

I created a class called AbsoluteLayout, with it's entirety looking like this:

public class AbsoluteLayout extends Div {

    public AbsoluteLayout() {
        getElement().getStyle().set("position", "relative");
    }

    public void add(Component component, int top, int left) {
        add(component);
        component.getElement().getStyle().set("position", "absolute");
        component.getElement().getStyle().set("top", top + "px");
        component.getElement().getStyle().set("left", left + "px");
    }
}

Only change that I did, compared to what Tatu said, was to give the position relative to the parent layout. This makes the position of the children added to the layout relative to the layout, and not the body (or parent position relative in the DOM structure). Otherwise the component would be in top:50px, left:50px from browser corner.

Then the usage class looks like this:

@HtmlImport("styles/shared-styles.html")
@Route
public class MainView extends VerticalLayout {

    public MainView() {
        setClassName("main-layout");

        //Just to add some content on the page to test relative position
        for (int i = 0; i<5; i++){
            add(new Div(new Text("Hello")));
        }

        // A 400x250 pixels size layout
        AbsoluteLayout layout = new AbsoluteLayout();
        layout.setWidth("400px");
        layout.setHeight("250px");

        // A component with coordinates for its top-left corner
        TextField text = new TextField("Somewhere someplace");
        layout.add(text, 50, 50);
        add(layout);
    }
}

I added a few lines of text before the layout to add some rows of text, just to test out the position:relative mentioned above.

Hope this helps and gets you on the right path. As you notice, this "AbsoluteLayout" doesn't have really any code to it - it is just a div. You can do this same trick with any layout in your app if you want to place one element into a relative position.

Jens Jansson
  • 4,626
  • 4
  • 25
  • 29
  • Setting both `top and bottom` or `left and right` means that the width or height has to change to compensate. If your element also has a set width or height, then the behavior might be a bit unexpected. – Jens Jansson Nov 11 '18 at 06:57
  • Since this is still valid for Vaadin 14 and only a single component, it could be presented in https://cookbook.vaadin.com/ Created an issue for it: https://github.com/vaadin/cookbook/issues/215 – eeq Oct 26 '21 at 11:51
4

The simplest way in Java-based Vaadin app is to use Div as the layout and add components there.

For each component you want to position you need to apply CSS styles, there is Java API for that, i.e. component.getElement().getStyle().

It could be something like

public void setPosition(Component component, int x, int y) {
   component.getElement().getStyle().set("position","absolute");
   component.getElement().getStyle().set("top",y+"px");
   component.getElement().getStyle().set("left",x+"px");
} 

Probably you want to extend Div and the above method (that makes rudimentary AbsoluteLayout)

See also https://developer.mozilla.org/en-US/docs/Web/CSS/position

Tatu Lund
  • 9,949
  • 1
  • 12
  • 26
  • 1
    Could you post a tiny-but-complete "Hello World" example app? – Basil Bourque Jul 06 '18 at 20:45
  • Do you know why the option to place or move a component with mouse in the canvas area is missing in the new version of Vaadin Designer ? It was very useful, specially when you don't want to mess with positioning EVERY component with CSS and just want a fixed position. – Diego Quirós Dec 26 '18 at 17:59
  • @DiegoQuirós I think the reason is the same as the original question. As there is no built in AbsoluteLayot in Vaadin 10+, Designer cannot rely on such. – Tatu Lund Dec 27 '18 at 07:19