在DOM上使用指令模板后应用jQuery代码

时间:2014-01-01 10:16:01

标签: angularjs angularjs-directive

我有以下指令:

appDirective.directive('sidebar', function () {
  var directiveDefinitionObject = {
    //return {
    restrict: 'E',
    replace: true,
    template: '<li ng-repeat="m in menu" ng-class="{\'dropdown\':m.submenu, \'open\':m.open}">' +
      '<a href="{{m.url}}" ng-class="{\'dropdown-toggle\':m.submenu}" ng-attr-data-toggle="{{m.type}}">' +
      '<i class="{{m.image}}"></i>' +
      ' {{m.name}}' +
      '<b class="caret" ng-if="m.submenu"></b>' +
      '</a>' +
      '<ul ng-if="m.submenu" class="dropdown-menu">' +
      '<li ng-repeat="s in m.submenu"><a ng-class="{\'active\':s.active}" href="{{s.url}}"><i class="{{s.image}}"></i> {{s.name}}</a></li>' +
      '</ul>' +
      '</li>',
    link: function (scope, elem, attrs) {
      scope.menu = [
        {
          "name": "Dashboard",
          "url": "/manage/dashboard/index",
          "image": "fa fa-dashboard",
          "type": "dropdown",
          "open": dashboardOpen,
          "submenu": [
            {
              "name": "Overview",
              "active": dashboard_overview_active,
              "url": "/manage/dashboard/index",
              "image": "fa fa-circle-o"
            },
            {
              "name": "System Performance",
              "active": dashboard_overview_nodes,
              "url": "/manage/dashboard/nodes",
              "image": "fa fa-tasks"
            },
            {
              "name": "Query Performance",
              "url": "/manage/dashboard/index",
              "image": "fa fa-bolt"
            }
          ]
        },
        {
          "name": "Data Integration",
          "url": "/manage/dataintegration/index",
          "image": "fa fa-table"
        },
        {
          "name": "User Management",
          "url": "/manage/users/index",
          "type": "dropdown",
          "image": "fa fa-users",
          "open": usersOpen,
          "submenu": [
            {
              "name": "Users",
              "active": users_users,
              "url": "/manage/users/index",
              "image": "fa fa-user"
            },
            {
              "name": "Roles & Permissions",
              "active": users_roles,
              "url": "/manage/users/roles",
              "image": "fa fa-lock"
            },
            {
              "name": "Organizations",
              "active": users_orgs,
              "url": "/manage/users/organizations",
              "image": "fa fa-globe"
            }
          ]
        },
        {
          "name": "Logs and Alerts",
          "url": "/manage/logger/index",
          "image": "fa fa-bars"
        }
      ];
      scope.$watch('menu', function(val) {
        console.log(val);
        $('.dropdown').on('show.bs.dropdown', function (e) {
          $(this).find('.dropdown-menu').first().stop(true, true).slideDown();
        });

        $('.dropdown').on('hide.bs.dropdown', function (e) {
          $(this).find('.dropdown-menu').first().stop(true, true).slideUp();
        });
      })
    }
  }
  return directiveDefinitionObject;
});

我已经在指令实际绘制模板后运行的$watch函数中添加了一些jQuery代码。但是,在将元素添加到DOM之前,$watch会触发。

1 个答案:

答案 0 :(得分:0)

这不是我们应该使用角度的方式。使用angular时,我们应该通过ng-clickng-change等指令附加事件处理程序。

在您的情况下,当模型更改时,无法保证视图已完成渲染。该视图还会使用$watch监听代码所做的模型更改。模型更改后,它会通知视图和您的代码 单独 。通常,使用$ timeout来安排下一个周期的工作是一个技巧。但我认为我们可以利用jQuery事件委托来处理动态元素。

尝试设置replace: false并使用事件委派。不需要$watch

elem.on('show.bs.dropdown','.dropdown', function (e) {
   $(this).find('.dropdown-menu').first().stop(true, true).slideDown();
});

elem.on('hide.bs.dropdown','.dropdown', function (e) {
    $(this).find('.dropdown-menu').first().stop(true, true).slideUp();
});

在你的情况下使用$ watch还有另一个缺点,即可以将多个事件处理程序添加到同一个元素,因为每次模型更改时,此代码都将再次运行。