简体   繁体   English

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

[英]Directive with isolate scope communicate with controller in AngularJS

I've read some similar answers to my question, such as this one though can't translate it to my own requirements - comes from a lack of understanding... 我已经读过我的问题的一些类似答案,例如,尽管不能将其转化为我自己的要求-来自缺乏理解...

I have a controller: 我有一个控制器:

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

And I have a directive: 我有一条指令:

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

}]);

And the template for my directive: 还有我指令的模板:

<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>

If I don't isolate the scope of the directive then the controller is called correctly, and i see the console logging out my arguments. 如果我没有隔离指令的范围,那么将正确调用控制器,并且我会看到控制台注销我的参数。

However, I (think) I need to isolate the scope as there will be multiples of this directive on the page. 但是,我(认为)我需要隔离范围,因为此指令在页面上会有多个。

when I add scope: {} to my directive the controller function is no longer called. 当我在指令中添加scope: {} ,不再调用控制器函数。

I also tried changing my ng-click to ng-click="$parent.Filter(.....)" - that didnt' seem to work either. 我还尝试将ng-click更改为ng-click="$parent.Filter(.....)" -似乎也不起作用。

Can anybody please point me in the right direction? 有人能指出我正确的方向吗?

ng-click="$parent.Filter(.....)" isn't working because you have it in an ng-repeat which also creates a (non-isolated) scope. ng-click="$parent.Filter(.....)"无法正常工作,因为您将其放在ng-repeat ,这也会创建一个(非隔离的)作用域。 In that case you would have to write 在这种情况下,您将不得不写

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

but don't do that... 但是不要那样

You could emit an event in the click event handler and listen for it in your controller. 您可以在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>

directive: 指示:

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

}]);

controller: 控制器:

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

Having the directive used in multiple places does not mean you can't use shared scope. 在多个位置使用指令并不意味着您不能使用共享范围。 That determination comes down to if the directives should always show the same state (thus each inheriting and manipulating the same properties of the controller), or if they each are intended to show their own versions of state (thus being isolate). 这种决定归结于指令是否应该始终显示相同的状态(因此每个指令都继承并操纵控制器的相同属性),或者它们是否各自旨在显示自己的状态版本(因此是隔离状态)。 Being that you are setting a controller level variable in $scope.FilterApplied I assume you just want to repeat the same controls on the page? 假设您要在$ scope.FilterApplied中设置控制器级别的变量,我想您只是想在页面上重复相同的控件? If so, you can stick with an inherited scope. 如果是这样,您可以坚持继承的范围。

If not, and instead each directive needs this functionality on it's own, you are probably better off moving the Filter code into a service that the directive and controller(s) both inject so that the utility functions are shared but the settings and state of the Filter are per scope rather than shared. 如果不是这样,而是每个指令本身都需要此功能,则最好将Filter代码移到该指令和控制器都注入的服务中,以便共享实用程序功能,但共享设置和状态。过滤器是按作用域而不是共享的。

Ultimately it depends on how you are using it. 最终,这取决于您的使用方式。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM