嵌套元素指令无法访问父指令范围
Posted
技术标签:
【中文标题】嵌套元素指令无法访问父指令范围【英文标题】:Nesting element directives can't access parent directive scope 【发布时间】:2013-05-22 11:51:22 【问题描述】:我已经为此苦苦挣扎了很长一段时间,但我不知道如何解决这个问题。
我正在尝试创建一个网格指令,其中包含用于描述网格的列指令,但列不会是元素,只会将列添加到在网格指令范围内声明的数组中。
我认为解释这个问题的最好方法是查看查看代码:
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/
我尝试使用编译、控制器和链接,但由于某种原因,父网格的列未定义。
我该如何解决这个问题?
编辑: 当我从 mygrid 指令中删除 replace、templateUrl、transclude 时,我可以从 column 指令中获取范围。
谢谢
【问题讨论】:
这有什么成功吗? 是的,在 angularJS 的更高版本中,您可以使用 $scope.$$childHead 获取父指令 【参考方案1】:在更高版本的 AngularJS 中,我发现 $scope.$$childHead 可以满足我的要求。
它仍然是新的,但它也适用于具有隔离范围的指令。
所以在 Columns 指令中你可以这样做:
$scope.$$childHead.Data.columns.push(
name: attrs.name
);
只需确保在网格编译后执行此命令即可。你可以这样做,但要在编译、链接和控制器之间切换,因为它们中的每一个都有不同的加载优先级。
【讨论】:
【参考方案2】:我明白你想要做什么,但使用 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
指令。它使用隔离作用域,但使用=
2-way 绑定从其父作用域获取行数据。请注意链接函数如何从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.
【讨论】:
感谢您的解释,但我真的更愿意使用我的标记方式来解决这个问题,因为如果我想更改列顺序或向我拥有的列添加更多选项,请按照您的方式将它传递给网格中的另一个属性,它最终会看起来很长而且很乱。尝试简化标记方面的所有内容,并在指令方面做所有艰苦的工作。 问题在于你将 JS 值编码到 HTML 中,这与使用 Angular 的目标背道而驰。请注意,我只是在这里使用字符串来简化事情。colKeys
和 colTitles
可以通过类似 rows
的隔离范围引用并在父控制器中定义,避免“冗长而混乱”。【参考方案3】:
正如伊姆里所说:
在更高版本的 AngularJS 中,您可以使用 $scope.$$childHead
获取父指令
我没有测试过。
【讨论】:
以上是关于嵌套元素指令无法访问父指令范围的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 Angular 中的依赖注入将属性指令实例传递给嵌套组件