6
<md-menu-bar>
  <md-menu ng-repeat="section in sections">
    <md-button class="navButton" ng-click="$mdOpenMenu()">
      {{section.name}}
    </md-button>
    <md-menu-content>
      <md-menu-item>
        <md-button>Subsection 1</md-button>
      </md-menu-item>
    </md-menu-content>
  </md-menu>
</md-menu-bar>

I am doing something like above but unfortunately, if I click a menu, it stays open even if I click other buttons.

I just want it to have the same behaviour as

https://material.angularjs.org/latest/demo/menuBar

P.S. If I don't use ng-repeat (meaning, menus are static), it works fine though.

Problem Codepen

Pankaj Parkar
  • 134,766
  • 23
  • 234
  • 299
Rey Libutan
  • 5,226
  • 9
  • 42
  • 73
  • Directive ng-repeat creates a separate scope, that's why (most likely) your example works. One possibility is to use controllerAs syntax and assigning your method onto real directive controller scope, not angular $scope. You'd then access in your method opening new menu as ctrlName.methodName(); It would be easier if you created a fiddle – Maciej Gurban Oct 19 '15 at 17:41
  • Pankaj created a codepen. Thank you very much! @Maciej, Please see edited question. – Rey Libutan Oct 20 '15 at 01:03

3 Answers3

4

I just bumped into this question and noticed that the link posted by S.Klechkovski has a workaround made by christrude. It's not perfect (as other users pointed out) but at least it works. Might as well post it here.

You have to include the $mdMenu service in your controller and invoke its hide method when you click to open the menu.

$scope.closeOthers = function() {
  $mdMenu.hide(null, { closeAll: true });
}

and in the HTML

<button ng-click="closeOthers();$mdOpenMenu()">File</button>

Here's an edited Codepen. I hope it helps.

EDIT

The best solution is patching the component itself. Even with the disadvantages with the workaround found in Github (that I replicated here) it's still the best one.

However here's an alternative just for exploration purposes ;) This little frankenstein uses promises to only open the next menu when all the animations are done.

Markup

<button ng-click="closeOthers().then($mdOpenMenu);">File</button>

Controller

var lock = false;

$scope.closeOthers = function() {
  if(lock) {
    return;
  }

  var defer = $q.defer()
  lock = true;

  $mdMenu.hide(null, { closeAll: true }).then(function() {
    lock = false;
    defer.resolve();
  });

  return defer.promise;
}
Ricardo Velhote
  • 4,630
  • 1
  • 24
  • 30
  • Unfortunately, this is not a complete working solution although it is good enough in some cases. The issue with this solution is that when you try menu1->menu2->menu1 again, the `md-content` will be not be displayed because as it is opening, it was still hit by the `.hide()` – Rey Libutan Oct 23 '15 at 09:05
  • @ReyLibutan I made an edit but I still think the other one is the best you'll get without fixing the component (either waiting for official fix, or running a patched component which may be undesirable for you). – Ricardo Velhote Oct 23 '15 at 10:47
2

Good question! It seems that is known bug which is not yet fixed. I have added a comment with your example and some elaboration of the problem on the existing issue. Let's hope that it will be fixed soon.

Comment:

Here is an example Codepen that illustrates the reported issue.

After some research I noticed that it happens because md-menu directives use $scope.$emit for triggering the $mdMenuOpen event on which listen all md-menu instances. $emit triggers listeners on all parent scopes including the one on which the event is emitted. That means if all md-menu instances are on the same scope everything is fine but that is not the case with ng-repeat which creates new scope for each child.

S.Klechkovski
  • 4,005
  • 16
  • 27
0

The only reliable workaround I found was

$scope.forceCloseMenu = function () {
    $('.md-open-menu-container').hide();
    $('.md-menu-backdrop').remove();
    $('.md-scroll-mask').remove();
};

And calling forceCloseMenu() every time a menu item was clicked.

Note this requires jQuery also.

Oliver Jonas
  • 1,188
  • 14
  • 12