Search code examples
javavaadinvaadin-flowvaadin14

Change NavBar content in AppLayout dynamically when navigation occurs


I would like to dynamically add buttons in the AppLayout NavBar section when navigating to a view. I'm using RouterLink links in the drawer (wrapped in tabs) i.e. the view object is not instantiated prior to the navigation event. Is there a standard way to achieving this in Vaadin 14+?

Ideally the view navigated to would be able to inspect its parent (the layout) and access the navBar to add/remove components from it.

Here is how the AppLayout looks:

MainLayout.java

public class MainLayout extends AppLayout implements BeforeEnterObserver, TrackerConfigurator {

    private Map<Tab, Component> tabSet = new HashMap<>();
    
    public MainLayout() {
        FlexLayout navBarLayout = new FlexLayout(leftNavBarLayout, navBarContentContainer, rightNavBarLayout);
        navBarLayout.setWidthFull();
        navBarLayout.setJustifyContentMode(FlexComponent.JustifyContentMode.BETWEEN);
        navBarLayout.setAlignItems(FlexComponent.Alignment.CENTER);
        addToNavbar(navBarLayout);
            
        // Tabs
        TabWithIdentifier page0 = tabForPageWithRouter("Dashboard", new IronIcon("icomoon", "icons"), DashboardView.class);
        TabWithIdentifier page1 = tabForPageWithRouter("Users", new IronIcon("icomoon", "users2"), UserView.class);
        ...
            
        final Tabs tabs = new Tabs(page0, page1, ...);
        tabs.setOrientation(Tabs.Orientation.VERTICAL);
            
        addToDrawer(tabs);
    }
    
    private TabWithIdentifier tabForPageWithRouter(String title, IronIcon icon, Class classType)   {
        icon.setSize("1.3em");
        icon.getStyle().set("margin-right", "10px");

        RouterLink routerLink = new RouterLink(null, classType);
        routerLink.add(icon);
        routerLink.add(title);

        TabWithIdentifier tab = new TabWithIdentifier(routerLink);
        tab.setId(title);
        tab.setIdentifier(title);
        tab.addClassName("drawer-tab");

        return tab;
    }

Solution

  • Resolved this case by overriding showRouterLayoutContent(HasElement content) and creating a base view class which provides a Div container for any components I want to add to the navbar.

    @Override
    public void showRouterLayoutContent(HasElement content) {
    
        super.showRouterLayoutContent(content);
    
        BaseView baseView = null;
    
        if (content instanceof BaseView) {
            baseView = (BaseView) content;
    
            pageTitle = new Label(baseView.getViewTitle());
    
            controlContainer.removeAll();
            controlContainer.add(baseView.getViewIconTray());
        }
    
        fireEvent(new RouterNavigated(this));
    }