How to collapse all other SideNav menus when one is expanded

I have a left navigation area composed of several SideNav components. When one is expanded I want to automatically close all other expanded SideNav menus.

I can’t find a way to do this. there is no click/expand listener on the SideNav component.

Is there a way to achieve this?

You can listen with Element#addPropertyChangeListener to changes of a property. In this case expanded.
This worked for me with client sided click and a server sided SideNavItem#setExpanded.

I created the addItem method to not have duplicated code.

    private SideNav sideNav = new SideNav("Side Nav");

    /* flow skeleton starter */
    public MainView() {
        addClassName("centered-content");

        // create items
        SideNavItem messagesLink = new SideNavItem("Messages", MainView.class, VaadinIcon.ENVELOPE.create());
        messagesLink.addItem(new SideNavItem("Inbox", MainView.class, VaadinIcon.INBOX.create()));
        messagesLink.addItem(new SideNavItem("Sent", MainView.class, VaadinIcon.PAPERPLANE.create()));
        messagesLink.addItem(new SideNavItem("Trash", MainView.class, VaadinIcon.TRASH.create()));
        SideNavItem adminSection = new SideNavItem("Admin");
        adminSection.setPrefixComponent(VaadinIcon.COG.create());
        adminSection.addItem(new SideNavItem("Users", MainView.class, VaadinIcon.GROUP.create()));
        adminSection.addItem(new SideNavItem("Permissions", MainView.class, VaadinIcon.KEY.create()));
        SideNavItem testSection = new SideNavItem("Test");
        testSection.setPrefixComponent(VaadinIcon.COG.create());
        testSection.addItem(new SideNavItem("Test", MainView.class, VaadinIcon.GROUP.create()));
        testSection.addItem(new SideNavItem("Test", MainView.class, VaadinIcon.KEY.create()));

        addItem(messagesLink, adminSection, testSection);
        add(sideNav);
        add(new Button("Expand last item", e -> testSection.setExpanded(true)));
    }

    /**
     * add to nav bar and add listener
     */
    private void addItem(SideNavItem... items) {
        for (SideNavItem item : items) {
            // listen to expanded changed on client
            item.getElement().addPropertyChangeListener("expanded", this::collapseItems);
            sideNav.addItem(item);
        }
    }

    /**
     * handle change
     */
    private void collapseItems(PropertyChangeEvent event) {
        final Element currentlyChangedItem = event.getSource();
        Object newPropValue = event.getValue();
        // collapse only if opened
        if (Boolean.TRUE.equals(newPropValue)) {
            sideNav.getChildren().filter(item -> {
                // do not collapse item that triggered event
                return !item.getElement().equals(currentlyChangedItem) && item instanceof SideNavItem;
            }).forEach(item -> ((SideNavItem) item).setExpanded(false));
            ;
        }
    }
1 Like