2014-07-24 134 views
0

我有一个自定义窗体指令,可能每页使用多次。我需要这些指令的总数,因此增加了一个指令配置物体之外,即每次加载某个页面时调用一次方法(AngularJS)

module.directive("customInput", [ 
    function() 
    { 
     /* 
     * Because each instance of the directive will get its own 
     * instance of the return object, we have to declare groupCount 
     * here, instead of inside the post-link function where it's used. 
     */ 
     var groupCount = {}; 

     return { ...configObj... } 
    } 
]); 

的问题是,这个计数跨越的意见仍然存在。我将它移动到一个服务,并给它一个重置方法,但我需要一种方法来调用该方法每页只有一次。

我不想添加一个$routeChangeSuccess侦听器,因为对于使用这些输入的少数页面来说这似乎太重了。我不能在指令的控制器中执行它(例如$watch("$viewContentLoaded")),因为它会执行多次。

我不想把个人视图控制器的负担,如果有办法做一次。有没有(也许有一个“父母”指令)?

回答

0

我把柜台的服务,以便它有一些很好的增量和递减方法。根据Matthew Berg的建议使用$destroy,我可以调用服务的递减方法。我的估计是,这种解决方案比一次性的重置呼叫稍重,但不如路线变化时的手表那么糟糕。

// recommended var name for this object: groupControl 
module.service("GroupControlSvc", [ 
    function() 
    { 
     this.groupCount = {}; 

     this.incrementGroupCount = function (groupName) 
     { 
      if (!this.groupCount.hasOwnProperty(groupName)) { 
       this.groupCount[groupName] = 0; 
      } 
      this.groupCount[groupName]++; 
     }; 

     this.decrementGroupCount = function (groupName) 
     { 
      if (this.groupCount.hasOwnProperty(groupName)) { 
       console.log("decrementing group " + groupName); 
       this.groupCount[groupName]--; 

       if (this.groupCount[groupName] === 0) { 
        console.log("removing group " + groupName); 
        delete this.groupCount[groupName]; 
       } 
      } 
     }; 
    } 
]); 


module.directive("customInput", [ 
    function() 
    { 
     return { 
      ... 
      ,link: function (scope, elem, attrs) 
      { 
       ... 

       /* 
       * Count the members of each group, so we can 
       * determine which element is last. Because 
       * groupCount is an object (and an object of 
       * objects, at that), assigning it to scope 
       * here is by reference. Thus, every scope 
       * instance will point to the same object. 
       */ 
       if (attrs.hasOwnProperty("editGroup")) { 
        groupControl.incrementGroupCount(attrs.editGroup); 
       } 
       scope.groupCount = groupControl.groupCount; 

       scope.$on("$destroy", function() 
       { 
        groupControl.decrementGroupCount(attrs.editGroup); 
       }); 
      } // end post-link function 
     }; 
    } 
]); 

我想不是groupCount财产直接暴露,而是分配吸气功能范围,现在反而是不值得的。

这也让我接触到由于$destroy或其回调失败而导致的倾向。

虽然这解决了我的需求,但它并没有回答问题。

0

您可以在范围内侦听,只需要增加。例如:

module.directive("customInput", [ 
    function(){ 
     /* 
     * Because each instance of the directive will get its own 
     * instance of the return object, we have to declare groupCount 
     * here, instead of inside the post-link function where it's used. 
     */ 
     var groupCount = {}; 

     var totalCount = 0; 

     return { 
      link: function(scope){ 
       totalCount++; 
       scope.$on("$destroy", function(){ 
        totalCount-- 
       }); 
      } 
     } 
    } 
]); 

totalCount将始终是您拥有的元素的数量。如果你想使用它,你可以连接到你想要的任何东西(服务等)。

+0

减少'$ destroy'是个不错的主意。我用自己的回答扩展了这一点。 – N13

1

这可以在架构层面解决,而AngularJS对这种事情有很好的机制。浏览一下移动应用程序的编写方式,并制作一个“经理”服务。 Angular中的服务是单例服务,因此它可以维护变量,如对象集合(指令)和这些项目的计数。随后可以在需要时询问这些事情,可以要求创建/更改/删除它们。当你像ngRepeat那样做时,它也可以是数据的来源,而不是将数据存储在控制器中。

通信驱动的模型做了很多,它工作得很好。假设你有一个假想的“好友列表”。你可以做这样的事情:

angular 
    .module('myApp', []) 
    .controller('MainDisplay', function($scope, buddyManager) { 
    $scope.buddyManager = buddyManager; 

    // Handle things here that are relevant to the main display 
    $scope.sendMessage = function(buddy) { 
     alert('here I could message ' + buddy.name); 
    } 

    buddyManager.addBuddy('Susan'); 
    buddyManager.addBuddy('David'); 
    buddyManager.addBuddy('Jamie'); 
    }) 
    .service('buddyList', function() { 
    var self = this; 

    this.buddies = []; 
    this.buddyCount = 0; // If you didn't want to just do buddies.length... 

    this.addBuddy = function(name) { 
     // Again, if you didn't want to just use .length... 
     self.buddyCount++; 
     self.buddies.push({ 
     name: name 
     }); 
    }; 
    }) 
    .directive('buddy', function() { 
    return { 
     restrict: 'E', 
     replace: true, 
     scope: { buddy: '=' }, 
     template: '<div class="buddy">{{ name }}</div>', 
     link: function($scope) { 
     // Here you can put anything specific to a buddy, like click handlers 
     // $scope.buddy is yourself/your buddy data 
     } 
    }; 
    }); 

和一个简单的页面:

<html ng-app="myApp"> 
<head> 
<!-- You know you what you need... --> 
</head> 
<body ng-controller="MainDisplay"> 
    <buddy ng-repeat="buddy in buddyManager.buddies" buddy="buddy"></buddy> 
</body> 
</html> 

工作Plnkr这里: http://plnkr.co/edit/R3QMwLxEbqMRlBg74dOi?p=preview

+0

我知道服务的作用。当我转到另一条路线/视图时,“buddyList”服务 - 特别是计数 - 仍然存在。你能澄清这是如何回答我的问题吗? – N13

+0

您要求的方法只能每页调用一次该方法......将它放入服务中将允许您这样做,因为服务是单例。例如,假设你正在使用ui-router。这会在每个页面转换中发出$ stateChangeStart事件。您可以在您的服务中简单地收听此内容,并在发生这种情况时执行一次您想要完成的操作。每个路由器都有类似的东西,所以你应该能够钩住它们中的任何一个,不管它是什么。 –

+0

来自OP:“我不想添加'$ routeChangeSuccess'侦听器”。没有关于AFAIK的服务,它允许它为每个视图/路线调用一次方法。 – N13

相关问题