[EDIT] Solution at the end of the question [/EDIT]
I currently struggle to implement a Component
which is based on the SplitLayout
that looks like this:
The idea was that the layout with the class="outer"
(the highlighted line) would be a placeholder for content that was supposed to be loaded when the user selects a line in the Grid
.
The "outer"-Layout
was added to to SplitLayout
alongside the grid and is therefore marked with slot='secondary'
.
Another class references the 'outer'-Layout
with @Route(value = "details", layout = OuterLayout.class)
By clicking on an entry of the Grid
the page navigates to "grid/details"
.
I expected Vaadin to place the contents of the annotated class within the 'outer'-Layout
but instead it adds a new entry next to it:
If I remove the first 'outer'-Layout
Vaadin tags the second one as slot='secondary'
and its content appears:
Its even updating according the currently selected Gridentry...
Splitlayout
@Route(value = "grid", layout = ContentLayout.class)
@ParentLayout(ContentLayout.class)
public class MySplitLayout extends SplitLayout implements RouterLayout {
private MyGrid grid;
private MyDetailOuterLayout detailOuterLayout;
public MySplitLayout() {
setSizeFull();
grid = new MyGrid();
detailOuterLayout = new MyDetailOuterLayout();
addToPrimary(grid);
addToSecondary(detailOuterLayout);
}
}
Outer
@ParentLayout(MySplitLayout.class)
public class MyDetailOuterLayout extends FlexLayout implements RouterLayout{
public MyDetailOuterLayout() {
setClassName("outer");
}
}
Inner
@Route(value = "grid/details", layout = MyDetailOuterLayout.class)
public class MyDetailLayout extends FlexLayout
implements HasUrlParameter<Integer>, BeforeEnterObserver
{
public MonitorDetailLayout() {
setClassName("inner");
/* define data via URL*/
}
}
Did I misunderstand the lifecycle concept?
Thank you in advance
As suggested by Tatu Lund I modified the default implementation of RouterLayout
like this:
@Route(value = "grid", layout = ContentLayout.class)
@ParentLayout(ContentLayout.class)
public class MySplitLayout extends SplitLayout implements RouterLayout {
private MyGrid grid;
private MyDetailOuterLayout detailOuterLayout;
public MySplitLayout() {
setSizeFull();
grid = new MyGrid();
detailOuterLayout = new MyDetailOuterLayout();
addToPrimary(grid);
addToSecondary(detailOuterLayout);
}
@Override
public void showRouterLayoutContent(HasElement content) {
if (content != null) {
Element rootElement = getElement();
rootElement.removeChild(detailOuterLayout.getElement()); // aka the secondary Element
rootElement.appendChild(Objects.requireNonNull(content.getElement()));
}
}
}
The idea with RouterLayout
use in cases like you have is that, you need to override showRouterLayoutContent(..)
method. When navigation happens, this method is called and it does place the content where you navigated to, into the layout. So in your case I assume you need a route target, which wraps the Grid.
So pattern is like this, e.g. in your main layout you need to have the content holder, here it is Div, but it can be anything (like SplitLayout, or what ever)
public class MainLayout extends VerticalLayout implements RouterLayout {
private Div childWrapper = new Div();
@Override
public void showRouterLayoutContent(HasElement content) {
childWrapper.getElement().appendChild(content.getElement());
}
}
Also note, if you are using @Route(value="..", layout = ParentLayout.class)
annotation, you should not use @ParentLayout(ParentLayout.class)
together with it. You need to use @ParentLayout
only for classes, that are not Route targets.
There is some more information here: https://vaadin.com/docs/v12/flow/routing/tutorial-router-layout.html and here: https://vaadin.com/tutorials/nested-layouts-in-flow