2014-02-24 122 views
1

我讀過一些類似的回答我的問題控制器通信,如this one雖然不能將其翻譯成我自己的要求 - 來自缺乏瞭解......指令與分離範圍與AngularJS

我有一個控制器:

appControllers.controller('TransactionsCtrl', ['$scope', 'InfiniteScrollingDataService', function ($scope, dataService) { 
    // setup our scope properties 
    $scope.$root.title = 'Transactions'; 
    var urlQuery = { 
     skip: 0, 
     take: 25, 
     search: '', 
     order: 'DateTimeCreated', 
     orderBy: 'desc', 
     transactionTypeID: null, 
     transactionStatusID: null 
    }; 
    var apiUrl = 'api/transactions'; 
    $scope.transactions = new dataService(apiUrl, urlQuery); 

    $scope.Filter = function (senderParent, type, id) { 
     $scope.FilterApplied = true; 
     console.log('filter in controller: ' + senderParent + ' ' + type + ' ' + id); 
    } 
}]); 

而且我有一個指令:

appDirectives.directive('bootstrapListItems', ['$rootScope', function ($rootScope) { 

    return { 
     restrict: 'A', 
     templateUrl: 'bootstrapDropDownItems.html', 
     link: function (scope, element, attrs) { 

      scope.type = attrs.useGlobaljsonObject; 
      scope.parentElement = attrs.id; 
      scope.items = []; 

      var obj = $rootScope.globalJSON[scope.type]; 

      for (o in obj) { 
       scope.items.push({ key: o, value: obj[o] }) 
      } 
     }  
    } 

}]); 

而對於我的指令模板:

<script type="text/ng-template" id="bootstrapDropDownItems.html"> 

    <li class="active"><a href="#" class="lnkFilterList">- Any -</a></li> 
    <li ng-repeat="item in items"> 
     <a href="#" class="lnkFilterList" ng-click="Filter(parentElement, type, item.key)">{{item.value}}</a> 
    </li> 

</script> 

如果我不隔離指令的作用域,那麼控制器被調用正確,我看到控制檯註銷我的參數。

但是,我(想)我需要隔離範圍,因爲該頁面上會有這個指令的倍數。

當我添加scope: {}到我的指令控制器功能不再被調用。

我也嘗試將我的ng-click更改爲ng-click="$parent.Filter(.....)" - 這似乎也沒有工作。

任何人都可以請我指出正確的方向嗎?

+0

這將有助於解決您的問題http://stackoverflow.com/questions/15991137/calling-method-of-parent-controller-from-a-directive-in-angularjs/15991525#15991525 –

回答

3

ng-click="$parent.Filter(.....)"不起作用,因爲您在ng-repeat中創建了一個(非隔離)範圍。在這種情況下,你會寫

ng-click="$parent.$parent.Filter(.....)" 

,但不這樣做......

你可以發出在單擊事件處理程序的事件,並在控制器中偵聽它。

<script type="text/ng-template" id="bootstrapDropDownItems.html"> 

    <li class="active"><a href="#" class="lnkFilterList">- Any -</a></li> 
    <li ng-repeat="item in items"> 
     <a href="#" class="lnkFilterList" ng-click="onClick(parentElement, type, item.key)">{{item.value}}</a> 
    </li> 

</script> 

指令:

appDirectives.directive('bootstrapListItems', ['$rootScope', function ($rootScope) { 

    return { 
     restrict: 'A', 
     templateUrl: 'bootstrapDropDownItems.html', 
     link: function (scope, element, attrs) { 

      scope.type = attrs.useGlobaljsonObject; 
      scope.parentElement = attrs.id; 
      scope.items = []; 

      var obj = $rootScope.globalJSON[scope.type]; 

      for (o in obj) { 
       scope.items.push({ key: o, value: obj[o] }) 
      } 
      scope.onClick = function(){ 
       // pass an array of original arguments to the event 
       scope.$emit('someEventName', Array.prototype.slice.call(arguments)); 
      }; 
     }  
    } 

}]); 

控制器:

appControllers.controller('TransactionsCtrl', ['$scope', 'InfiniteScrollingDataService', function ($scope, dataService) { 
    // setup our scope properties 
    $scope.$root.title = 'Transactions'; 
    var urlQuery = { 
     skip: 0, 
     take: 25, 
     search: '', 
     order: 'DateTimeCreated', 
     orderBy: 'desc', 
     transactionTypeID: null, 
     transactionStatusID: null 
    }; 
    var apiUrl = 'api/transactions'; 
    $scope.transactions = new dataService(apiUrl, urlQuery); 

    $scope.$on('someEventName', function(e, args){ 
     // call the $scope.Filter function with the passed array of arguments 
     $scope.Filter.apply(null, args); 
    }); 
    $scope.Filter = function (senderParent, type, id) { 
     $scope.FilterApplied = true; 
     console.log('filter in controller: ' + senderParent + ' ' + type + ' ' + id); 
    } 
}]); 
+0

嗨。我喜歡這個解決方案,因爲它可以讓我在指令中更改所選項目的某些課程信息。然而,我幾乎複製/粘貼這個,出於某種原因,我的參數在我的$ scope中是空的。$ on('filterSelected',function(e,args){...'並且都是undefined在我的$ scope.Filter函數。任何想法,我可能會出錯? – Darren

+0

其實 - 如果我改變'Array.prototype.slice(參數)'只是'參數'它一切按規定工作。不知道爲什麼(不使用片之前......) – Darren

+0

任何想法爲什麼Array.prototype.slice(arguments)返回一個空數組? – Darren

1

擁有在多個地方使用,並不意味着你不能使用共享範圍的指令。如果指令總是顯示相同的狀態(因此每個繼承和操作控制器的相同屬性),或者它們每個都打算顯示它們自己的狀態版本(因此被隔離),那麼這個決定歸結爲。因爲你在$ scope.FilterApplied中設置了一個控制器級變量,我假設你只是想在頁面上重複相同的控件?如果是這樣,你可以堅持一個繼承範圍。

如果不是,每個指令都需要它自己的功能,您最好將Filter代碼移動到指令和控制器都注入的服務中,以便實用程序功能可以共享,但設置和過濾器的狀態是根據範圍而不是共享的。

最終取決於你如何使用它。

+0

我假設(由於缺乏這方面的知識),我將需要一個隔離範圍。網頁上會有幾個使用此指令的元素。每個顯示列表中的不同項目。另外,當選擇過濾器的項目時,我需要設置所選項目的類別。在這種情況下,仍然不確定是否需要隔離作用域。 – Darren

+0

繼承作用域將簡單地允許它繼承其父代的作用域,而不是創建自己的作用域。如果您顯示的是同一個列表,並且它由控制器中的對象/屬性確定,那麼繼承範圍是最簡單的路徑。指令的每個實例都可以包含屬性,以更改它們顯示的列表的哪一部分。只有在操作和封裝自己的數據副本時,才需要隔離範圍。否則,每次更改控制器列表時,它們都會一起更改。這只是一個原型鏈。 –

+0

啊,好的。現在它變得更清晰了。在這些列表中沒有雙向綁定或類似的東西。這只是告訴控制器從應用此過濾器的web api獲取一些數據。我喜歡kamilkp給予的解決方案,因爲我可以在被選中的項目的指令內做更多的事情 - 更改類等等。謝謝你澄清 – Darren