2015-04-07 33 views
1

我正在使用AngularJS應用程序。這個應用程序通過過濾和排序等構造了一個複雜的零件信息表。該表使用兩個ngRepeat指令構建。其中一個命中JSON API來獲取列標題,另一個獲取這些列的所有部分數據。根據零件類別,表格可以有5到50列的任意位置,並且該類別中可能有2到2000個零件。AngularJS - 如何僅對多個事件的組合採取行動

表格呈現後,我需要應用jQuery插件來啓用附加功能。我的問題是插件初始化發生得太早。當指令完成所有渲染時,我只需要調用init函數。

我的第一步是創建一個指令,設置一個我可以聽的事件。以下是我使用的:

angular.module('myApp') 
.directive('myOnLoad', [function() { 
    return function(scope, element, attrs) { 
     if (scope.$last) setTimeout(function(){ 
      scope.$emit('everythingLoaded', element, attrs); 
     }, 1); 
    }; 
}]); 

我然後把該指令對這樣我的中繼器之一:

<th ng-repeat="attribute in ctrl.attributes" attribcol="attribute" class="mps-attribute-cell" my-on-load></th> 

然後在我的控制器聽吧:

$scope.$on('everythingLoaded', function(scope, element, attrs){ 
    var containerHeight = jQuery(window).height() - 100; 
    jQuery('#mps-table').fixedHeaderTable({ 
      width: '100%', 
      height: containerHeight + 'px', 
      fixedColumn: true 
    }); 
}); 

這幫助我等待插件初始化之前加載的屬性列,但它並不完全正確,因爲當這種情況發生時,其他指令可能無法完成。我需要確保兩個中繼器都已完成。

在init代碼觸發之前,我怎樣才能要求兩個不同事件的組合

UPDATE

我創建了一個看起來像這樣至今服務:

angular.module('myApp') 
    .factory('featureInit', ['$rootScope', 
     function ($rootScope) { 
      var featureReady = 0; 
      $rootScope.$on('attributesLoaded', function (scope, element, attrs) { 
       featureReady++; 
       console.log('attributesLoaded so featureReady is now ' + featureReady); 
      }); 
      $rootScope.$on('partsLoaded', function (scope, element, attrs) { 
       featureReady++; 
       console.log('partsLoaded so featureReady is now ' + featureReady); 
      }); 
      featureInit.init = function() { 
       if (featureReady > 1) { 
        console.log('triggers were hit'); 
        var containerHeight = jQuery(window).height() - 100; 
        jQuery('#mps-table').fixedHeaderTable({ 
         width: '100%', 
         height: containerHeight + 'px', 
         fixedColumn: true 
        }); 
       } 
      }; 
     }]); 

我已經調整的情況下,發射指令產生正確的事件何時完成加載和我服務正確記錄變量「featureReady」。我可以看到它在最終到達「2」時得到記錄,此時我想運行init函數中的所有代碼。

在這一點上,我不確定如何讓我的應用程序「觀看」featureReady變量,以便它在觸及正確的點時啓動該init函數。

+0

您可以創建一個服務,(因爲它們是單身),把你想要觀看裏面的事情的清單它,當你想觀看的所有東西都完成時觸發一個功能。 – Delta

+0

更新了問題。 – claywhipkey

+0

如果您正在使用角UI路由器作爲指定在這裏你可以監聽$ viewContentLoadedevent https://github.com/angular-ui/ui-router/wiki#view-load-events – Senthil

回答

0

終於解決了。這裏是我的自定義指令文件(鏈接他們到同一個文件),以處理事件發射:

angular.module('myApp') 
    .directive('partLoadEvent', [function() { 
      return function (scope, element, attrs) { 
       if (scope.$last) 
        setTimeout(function() { 
         scope.$emit('partsLoaded', element, attrs); 
        }, 1); 
      }; 
     }]) 
    .directive('attributeLoadEvent', [function() { 
      return function (scope, element, attrs) { 
       if (scope.$last) 
        setTimeout(function() { 
         scope.$emit('attributesLoaded', element, attrs); 
        }, 1); 
      }; 
     }]); 

我有這樣的中繼器的指令:

<tr ng-repeat="part in ctrl.parts" partrow="part" part-load-event></tr> 

我的服務是這樣的:

angular.module('myApp') 
    .factory('featureInit', ['$rootScope', 
     function ($rootScope) { 
      var featureReady = 0; 
      var initThreshold = 2; 
      var featureMethods = { 
       init: function() { 
        /* do all my post-render stuff */ 
       } 
      }; 
      $rootScope.$on('attributesLoaded', function (scope, element, attrs) { 
       featureReady++; 
       if (featureReady >= initThreshold) 
        featureMethods.init(); 
      }); 
      $rootScope.$on('partsLoaded', function (scope, element, attrs) { 
       featureReady++; 
       if (featureReady >= initThreshold) 
        featureMethods.init(); 
      }); 
     }]); 

最後,包括服務到主控制器:

angular.module('myApp') 
    .controller("MPSController", ['$http','$sce','_','featureInit', function ($http, $sce, _, featureInit) { 

榮譽給@Delta的建議,調用函數時的門檻被擊中。我只需要進一步研究訪問該功能的正確方法。我不得不將函數附加到一個變量,而不是「this」。 (可能是與範圍,但我新的角度和不完全得到它。)

1

所以如果你只需要讓這個類做一件事,那麼我會創建一個這樣的服務。

angular.module('myApp') 
     .service('featureService', 
     function() 
     { 
      var _this = this; 
      this.OpenResponses = []; 
      this.RemoveResponse = function (responseToRemove) 
      { 
       var index = this.OpenResponses.indexOf(responseToRemove) 
       if (index > -1) 
        this.OpenResponses.splice(index, 1); 
       if (this.OpenResponses.length <= 0) 
        this.ResponsesAllFinished(); 
      }; 
      this.ResponsesAllFinished = function() 
      { 
       //do stuff 
      } 
     }); 

然後在你的指令

angular.module('myApp') 
     .directive('myOnLoad', ['featureService', function (featureService) 
     { 
      return function (scope, element, attrs) 
      { 
       //If doesnt matter what you push in here as long as you remove the same value 
       featureService.OpenResponses.push(this); 
       if (scope.$last) 
        featureService.RemoveResponse(this); 
      }; 
     }]); 

所有這一切的JavaScript可能不是語義正確的,我一直在使用打字稿最近但這應該傳達出的總體思路。

+0

'featureService.OpenResponses.length'不會在每個指令的末尾分別減少到0嗎?我有兩個指令,每個指令都發出自己的事件來表示特定類型的加載已完成。我需要將我的init代碼綁定到兩個事件的**組合**上。 – claywhipkey

+0

如果您將它們都添加到服務中,由於該服務是單例服務,它會將每個服務添加到同一個列表中。 – Delta

+0

我確實嘗試過這種方式,但沒有啓動最終功能。我錯過了什麼嗎?我應該從控制器觀看服務嗎? – claywhipkey