【问题标题】:Vaadin Flow: Navigation broken(?) when using SplitLayout and @ParentLayoutVaadin Flow:使用 SplitLayout 和 @ParentLayout 时导航损坏(?)
【发布时间】:2019-01-31 15:43:16
【问题描述】:

[EDIT] 问题末尾的解决方案[/EDIT]

上下文

我目前很难实现基于SplitLayout 的Component,如下所示:

这个想法是,带有class="outer"(突出显示的行)的布局将成为当用户选择Grid 中的一行时应该加载的内容的占位符。

"outer"-Layout 被添加到网格旁边的SplitLayout,因此标有slot='secondary'。

另一个类用@Route(value = "details", layout = OuterLayout.class)引用'outer'-Layout

通过单击Grid 的条目,页面导航到"grid/details"。


问题:

我希望 Vaadin 将带注释的类的内容放在 'outer'-Layout 中,但它在它旁边添加了一个新条目: 如果我删除第一个 'outer'-Layout Vaadin 将第二个标记为 slot='secondary' 并显示其内容: 它甚至会根据当前选择的 Gridentry 进行更新...


来源:

拆分布局

@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);
    }
}

外层

@ParentLayout(MySplitLayout.class)
public class MyDetailOuterLayout extends FlexLayout implements RouterLayout{

    public MyDetailOuterLayout() {
        setClassName("outer");
    }
}

内层

@Route(value = "grid/details", layout = MyDetailOuterLayout.class)
public class MyDetailLayout extends FlexLayout 
        implements HasUrlParameter<Integer>, BeforeEnterObserver
{
    public MonitorDetailLayout() {
        setClassName("inner");

        /* define data via URL*/
    }
}

我误解了生命周期的概念吗?

提前谢谢你


解决方案

按照 Tatu Lund 的建议,我修改了 RouterLayout 的默认实现,如下所示:

@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()));
        }
    }

}

【问题讨论】:

    标签: navigation vaadin vaadin-flow vaadin12


    【解决方案1】:

    RouterLayout 在您遇到的情况下使用的想法是,您需要覆盖 showRouterLayoutContent(..) 方法。发生导航时,会调用此方法,并将导航到的内容放入布局中。因此,在您的情况下,我假设您需要一个包含 Grid 的路由目标。

    所以模式是这样的,例如在你的主布局中,你需要有内容持有者,这里是 Div,但它可以是任何东西(比如 SplitLayout,或者其他任何东西)

    public class MainLayout extends VerticalLayout implements RouterLayout {
       private Div childWrapper = new Div();
    
       @Override
       public void showRouterLayoutContent(HasElement content) {
           childWrapper.getElement().appendChild(content.getElement());
       }
    }
    

    另外注意,如果你使用@Route(value="..", layout = ParentLayout.class)注解,你不应该和@ParentLayout(ParentLayout.class)一起使用。您只需将@ParentLayout 用于非路由目标的类。

    这里有更多信息:https://vaadin.com/docs/v12/flow/routing/tutorial-router-layout.html 和这里:https://vaadin.com/tutorials/nested-layouts-in-flow

    【讨论】:

    • 非常感谢。我将解决方案添加到问题的末尾。
    • 顺便说一句,如果我省略 MySplitLayout 上的 @ParentLayout 注释,如果我导航到 "grid/details" 并删除 ContentLayout 及其父元素,它将成为根元素。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-12
    • 2018-10-07
    • 2013-10-31
    • 2011-09-17
    相关资源
    最近更新 更多