在指令中调用模板后 $scope 变为空

$scope gets null after calling template in directive

我有一个像这样的嵌套指令

app.directive('grid', ['$log', '$http', function ($log , $http) {
    return {
        restrict: 'E',
        scope: {},
        //template: '<span></span>', //i uncomment this line
        controller: function ($scope, $element, $attrs){
            var swColumns = [];
            this.setColumns = function (columns) {
                swColumns = columns;
                $log.log('grid controller');
                $log.log(columns);
                $scope.swColDefs = columns;
                $log.log($scope.swColDefs);
            };

            this.getColumns = function () {
                return swColumns;
            };
        },
        link: function (scope, element, attrs, gridController) {
            $log.log('grid link');
            $log.log(gridController.getColumns());
            $log.log(scope.swColDefs);
        }
    };
}]);
app.directive('gridColumns', ['$log', function ($log) {
    return {
        restrict: 'E',
        require: ['^grid', 'gridColumns'],
        controller: function () {
            var columns = [];
            this.addColumns = function (column) {
                columns.push(column);
            };
            this.getColumns = function () {
                return columns;
            };
        },
        link: function (scope, element, attrs, controllers) {
            var gridController = controllers[0];
            var gridColumnsController = controllers[1];
            gridController.setColumns(gridColumnsController.getColumns());
        }
    };
}]);

一切正常,直到我取消注释网格指令中的模板 之后 grid link 函数中的 swColDefs 变为空数组 我的代码有什么问题?

<grid>
  <grid-columns>
  </grid-columns>
  ...
</grid>

我就是这样用的

虽然问题没有具体说明,但我假设您是这样使用指令的:

<grid>
  <grid-columns>
  </grid-columns>
  ...
</grid>

但是由于您指定的模板是 <grid>,Angular 会删除内容并设置模板。因此,gridColumns 指令永远不会编译并且 link 函数永远不会运行。

这是 grid 上需要嵌入的地方。嵌入从 DOM 中取出内容,对其进行编译(在编译阶段),然后允许您根据需要的任何范围 link 将其放入内容中。

从你的问题中不清楚 gridColumns 指令需要 link 反对什么范围,以及它是否有任何可视组件。

对于简单的嵌入情况,可以在 grid 的模板中使用 <ng-transclude> 来完成:

transclude: true,
template: "<span>whatever</span><div ng-transclude></div>" // template of grid

或者,为了更精确地控制范围和位置,您可以使用 transclude 函数(作为第五个参数传递给 link 函数):

transclude: true,
template: "<span>whatever</span>",
link: function(scope, element, attrs, gridController, transclude){
  transclude(function(transcludedContent){
     // place the content where needed, if at all
  });
}

我已经在网格模板中解决了这个问题 首先我在模板中添加一个带有 ng-transclude 的 div secod transclude : true in grid directive

app.directive('grid', ['$log', '$http', function ($log , $http) {
    return {
        restrict: 'E',
        scope: {},
        transclude:true,//my change
        template: '<span>
                   <div ng-transclude>//my change
                   </div>
                   </span>',
        controller: function ($scope, $element, $attrs){
            var swColumns = [];
            this.setColumns = function (columns) {
                swColumns = columns;
                $log.log('grid controller');
                $log.log(columns);
                $scope.swColDefs = columns;
                $log.log($scope.swColDefs);
            };

            this.getColumns = function () {
                return swColumns;
            };
        },
        link: function (scope, element, attrs, gridController) {
            $log.log('grid link');
            $log.log(gridController.getColumns());
            $log.log(scope.swColDefs);
        }
    };
}]);