我正在学习angularjs,我正在训练如何构建一个可重用的指令。
问题是它适用于包含1个元素但不包含2个或更多元素的数组。
html标记只是:<breadcrumb></breadcrumb>
,以防万一,按预期呈现。但是,我需要手动执行“替换:true”会做什么。
错误是:父级为空。
我用尽所有谷歌搜索寻找一个例子。
但是我的情况很奇怪,因为<inner ng-repeat>
里面有<breadcrumb>
这是另一个内部指令而不是普通标签,这就是为什么替换不起作用而我需要手动完成的原因。
存在与“动态模板加载...”相关的问题
obs:我试着在“link:”和“compile:”逻辑中做同样的错误......
[编辑]
我可以使代码有效,但是,我无法删除<inner>
代码,因为transclude
会自动执行。
现在输出几乎是完美的,只需删除<inner>
但现在没有运气,我试图替换元素标签,仍然没有运气。
<ul class="breadcrumb">
<!-- I want to remove this <inner> and leave <li> alone! -->
<inner data-ng-repeat="_item in items track by $index" class="ng-scope">
<li class="ng-scope"><a href="#" class="ng-binding">1</a>
</li>
</inner>
<!-- remove for clarity -->
</ul>
var myModule = angular.module("myModule", []);
myModule.directive('breadcrumb', function($timeout) {
"use strict";
var directiveDefinitionObject = {
template: '<ul class="breadcrumb"><inner data-ng-repeat="_item in items track by $index"></inner></ul>',
replace: true,
// transclude: true,
restrict: 'E',
scope: {},
controller: ["$scope", "$element", "$attrs", "$transclude", controller],
link: ["scope", "iElement", "iAttrs", link]
};
function link(scope, iElement, iAttrs) {
scope.addNewItem = function(new_item) {
scope._push(new_item);
}
}
function controller($scope, $element, $attrs, $transclude) {
$scope.items = [1, 2, 3, 4, 5];
$scope._push = function(item) {
$scope.items.push(item);
};
$scope._pop = function() {
$scope.items.pop();
};
$scope.is_last = function(item) {
return $scope.items.indexOf(item) == ($scope.items.length - 1);
}
}
return directiveDefinitionObject;
});
myModule.directive("inner", ["$compile",
function($compile) {
"use strict";
function getItemTemplate(index) {
return '<li><a href="#">{{ _item }}</a></li>';
}
return {
require: "^breadcrumb",
restrict: "E",
compile: function compile(tElement, tAttrs)
{
return function postLink(scope, iElement, iAttrs)
{
iElement.html(getItemTemplate(0));
$compile(iElement.contents())(scope);
};
}
};
}
]);
答案 0 :(得分:2)
您可以在inner
指令中删除您的编译功能并设置replace: true
,因为它只是模仿replace
的默认行为,如您所述。所以你inner
指令将成为:
myModule.directive("inner", ["$compile",
function($compile) {
"use strict";
return {
replace: true
require: "^breadcrumb",
restrict: "E",
template: '<li><a href="#">{{ _item }}</a></li>'
};
}
]);
但是您遇到的问题是items
数组已定义到breadcrumb
指令中,出现了什么问题,并且不允许您将其重复使用。你可以用scope
定义将它绑定到这样的东西:
<breadcrumb items="someItemsArrayFromParentScope"></breadcrumb>
...directive('breadcrumb', function() {
...
return {
...
scope: {
items: '='
}
}
});
这将在父节点和内部小部件范围的数组之间创建双向绑定。但进一步说,您可能希望让用户定义breadcrumb
的内部元素,它将如下所示:
myModule.directive('breadcrumb', function($timeout) {
var directiveDefinitionObject = {
template: '<ul class="breadcrumb" ng-transclude></ul>',
replace: true,
transclude: true,
restrict: 'E',
scope: {},
controller: ["$scope", "$element", "$attrs", "$transclude", controller]
};
function controller($scope, $element, $attrs, $transclude) {
$scope.addNewItem = function(new_item) {
$scope._push(new_item);
}
$scope._push = function(item) {
$scope.items.push(item);
};
$scope._pop = function() {
$scope.items.pop();
};
$scope.is_last = function(item) {
return $scope.items.indexOf(item) == ($scope.items.length - 1);
}
}
return directiveDefinitionObject;
});
myModule.directive("inner", function($compile) {
return {
require: "^breadcrumb",
restrict: "E",
template: '<li><a href="#" ng-transclude></a></li>',
replace: true,
transclude: true
};
}
);
在你的HTML中,你会来:
<breadcrumb>
<inner ng-repeat="item in items"><i>{{item}}</i></inner>
</breacrumb>
技巧是模板中的ng-transclude
指令。它只是获取元素的内容并将其“移动”到标有ng-transclude
的元素内,并将其链接到父作用域,这很棒,因为您可以对基于的项目进行动态命名父范围。例如,items
的{{1}}将按预期在父作用域中定义。这是首选方式,您甚至可以使用不同的内部模板(就像我使用ng-repeat
标记一样)。如果是这种情况,您甚至可以不使用<i>
并对ng-repeat
元素进行硬编码:
inner
这是一个有效的Plnker。
答案 1 :(得分:0)
我能够重建它。
完整代码在此处:http://plnkr.co/ZQOHqao8aqksbVjGQTHj
自从我第一次尝试以来,我学到了很多东西。
解决方案被简化,因为动态模板是垃圾来处理,因为ng-repeat不会重新绘制整个数组。所以,我是按照自己的方式做到的,这是一个干净的解决方案。