在模板中非法使用 ngTransclude 指令!手动执行嵌入时
Illegal use of ngTransclude directive in the template! when doing transclusion manually
我在SO上询问是否可以在指令模板中两次排除指令的内部内容(克隆它并将其插入模板中的两个位置)。
一个非常乐于助人的人帮我把这个 plunkr 放在一起。
http://plnkr.co/edit/k2UB1o4CTHtZ1voS0OKN?p=preview
起初似乎有效。当我使用任何使用嵌入本身的子元素时,问题就来了。我得到的错误是...
[ngTransclude:orphan] 在模板中非法使用 ngTransclude 指令!未找到需要嵌入的父指令。元素:
例如,我有一个具有以下定义的按钮指令。
angular.module('s4p.directives').directive('s4pButton', function () {
return {
restrict: 'E',
scope: {
icon: '@'
},
transclude: true,
replace: true,
template: getTemplate
};
function getTemplate(element, attr) {
var btnType = (typeof attr.type === 'undefined') ? 'button' : attr.type;
return '<button s4p-button type="' + btnType + '">'+
'<s4p-button-content ng-transclude></s4p-button-content>'+
'<s4p-button-icon ng-if="icon">'+
'<s4p-icon href="{{icon}}"></s4p-icon>'+
'</s4p-button-icon>'+
'</button>';
}
});
一旦我将一个按钮放在工具栏中并尝试克隆它,我就会收到上述错误。
编辑:
带有完整示例的新 PLUNKR
http://plnkr.co/edit/uK8r4EA2IPRnYKfjWNVG?p=preview
任何帮助将不胜感激。
问题代码
该指令试图在一次调用 transclude 函数时执行双重嵌入。
//PROBLEM Code
link: function(scope, element, attrs, controller, transclude) {
transclude(function(clone, scope) {
element.find('[transclude-main]').replaceWith(clone);
element.find('[transclude-overflow]').replaceWith($compile(clone.clone())(scope));
});
}
正确的代码
若要将指令内容嵌入到模板中的两个位置,请调用 transclusion 函数两次。
app.directive('toolbar', function($compile) {
return {
restrict: 'E',
scope: {},
transclude: {
},
template:
'<toolbar-main><div transclude-main></div></toolbar-main>' +
'<toolbar-overflow><div transclude-overflow></div></toolbar-overflow>',
//CORRECTED code
link: function(scope, element, attrs, controller, transclude) {
transclude(scope, function(clone) {
element.find('[transclude-main]').replaceWith(clone);
});
transclude(scope, function(clone) {
element.find('[transclude-overflow]').replaceWith(clone);
});
}
};
});
如果需要新的范围进行嵌入,可以使用 scope.$new()
创建它们。
var newScope = scope.$new();
transclude(newScope, function(clone) {
element.find('[transclude-main]').replaceWith(clone);
});
有关创建新作用域的详细信息,请参阅 AngularJS $rootScope.scope API 参考 -- $new。
使用 AngularJS jqLite
AngularJS jqLite 是 jQuery 的一个微小的、与 API 兼容的子集,它允许 Angular 以跨浏览器兼容的方式操作 DOM。 jqLite 只实现最常用的功能,目标是占用空间非常小。1
jqLite 的find
方法不支持属性选择器。要使上面的示例与 jqLite 兼容,对嵌入目标使用自定义标记。
app.directive('toolbar', function($compile) {
return {
restrict: 'E',
scope: {},
transclude: {},
template:
'<toolbar-main><my-main></my-main></toolbar-main>' +
'<toolbar-overflow><my-overflow></my-overflow></toolbar-overflow>',
//CORRECTED code
link: function(scope, element, attrs, controller, transclude) {
transclude(scope, function(clone) {
element.find('my-main').replaceWith(clone);
});
transclude(scope, function(clone) {
element.find('my-overflow').replaceWith(clone);
});
}
};
});
这样就不需要将jQuery作为依赖项添加到应用程序中。
实际错误不是来自嵌入,而是来自模板属性。从您提供的代码段中,您只需要进行一个小的更改即可使其工作(您为模板属性分配了一个函数而不调用它)
从
template: getTemplate
自
template: getTemplate()
虽然这可能会解决您的问题,但我建议将您的模板移动到单独的 html 文件中,而不是保持内联。调试和扩展内联 HTML 非常困难。
- 通过指令在控制器中执行javascript函数
- AngularJS执行指令模板中的控制器函数
- 我的指令在ngRepeat和ngInclude之前执行,尽管默认优先级为0
- Angular 指令似乎没有使用元素传入的选项执行
- 在不使用隔离作用域的情况下执行函数的角度指令
- 就绪函数上的指令只能执行一次
- 隔离范围-仅在指令范围内定义的值必须执行更改
- 验证指令代码在ng重复中的每个项目上执行
- AngularJS指令不是每次都执行
- 如何在路由更改后停止 setInterval 函数在角度指令上执行
- ng 类指令调用执行两次
- angularJS在内存中执行指令并获取innerHTML
- 如何确保在执行指令之前解决工厂承诺
- Yeoman Angularjs如何执行指令
- 范围更改不会;t执行指令中的代码
- node . js /套接字.Io /express执行指令
- 在控制器前执行指令代码
- Angular测试不执行指令代码
- 执行指令的参数's的链接功能依赖于DI
- 如何在AngularJS模板被评估后执行指令逻辑