【问题标题】:Child directive can't access parent controller子指令无法访问父控制器
【发布时间】:2016-02-10 17:50:27
【问题描述】:

我有 2 个创建网格表的指令。 对于每一行,我们可能有一些操作,我的问题是我可以在不调用模板中的 $parent.$parent.action 的情况下以某种方式访问​​这些操作吗?

            .directive("grid", function ($compile, $parse) {
            return {
                restrict: 'AE',
                scope:  {
                    templateUrl         : '@?',
                    columns             : '=',
                    filterBy            : '=?',
                    excludeSortColumns  : '=?'
                },
                controller: GridController,
                controllerAs: 'grid',
                bindToController: true,
                replace: true,
                transclude: true,
                templateUrl: function($element, $attrs) {
                    if(!angular.isDefined($attrs.filterBy)) {
                        return '/assets/js/src/templates/partials/grid/grid-sortable.tpl.html';
                    }
                    return $attrs.templateUrl || '/assets/js/src/templates/partials/grid/grid.tpl.html';
                },
                link: function($scope, $element, $attrs, ctrl, transclude) {
                    //filter collection when user has typed some letter
                    $element.on('keyup', function() {
                        $scope.$apply(function() {
                            $scope.$parent.filterValue = $('.filterBy').val();
                        });
                    });
                    //var e = $compile(transclude())($scope.$parent);
                    //angular.element('.table').append(e);
                    $element.append(transclude($scope.$parent));
                }
            };

            function GridController($scope, $element, $attrs) {
                var vm = this;

                vm.columns = $parse($attrs.columns)($scope.$parent);
                vm.excludeSortColumns = angular.isDefined($attrs.excludeSortColumns) ? $parse($attrs.excludeSortColumns)($scope.$parent) : false;
                vm.filterCol = angular.isDefined($attrs.filterBy) ? $parse($attrs.filterBy)($scope.$parent) : false;

                vm.sortBy = function(column) {
                    if(!vm.isExludedSortBy(column)) {
                        vm.predicate = column;
                        vm.reverse = (vm.predicate === column) ? !vm.reverse : false;
                        var sortType = (vm.reverse) ? '-' : '+';
                        $scope.$parent.orderByColumn = sortType + column;
                    }
                };

                vm.isExludedSortBy = function(column) {
                    if(!vm.excludeSortColumns) {
                        return true;
                    }
                    if(vm.excludeSortColumns.indexOf(column) >= 0) {
                        return true;
                    }
                    return false;
                };
            };
        })

        .directive("gridBody", function ($parse) {
            return {
                restrict: 'AE',
                scope:  {
                    templateUrl         : '@?',
                    collection          : '='
                },
                require: '^grid',
                controller: function($scope, $element, $attrs) {
                    var vm = this;
                    vm.collection = $parse($attrs.collection)($scope.$parent);
                },
                controllerAs: 'body',
                bindToController: true,
                replace: true,
                transclude: false,
                templateUrl: function($element, $attrs) {
                    return $attrs.templateUrl || '/assets/js/src/templates/partials/grid/grid-body.tpl.html';
                }
            };
        })

这是一个模板:

<tbody>
    <tr ng-repeat="item in body.collection | gridFilterBy:$parent.filterBy:$parent.filterValue | orderBy:$parent.orderByColumn track by $index">
        <td class="col-sm-1">{{item.id}}</td>
        <td class="col-sm-2">{{item.name}}</td>
        <td class="col-sm-1">{{item.latest_result.count}}</td>
        <td class="col-sm-2">{{item.created_at}}</td>
        <td class="col-sm-2">{{item.updated_at}}</td>
        <td class="col-sm-4">
            <button class="btn btn-primary" ng-disabled="item.has_cluster" role="button" ng-click="$parent.$parent.addCluster(item.id)">
                Crea cluster
            </button>
            <button class="btn btn-primary" role="button" ng-click="$parent.getExports(item.id, item.name)">
                Export
            </button>
            <button class="btn btn-primary" role="button" ng-click="$parent.$parent.loadQuery(item.id)">
                Visualizza
            </button>
            <button class="btn btn-primary" role="button" ng-click="$parent.$parent.removeQuery(item.id)">
                Rimuovi
            </button>
        </td>
    </tr>
</tbody>
            <grid columns="columns" filter-by="filterBy" exclude-sort-columns="excludeColumns">
            <grid-body collection="result.items" template-url="/assets/js/src/templates/partials/grid/grid-body.tpl.html"></grid-body>
        </grid>

我无法获取网格控制器

感谢所有回复。

【问题讨论】:

    标签: angularjs directive angularjs-ng-transclude


    【解决方案1】:

    通常这是通过指令控制器完成的。以下是设置父子指令控制器相互感知的示例:

    app.directive('parentDir', function() {
      return {
        restrict: 'A',
        controller: function($scope, $element, $attrs) {
          this.parentInit = function(ctrl) {
            console.log(ctrl);
          };
    
          this.parentClick = function(param) {
    
          };
        },
        link: function(scope, element, attrs) {
    
        }
      }
    });
    
    app.directive('childDir', function() {
      return {
        restrict: 'A',
        require: ['childDir', '^parentDir'],
        controller: function($scope, $element, $attrs) {
          var parentCtrl;
          this.childInit = function(parentCtrl) {
            console.log(parentCtrl);
            parentCtrl = ctrl;
          };
    
          $scope.childClick = function(param) {
            parentCtrl.parentClick(param);
          };
        },
        link: function(scope, element, attrs, ctrls) {
          ctrls[0].childInit(ctrls[1]);
          ctrls[1].parentInit(ctrls[0]);
        }
      }
    });
    

    这是plunk 的演示。

    【讨论】:

    • 好吧,我知道我可以使用 require 属性来检索父控制器,但是当我在我的子指令上设置它时,它会抛出这个错误:Controller 'grid', required by directive 'gridBody', can't be found!
    猜你喜欢
    • 2015-06-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-10-15
    • 1970-01-01
    • 2016-01-25
    • 2015-09-09
    • 1970-01-01
    相关资源
    最近更新 更多