在我的AngularJs(v1.5.9)应用程序中,我有一种列表视图指令,它本身依赖于指令来呈现单个复杂项目。在列表项中应该准确呈现的内容由消费者决定并通过翻译传递。
所以基本结构看起来像这样:
<list-directive>
<list-item>
<some more stuff />
<transcluded content />
</list-item>
</list-directive>
我现在正在尝试向此结构添加另一个指令,该指令将可以通过属性从外部传递到顶级元素的数据,然后根据每个列表项的输入执行操作
结构有点复杂,我试图将下面的代码片段减少到最低限度。
// controller
(function () {
'use strict';
function FcDataListCtrl($scope, $q, $element) {
var that = this;
initVars();
init();
function initVars() {
that.actionButtons = that.actionButtons || [];
}
function init() {
}
}
angular
.module('controls.fcDataList.controller', [])
.controller('fcDataListCtrl', FcDataListCtrl);
})();
(function () {
'use strict';
function FcDataList() {
return {
restrict: 'E',
transclude: true,
template: `<fc-data-list-item ng-repeat="item in ::fcDataList.items" item="::item">
<div ng-transclude></div>
</fc-data-list-item>`,
scope: {
items: '=?',
actionButtons: '=?'
},
controller: 'fcDataListCtrl',
controllerAs: 'fcDataList',
bindToController: true
};
}
angular
.module('controls.fcDataList', [
'controls.fcDataList.controller',
'controls.fcDataList.item'
])
.directive('fcDataList', FcDataList);
})();
(function () {
'use strict';
function FcDataListItem() {
return {
restrict: 'E',
replace: true,
require: '^fcDataList',
transclude: 'element',
template: `<div>
<div ng-transclude></div>
<fc-item-menu items="fcDataList.actionButtons"></fc-item-menu>
</div>`,
scope: {
item: '=?'
},
link: {
pre: FcDataListItemLink
}
};
function FcDataListItemLink(scope, elem, attrs, fcDataListCtrl) {
initVars();
init();
function initVars() {
}
function init() {
console.log('FcDataListItem')
console.dir(fcDataListCtrl.actionButtons);
}
}
}
angular
.module('controls.fcDataList.item', [
'components.fioControlsExtensions.fcDataList.menu'
])
.directive('fcDataListItem', FcDataListItem);
})();
(function () {
'use strict';
function FcItemMenu() {
return {
restrict: 'E',
template: `<div ng-repeat="item in items">
<div>{{ item.icon }}</div>
</div>`,
scope: {
items: '=?'
},
link: {
pre: FcItemMenuLink
}
};
function FcItemMenuLink(scope, elem, attrs) {
scope.open = open;
initVars();
init();
function initVars() {
console.log('MenuItem');
console.dir(scope.items);
}
function init() {
}
function open(event) {
}
}
}
angular
.module('components.fioControlsExtensions.fcDataList.menu', [])
.directive('fcItemMenu', FcItemMenu);
})();
(function () {
'use strict';
function AppCtrl() {
var that = this;
init();
function init() {
that.fcDataList = {
buttons: [
{ icon: 'ff-show' }
],
items: [
{ firstName: 'Ivan', lastName: 'Petrov', jobPosition: 'Zookeeper' },
{ firstName: 'Andrei', lastName: 'Müller', jobPosition: 'Pilot' },
{ firstName: 'Christian', lastName: 'Klein', jobPosition: 'Cook' },
{ firstName: 'Peter', lastName: 'Stoyanov', jobPosition: 'Fuller' },
{ firstName: 'Nadine', lastName: 'Wolf', jobPosition: 'Driving Instructor' },
{ firstName: 'Amya', lastName: 'Krüger', jobPosition: 'Military' }
],
}
}
}
angular
.module('controls.example', [
'controls.fcDataList'
])
.controller('AppCtrl', AppCtrl)
})();
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.8/angular.min.js"></script>
<html lang="en" ng-app="controls.example">
<body ng-controller="AppCtrl as app">
<b>Test for data list n stuff</b>
<fc-data-list items="app.fcDataList.items"
action-buttons="app.fcDataList.buttons">
<div class="row">
<span> This is a list item </span>
</div>
</fc-data-list>
</body>
</html>
&#13;
这里也是Codepen的例子:https://codepen.io/lyioth/pen/LbqWLz/
请注意,这里没有显示实际项目内容的转换(但这没有问题,所以我跳过了它。)
实际问题是,items
中的fc-item-menu
未定义。我添加了一些日志语句来表明在该组件上面的级别,所讨论的数组实际上并不是空的。
如果我将指令更改为require
控制器并直接访问actionButtons
属性,它似乎也可以工作。但我宁愿不这样做。
所以问题是,为什么这项工作没有按预期进行?我错过了什么?
答案 0 :(得分:1)
items
处的fc-item-menu
绑定到fcDataList.actionButtons
。这意味着fc-item-menu
指令将在 scope.fcDataList.actionButtons 中查找它们。
让我们退一步 - 在你的fc-data-list
指令中,你有相同类型的绑定 - fcDataList.item
。这是有效的,因为您使用了bindToController
和controllerAs
,它将隔离的范围放在范围字段中,其名称在controllerAs
中定义( scope.fcDataList )。
返回fc-item-menu
:虽然指令中有 require:^ fcDataList ,但上面的表达式将是未定义的,因为不存在 scope.fcDataList 。此外,这是正确的,因为通过转换,已创建一个隔离的范围,该范围不包含 scope.fcDataList 。使其工作的方法是使用控制器中的值自己定义范围属性,如下所示:
function FcDataListItemLink(scope, elem, attrs, fcDataListCtrl) {
scope.buttons = fcDataListCtrl.actionButtons;
}
这是一个有效的plnkr:https://codepen.io/anon/pen/GNzELy