2013-05-27 110 views
1

我一直在努力与此相当一段时间,我无法弄清楚如何解决这个问题。嵌套元素指令无法访问父指令范围

我想做一个网格指令,其中包含列指令来描述网格,但列不会是元素,只会将列添加到在网格指令的范围内声明的数组。

我想解释这个问题的最好办法是查看查看代码:

var myApp = angular.module('myApp', []) 

    .controller('myCtrl', function ($scope, $http) { 
    }) 
    .directive('mygrid', function() { 
     return { 
      restrict: "E", 
      scope: true, 
      compile: function ($scope) { 
       debugger; 
       $scope.Data = {}; 
       $scope.Data.currentPage = 1; 
       $scope.Data.rowsPerPage = 10; 
       $scope.Data.startPage = 1; 
       $scope.Data.endPage = 5; 
       $scope.Data.totalRecords = 0; 
       $scope.Data.tableData = {}; 
       $scope.Data.columns = []; 
      }, 
      replace: true, 
      templateUrl: 'mygrid.html', 
      transclude: true 
     }; 
    }) 
    .directive('column', function() { 
     return { 
      restrict: "E", 
      scope: true, 
      controller: function ($scope) { 
       debugger; 
       $scope.Data.columns.push({ 
        name: attrs.name 
       }); 

      } 
     }; 
    }); 

这里是HTML标记:

<body ng-app="myApp"> 
<div ng-controller="myCtrl"> 
    <input type="text" ng-model="filterGrid" /> 
    <mygrid> 
     <column name="id">ID</column> 
     <column name="name">Name</column> 
     <column name="type">Type</column> 
     <column name="created">Created</column> 
     <column name="updated">Updated</column> 
    </mygrid> 
</div> 

此外,你可以测试jsfiddle中的实际代码:http://jsfiddle.net/BarrCode/aNU5h/

我试着用compile,c控制器和链接,但由于某些原因,父网格的列未定义。

我该如何解决这个问题?

编辑: 当我删除替换,templateUrl,transclude从mygrid指令,我可以从列指令的范围。

感谢

+1

这个成功吗? –

+1

是的,在更高版本的angularJS中,您可以使用$ scope。$ child childHead –

回答

1

在更高版本的AngularJS中,我发现$ scope。$$ childHead做我想要的。

它仍然是新的,但它也适用于隔离范围指令。

所以在列指令,你可以这样做:

$scope.$$childHead.Data.columns.push({ 
        name: attrs.name 
       }); 

只要确保这个命令在格的编译后执行。你可以这样做,但在编译,链接和控制器之间切换,因为它们每个都有不同的加载优先级。

0

我看到你想要做什么,但使用column指令可能不是解决问题的最好办法。

您试图使用可自定义的列定义grid指令。每列都有2条相关信息:访问行数据中的值的键和要显示的标题。

暂时忽略所有分页相关的东西,这里是解决问题的另一种方法。

首先,让我们使用属性来定义列信息,所以我们的HTML看起来像:

<body ng-app='app' ng-controller='Main'> 
    <grid col-keys='id,name,type' 
      col-titles='ID,Name,Type' 
      rows='rows'> 
    </grid> 
</body> 

对于JS,我们显然需要app模块:

var app = angular.module('app', []); 

而这里的grid指令。它使用隔离范围,但使用双向绑定从其父范围获取行数据。注意链接函数如何从attrs对象中提取列信息。

该模板变得非常简单:循环遍历列标题来定义标题,然后遍历rows,并在每一行循环遍历列键。

app.directive('grid', function() { 
    return { 
     restrict: 'E', 
     scope: { 
      rows: '='    
     }, 
     link: function(scope, element, attrs) { 
      scope.colKeys = attrs.colKeys.split(','); 
      scope.colTitles = attrs.colTitles.split(','); 
     }, 
     replace: true, 
     template: 
      '<table>' + 
      ' <thead>' + 
      ' <tr>' + 
      '  <th ng-repeat="title in colTitles">{{title}}</th>' + 
      ' </tr>' + 
      ' </thead>' + 
      ' <tbody>' + 
      ' <tr ng-repeat="row in rows">' + 
      '  <td ng-repeat="key in colKeys">{{row[key]}}</td>' + 
      ' </tr>' + 
      ' </tbody>' + 
      '</table>' 
    }; 
}); 

和一些示例数据开始。

app.controller('Main', function($scope) { 
    $scope.rows = [ 
     {id: 1, name: 'First', type: 'adjective'}, 
     {id: 2, name: 'Secondly', type: 'adverb'}, 
     {id: 3, name: 'Three', type: 'noun'} 
    ]; 
}); 

Here it is in fiddle form.

+1

获取您的父指令。感谢您的解释,但我真的宁愿使用我的标记方式来解决此问题,因为在您的方式中,如果我想要要更改列订单或向列添加更多选项,我必须通过网格中的另一个属性传递它,它最终看起来非常漫长和混乱。试图简化标记方面的所有内容,并在指令方面做所有的努力工作。 –

+0

问题在于你在编码JS值到你的HTML中,这与使用Angular的目标背道而驰。请注意,我只是在这里使用字符串来简化事情。 'colKeys'和'colTitles'可以通过隔离范围来引用,就像在父控制器中定义的“rows”一样,避免了“冗长和杂乱”。 – satchmorun

0

正如评论音利:

在AngularJS的更高版本可以使用$scope.$$childHead

我没有测试它让你的父母指令。