Show TOC

Displaying the Complete Menu TreeLocate this document in the navigation structure

The SAPUI5 shell control allows you to add tool popups to its left border.

For more information on the SAPUI5 shell control, see the control documentation for the SAPUI5 demo kit (Start of the navigation path UX3 Controls Next navigation step Shell End of the navigation path).

You can add such a tool popup to your shell to display a tree representing the user's complete menu. We recommend to make the popup modal and react on its “open” event to lazily create the tree's content.

Shell.view.xml
<Shell>
  <toolPopups>
    <ToolPopup icon="..."
      iconHover="..."
      id="navigationToolPopup"
      modal="true"
      open="onNavigationToolPopupOpen"
      title="{i18n>navigation}">
    </ToolPopup>
  </toolPopups>
</Shell>

In order to structure the content of the popup, you can use a view. You should pass the user object (sap.ui2.shell.getUser()) to it, as it is initially a stub and the menu cannot be accessed immediately. This gives your shell the chance to asynchronously load the user object, so it will be available in time for the user to open the tool popup.

In order to get informed about selection changes, you need to pass a callback to the view. This allows you to keep the menu item selection in the shell in sync with the one in the tree.


Shell.controller.js
   /**
     * Initialization.
     */
    onInit: function () {
      this.oUser = sap.ui2.shell.getUser();
      this.oNavigationView = sap.ui.view({
        type: "XML",
        viewData: {
          selected: function (oNode) {
            // ...
            this.getView().byId("navigationToolPopup").close();
          },
          user: this.oUser // only Menu is needed, but User is still a stub!
        },
        viewName: "...Navigation"
      });
      this.getView().byId("navigationToolPopup").addContent(this.oNavigationView);
      this.oUser.load(...);
    },

    /**
     * Event handler for the navigation tool popup's "open" event.
     */
    onNavigationToolPopupOpen: function () {
      this.oNavigationView.getController().onOpen();
    },

In the navigation tree, we recommend using a tree control. You may want to remove its header (showHeader="false"). Wrap the menu's folders and applications into the tree nodes as shown in the example below:

Navigation.controller.js

    /**
     * Wraps the given menu entries as tree nodes and adds those to the given parent.
     *
     * @param {sap.ui.commons.Tree|sap.ui.commons.TreeNode} vParent
     *   either a tree or a tree node
     * @param {sap.ui2.shell.Node[]} aEntries
     *   a list of menu entries
     */
    buildTree: function (vParent, aEntries) {
      var oEntry,
        oTreeNode,
        i,
        n;

      for (i = 0, n = aEntries.length; i < n; i += 1) {
        oEntry = aEntries[i];
        oTreeNode = new sap.ui.commons.TreeNode({
          expanded: false,
          hasExpander: oEntry.isFolder(),
          selected: this.onTreeNodeSelected.bind(this, oEntry),
          text: oEntry.getText()
        });
        vParent.addNode(oTreeNode);
        this.oTreeNodeById.put(oEntry.getId(), oTreeNode);
        if (this.oInitiallySelectedNode === oEntry) {
          selectTreeNode(oTreeNode);
        }

        if (oEntry.isFolder()) {
          this.buildTree(oTreeNode, oEntry.getChildren());
        }
      }
    },

    /**
     * Initialization.
     */
    onInit: function () {
      this.oInitiallySelectedNode = null; // because selection happens already before opening
      this.oTreeNodeById = new sap.ui2.srvc.Map();
    },

    /**
     * Called by the embedding tool popup whenever it opens.
     */
    onOpen: function () {
      var aEntries = this.getView().getViewData().user.getMenu().getEntries(),
        oTree = this.getView().getContent()[0];

      if (oTree.getNodes().length === 0) {
        // lazily build tree
        this.buildTree(oTree, aEntries);
      }
    },

    /**
     * Event handler for any tree node's "selected" event.
     *
     * @param {sap.ui2.shell.Node} oEntry
     * @param {sap.ui.base.Event} oControlEvent
     */
    onTreeNodeSelected: function (oEntry, oControlEvent) {
      this.getView().getViewData().selected(oEntry);
    },

    /**
     * Selects the menu entry represented by the given node.
     *
     * @param {sap.ui2.shell.Node} oNode
     */
    selectNode: function (oNode) {
      var oTreeNode = this.oTreeNodeById.get(oNode.getId());
      if (oTreeNode) {
        selectTreeNode(oTreeNode);
      } else {
        this.oInitiallySelectedNode = oNode;
      }
    }

In the example above, some details have been omitted, for example selecting a tree node with oTreeNode.select(true).

The example illustrates how you can use a node's ID to uniquely identify it, for example in hash maps. You may want to use the same ID in the URL to keep state in the URL. Node objects are passed between the shell view and the navigation view to identify the current selection.