指令中的子菜单不起作用

时间:2015-11-13 16:05:11

标签: javascript angularjs twitter-bootstrap

我有一个多层菜单,可以像硬编码的html一样正常工作。一旦我将子菜单片段移动到angularJs指令(nav-dropdown),它就不再正常工作,而是在我点击子菜单项时关闭父菜单。生成的HTML与一些AngularJS类和属性不同,除了AngularJS之外,其他所有内容都应该忽略。

请在此处查看plunkr:http://plnkr.co/edit/YknatvTulTC0FM2fXkSc?p=preview

注意" Dropdown"下的子菜单。行为正确(点击时打开子菜单)。 动态生成的所有其他子菜单都不起作用。

下拉html(有效):

<li class="dropdown open">
    <a tabindex="0" data-toggle="dropdown" data-submenu="" aria-expanded="true">
      Dropdown<span class="caret"></span>
    </a>

    <ul class="dropdown-menu">
      <li class="dropdown-submenu">
        <a tabindex="0">Action</a>

        <ul class="dropdown-menu">
          <li><a tabindex="0">Sub action</a></li>
          <li class="dropdown-submenu">
            <a tabindex="0">Another sub action</a>

            <ul class="dropdown-menu">
              <li><a tabindex="0">Sub action</a></li>
              <li><a tabindex="0">Another sub action</a></li>
              <li><a tabindex="0">Something else here</a></li>
            </ul>
          </li>
          <li><a tabindex="0">Something else here</a></li>
          <li class="dropdown-submenu">
            <a tabindex="0">Another action</a>

            <ul class="dropdown-menu">
              <li><a tabindex="0">Sub action</a></li>
              <li><a tabindex="0">Another sub action</a></li>
              <li><a tabindex="0">Something else here</a></li>
            </ul>
          </li>
        </ul>
      </li>

      <li class="dropdown-submenu">
        <a tabindex="0">Another action</a>

        <ul class="dropdown-menu">
          <li><a tabindex="0">Sub action</a></li>
          <li><a tabindex="0">Another sub action</a></li>
          <li><a tabindex="0">Something else here</a></li>
        </ul>
      </li>
      <li><a tabindex="0">Something else here</a></li>
      <li class="divider"></li>
      <li><a tabindex="0">Separated link</a></li>
    </ul>
</li>

angularjs指令的动态html(不起作用):

<li class="dropdown ng-scope ng-isolate-scope open" ng-repeat="department in vm.departments" department="department">
    <a tabindex="0" data-toggle="dropdown" data-submenu="" class="ng-binding ng-scope" aria-expanded="true">
      Apparel<span class="caret"></span>
    </a>

    <ul class="dropdown-menu ng-scope">
      <li class="dropdown-submenu">
        <a tabindex="0">Action</a>

        <ul class="dropdown-menu">
          <li><a tabindex="0">Sub action</a></li>
          <li class="dropdown-submenu">
            <a tabindex="0">Another sub action</a>

            <ul class="dropdown-menu">
              <li><a tabindex="0">Sub action</a></li>
              <li><a tabindex="0">Another sub action</a></li>
              <li><a tabindex="0">Something else here</a></li>
            </ul>
          </li>
          <li><a tabindex="0">Something else here</a></li>
          <li class="dropdown-submenu">
            <a tabindex="0">Another action</a>

            <ul class="dropdown-menu">
              <li><a tabindex="0">Sub action</a></li>
              <li><a tabindex="0">Another sub action</a></li>
              <li><a tabindex="0">Something else here</a></li>
            </ul>
          </li>
        </ul>
      </li>

      <li class="dropdown-submenu">
        <a tabindex="0">Another action</a>

        <ul class="dropdown-menu">
          <li><a tabindex="0">Sub action</a></li>
          <li><a tabindex="0">Another sub action</a></li>
          <li><a tabindex="0">Something else here</a></li>
        </ul>
      </li>
      <li><a tabindex="0">Something else here</a></li>
      <li class="divider"></li>
      <li><a tabindex="0">Separated link</a></li>
    </ul>
  </li>

这里是完整的javascript,你可以在plunkr上看到:

// Code goes here

angular.module('myApp', []);

angular.module('myApp').directive('dccNavigation', function (departmentService) {
    return {
        restrict: 'E',
        scope: {
            brandName: '@',
            brandImage: '@'
        },
        replace: true,
        templateUrl: 'navigation.html',
        controllerAs: 'vm',
        controller: function($scope, $timeout) {
          var vm = this;
          vm.departments = [];
          vm.brandName = $scope.brandName;
          vm.brandImage = $scope.brandImage;
          $('[data-submenu]').submenupicker();

          departmentService.getDepartments().then(function(success) {
            vm.departments = success.data.departments;
          });
        }
    }
});

angular.module('myApp').directive('dccNavDropdown', function ($compile) {
    return {
        restrict: 'E',
        scope: {
            department: '=department',
        },
        replace: true,
        templateUrl: 'nav-dropdown.html',
        controller: 'navDropdownController',
        controllerAs: 'vm',
        compile: function (el) {
            var contents = el.contents().remove();
            var compiled;
            return function(scope,el){
                if(!compiled)
                    compiled = $compile(contents);

                compiled(scope,function(clone){
                    el.append(clone);
                });
            };
        }
    }
});

angular.module('myApp').controller('navDropdownController', function($scope, departmentService){
      var vm = this;
      vm.department = $scope.department;
});

angular.module('myApp').factory('departmentService', function($q){
  var customNavElements = [];

  return {
      customNavElements: customNavElements,
      getDepartments: function() {
        var departments =[
          {"id":18245,"name":"Apparel","level":1,"itemCount":5,"children":[
            {"id":3509,"name":"Men","level":2,"itemCount":5,"children":[
              {"id":18112,"name":"Jackets","level":3,"itemCount":0,"children":[]},
                 {"id":18113,"name":"Polos","level":3,"itemCount":0,"children":[]},
                 {"id":18114,"name":"Sweatshirts","level":3,"itemCount":0,"children":[]},
                 {"id":18115,"name":"T-Shirts","level":3,"itemCount":0,"children":[]},
                 {"id":18499,"name":"View all","level":3,"itemCount":0,"children":[]}]},
              {"id":3510,"name":"Women","level":2,"itemCount":4,"children":
                [{"id":18116,"name":"Jackets","level":3,"itemCount":0,"children":[]},
                 {"id":18118,"name":"Sweatshirts","level":3,"itemCount":0,"children":[]},
                 {"id":18119,"name":"T-Shirts","level":3,"itemCount":0,"children":[]},
                 {"id":18500,"name":"View all","level":3,"itemCount":0,"children":[]}]},
              {"id":3513,"name":"Hats","level":2,"itemCount":0,"children":[]},
              {"id":5023,"name":"Kids","level":2,"itemCount":0,"children":[]},
              {"id":18468,"name":"View All","level":2,"itemCount":0,"children":[]}]},
            {"id":3514,"name":"Accessories","level":1,"itemCount":7,"children":[
              {"id":18120,"name":"Drinkware","level":2,"itemCount":0,"children":[]},
              {"id":18121,"name":"Bags","level":2,"itemCount":0,"children":[]},
              {"id":18122,"name":"Office","level":2,"itemCount":0,"children":[]},
              {"id":18124,"name":"High-end Tech Items","level":2,"itemCount":0,"children":[]},
              {"id":18123,"name":"Tradeshow/Giveaways","level":2,"itemCount":0,"children":[]},
              {"id":18226,"name":"Misc","level":2,"itemCount":0,"children":[]},
              {"id":18411,"name":"View All","level":2,"itemCount":0,"children":[]}]},
            {"id":14961,"name":"Monday Night Football","level":1,"itemCount":0,"children":[]},
            {"id":3515,"name":"Golf","level":1,"itemCount":3,"children":[
              {"id":18125,"name":"Apparel","level":2,"itemCount":0,"children":[]},
              {"id":18126,"name":"Accessories","level":2,"itemCount":0,"children":[]},
              {"id":18127,"name":"View All","level":2,"itemCount":0,"children":[]}]},
            {"id":18080,"name":"Shop by Price","level":1,"itemCount":4,"children":[
              {"id":18081,"name":"Under $5.00","level":2,"itemCount":0,"children":[]},
              {"id":18082,"name":"$5.00 - $10.00","level":2,"itemCount":0,"children":[]},
              {"id":18083,"name":"$10.01 - $25.00","level":2,"itemCount":0,"children":[]},
              {"id":18084,"name":"Over $25.00","level":2,"itemCount":0,"children":[]}]},
            {"id":3516,"name":"Sales","level":1,"itemCount":8,"children":[
              {"id":16927,"name":"Men","level":2,"itemCount":4,"children":[
                {"id":18128,"name":"Jacket","level":3,"itemCount":0,"children":[]},
                {"id":18129,"name":"Polos","level":3,"itemCount":0,"children":[]},
                {"id":18130,"name":"Sweatshirts","level":3,"itemCount":0,"children":[]},
                {"id":18131,"name":"T-Shirts","level":3,"itemCount":0,"children":[]}]},
              {"id":16928,"name":"Women","level":2,"itemCount":3,"children":[
                {"id":18132,"name":"Jackets","level":3,"itemCount":0,"children":[]},
                {"id":18134,"name":"Sweatshirts","level":3,"itemCount":0,"children":[]},
                {"id":18135,"name":"T-Shirts","level":3,"itemCount":0,"children":[]}]},
              {"id":16929,"name":"Kids","level":2,"itemCount":0,"children":[]},
                {"id":16930,"name":"Hats","level":2,"itemCount":0,"children":[]},
                {"id":16931,"name":"Accessories","level":2,"itemCount":5,"children":[
                  {"id":18136,"name":"Drinkware","level":3,"itemCount":0,"children":[]},
                  {"id":18137,"name":"Bags","level":3,"itemCount":0,"children":[]},
                  {"id":18138,"name":"Office","level":3,"itemCount":0,"children":[]},
                  {"id":18139,"name":"Tradeshow/Givaways","level":3,"itemCount":0,"children":[]},
                  {"id":18304,"name":"Misc","level":3,"itemCount":0,"children":[]}]},
                {"id":16932,"name":"Golf","level":2,"itemCount":3,"children":[
                  {"id":18141,"name":"Apparel","level":3,"itemCount":0,"children":[]},
                  {"id":18142,"name":"Accessories","level":3,"itemCount":0,"children":[]},
                  {"id":18143,"name":"View All","level":3,"itemCount":0,"children":[]}]},
                {"id":16933,"name":"Monday Night Football","level":2,"itemCount":0,"children":[]},
                {"id":16934,"name":"View All","level":2,"itemCount":0,"children":[]}]}];
        var deferred = $q.defer();
        setTimeout(function(){
            deferred.resolve({ data: { departments: departments }});
        }, 100);
        return deferred.promise;
      }
  }
});

我正在使用bootstrap-submenu项目:http://vsn4ik.github.io/bootstrap-submenu/

1 个答案:

答案 0 :(得分:0)

将行为应用于子菜单的代码行是:

$('[data-submenu]').submenupicker();

问题是这行代码是在子菜单存在之前执行的,因此从不应用该行为。修复是在将子菜单项(部门)添加到范围之后将此代码包装在$ timeout函数中。包装它允许完成AngularJS $摘要周期,并在添加子菜单行为之前将所有元素附加到DOM。

工作Plunkr:http://plnkr.co/edit/c8g43JxntmOXgZI0Wo05?p=preview

departmentService.getDepartments().then(function(success) {
    vm.departments = success.data.departments;
    $timeout(function(){
      $('[data-submenu]').submenupicker();
    }, 500);
  });