Search code examples
javavaadin10vaadin-flow

How insert view (child) into div of parent layout? Vaadin 10 / Flow


I have a component implementing RouterLayout like this:

@Tag("side-menu")
@HtmlImport(value = "src/components/side-menu.html")
public class SideMenu extends PolymerTemplate<TemplateModel> implements RouterLayout {

    @Id("menu")
    private PaperListBox listBox = new PaperListBox();

    public SideMenu() {

        listBox.addMenu(new PaperItem("tutorial", TutorialView.class));
        listBox.addMenu(new PaperItem("icons", IconsView.class));

    }
}

I route a view child of the parent layout

@Route(value=IconsView.VIEW_ROUTE, layout = SideMenu.class)
public class IconsView extends Div {

    public static final String VIEW_ROUTE = "icons";

    public IconsView() {
        add(new Label("ICONS VIEW"));
    }

}

But the result overwrote all the content of side-menu.html file.

side-menu.html template base format

<side-menu>
    <div>App Name</div>
    <div id="menu"></div>
    <div id=contenido><!-- I want to show here my view Icons --></div>
</side-menu>

But the result it's

<side-menu>
    <div>
       <label>ICONOS VIEW</label>
    </div>
</side-menu>

The expected result is:

<side-menu>
    <div>App Name</div>
    <div id="menu"></div>
    <div id=contenido>
       <div>
          <label>ICONOS VIEW</label>
        </div>
    </div>
</side-menu>

Solution

  • In vaadin documentation said this:

    You can add child components to templates using the Component or Element API, but because PolymerTemplate uses the shadow DOM the shadow tree is rendered instead of the elements children that are in the light DOM.

    This means that the template needs to have a <slot></slot> to mark the place where the light DOM elements should be rendered.

    I found a solution for this composite layout:

    I only needed to be modified my template side-menu.html and add a <slot> tag like this:

    <side-menu>
        <div>App Name</div>
        <div id="menu"></div>
        <slot></slot>
    </side-menu>
    

    And then when my view is loaded, it's rendered into the <slot> tag into the template