2013-08-11 1 views
2

Итак, я сделал директиву для переключения (выпадающего) меню в AngularJS. Я использовал директиву для нескольких элементов на странице, но у меня есть небольшая проблема. Когда один элемент открыт, и я нажимаю другой, я хочу, чтобы предыдущий был закрыт. Event.preventDefault и event.stopPropagation останавливает событие для предыдущего элемента и не закрывает его. Есть какие нибудь идеи как это починить? Есть ли способ, возможно, остановить событие только в пределах области?Меню переключателя угловогоJS, предотвращающее по умолчанию для другой директивы

app.directive('toggleMenu', function ($document) { 
    return { 
     restrict: 'CA', 
     link: function (scope, element, attrs) { 
      var opened = false; 
      var button = (attrs.menuButton ? angular.element(document.getElementById(attrs.menuButton)) : element.parent()); 
      var closeButton = (attrs.closeButton ? angular.element(document.getElementById(attrs.closeButton)) : false); 

      var toggleMenu = function(){ 
       (opened ? element.fadeOut('fast') : element.fadeIn('fast')); 
      }; 

      button.bind('click', function(event){ 
       event.preventDefault(); 
       event.stopPropagation(); 
       toggleMenu(); 
       opened = ! opened; 
      }); 

      element.bind('click', function(event){ 
       if(attrs.stayOpen && event.target != closeButton[0]){ 
        event.preventDefault(); 
        event.stopPropagation(); 
       } 
      }); 

      $document.bind('click', function(){ 
       if(opened){ 
        toggleMenu(); 
        opened = false; 
       } 
      }); 


     } 
    }; 

И вот Fiddle: http://jsfiddle.net/JknUJ/5/ Кнопка открывает содержание и содержание должно закрываться при нажатии вне дел. При нажатии кнопки 2 содержимое 1 не закрывается.

+0

У нас есть любые [скрипки] (http://jsfiddle.net), [plunks] (http://plnkr.co/) или [pens] (http://codepen.io/)? – madhead

+0

Да добавил скрипку! –

ответ

2

Основная идея заключается в том, что вам нужно разделить состояние между всеми раскрывающимися подменю, поэтому, когда один из них отображается, все остальные скрыты. Самый простой способ сохранения состояния (например, открытого или закрытого) - это ... классы CSS!

Мы создадим пару директив - один для меню, а другой для sumbenu. Более выразительно, что только div s.

Здесь нет разметки.

<menu> 
    <submenu data-caption="Button 1"> 
    Content 1 
    </submenu> 
    <submenu data-caption="Button 2"> 
    Content 2 
    </submenu> 
</menu> 

Посмотрите, насколько это понятно! Скажем, благодаря директивам:

plunker.directive("menu", function(){ 
    return { 
     restrict : "E", 
     scope : {}, 
     transclude : true, 
     replace : true, 
     template : "<div class='menu' data-ng-transclude></div>", 
     controller : function ($scope, $element, $attrs, $transclude){ 
      $scope.submenus = []; 

      this.addSubmenu = function (submenu) { 
       $scope.submenus.push(submenu); 
      } 

      this.closeAllSubmenus = function (doNotTouch){ 
       angular.forEach($scope.submenus, function(submenu){ 
        if(submenu != doNotTouch){ 
         submenu.close();  
        } 
       }) 
      } 
     } 
    } 
}); 

plunker.directive("submenu", function(){ 
    return { 
     restrict : "E", 
     require : "^menu", 
     scope : { 
      caption : "@" 
     }, 
     transclude : true, 
     replace : true, 
     template : "<div class='submenu'><label>{{caption}}</label><div class='submenu-content' data-ng-transclude></div></div>", 
     link : function ($scope, $iElement, $iAttrs, menuController) { 
      menuController.addSubmenu($scope); 

      $iElement.bind("click", function(event){ 
       menuController.closeAllSubmenus($scope); 
       $iElement.toggleClass("active"); 
      }); 

      $scope.close = function(){ 
       $iElement.removeClass("active"); 
      } 
     } 
    } 
}); 

Посмотрите Тары мы ограничили их HTML элементов (restrict : "E"). submenu требует вставки в menu (require : "^menu"), это позволяет нам вводить контроллер меню в функцию связи submenu. transclude и replace управляет положением исходной разметки в скомпилированном HTML-выходе (replace=true означает, что исходная разметка будет заменена скомпилированной, transclude вставляет части исходной разметки в скомпилированный вывод).

Когда мы закончили с этим, мы просто скажем в меню закройте все ваши детские меню! и меню выполняет итерацию по подменю, заставляя их закрываться.

Мы добавляем детей к контроллеру menu в addSubmenu функции. Он вызывается в функции связи submenu, поэтому каждый скомпилированный экземпляр подменю добавляет себя к menu. Теперь закрыть все submenus так же просто, как итерация над всеми детьми, это делается closeAllSubmenus в контроллере menu.

Here является полным плунжером для игры.

+1

Большое спасибо, например, и ясное объяснение! –

Смежные вопросы