具有隔离范围的指令与AngularJS中的控制器通信

时间:2014-02-24 17:43:34

标签: javascript angularjs

我已经阅读了一些类似我的问题的答案,例如this one虽然无法将其转化为我自己的要求 - 来自缺乏理解......

我有一个控制器:

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(.....)" - 这似乎也没有用。

有人可以指出我正确的方向吗?

2 个答案:

答案 0 :(得分:3)

ng-click="$parent.Filter(.....)"无效,因为您在ng-repeat中创建了一个(非隔离的)范围。在这种情况下,你必须写

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

但不要这样做......

您可以在Click事件处理程序中发出一个事件,并在控制器中监听它。

<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);
    }
}]);

答案 1 :(得分:1)

在多个地方使用指令并不意味着您不能使用共享范围。如果指令应始终显示相同的状态(因此每个继承和操作控制器的相同属性),或者它们各自旨在显示自己的状态版本(因此是隔离的),那么这个决定归结为。因为你在$ scope.FilterApplied中设置一个控制器级变量,我假设你只想在页面上重复相同的控件?如果是这样,你可以坚持继承范围。

如果没有,而且每个指令都需要它自己的这个功能,你可能最好将Filter代码移动到指令和控制器都注入的服务中,以便共享实用程序功能但是设置和过滤器的状态是每个范围而不是共享。

最终取决于你如何使用它。

相关问题