Javascript 在模板中非法使用NGTRANCLUDE指令!手动进行转换时

Javascript 在模板中非法使用NGTRANCLUDE指令!手动进行转换时,javascript,angularjs,angularjs-directive,angularjs-ng-transclude,Javascript,Angularjs,Angularjs Directive,Angularjs Ng Transclude,我很谨慎地问,是否可以在指令模板中两次屏蔽指令的内部内容(克隆指令并将其插入模板中的两个位置) 一个非常乐于助人的人帮我把这个东西组装起来 一开始似乎很管用。当我使用任何使用转换本身的子元素时,问题就来了。我得到的错误是 [ngTransclude:orphan]在模板中非法使用ngTransclude指令!未找到需要转换的父指令。元素: 例如,我有一个按钮指令,其定义如下 angular.module('s4p.directives').directive('s4pButton', func

我很谨慎地问,是否可以在指令模板中两次屏蔽指令的内部内容(克隆指令并将其插入模板中的两个位置)

一个非常乐于助人的人帮我把这个东西组装起来

一开始似乎很管用。当我使用任何使用转换本身的子元素时,问题就来了。我得到的错误是

[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>';
    }

});
angular.module('s4p.directives')。directive('s4pButton',function(){
返回{
限制:'E',
范围:{
图标:“@”
},
是的,
替换:正确,
模板:getTemplate
};
函数getTemplate(元素,属性){
var btnType=(typeof attr.type==‘未定义’?‘按钮’:attr.type;
返回“”+
''+
''+
''+
''+
'';
}
});
当我把我的一个按钮放在工具栏中,它试图克隆它时,我得到了上面的错误

编辑:

带有完整示例的新PLUNKR


任何帮助都将不胜感激。

实际错误不是来自转换,而是来自模板属性。从您提供的代码中,您只需要做一些小的更改就可以使其正常工作(您为模板属性分配了一个函数,而没有调用它)

虽然这可能会解决您的问题,但我建议将模板移动到单独的html文件中,而不要将其内联。调试和扩展内联HTML非常困难。

问题代码 该指令试图在一次调用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));
    });
}
正确代码 要将指令内容转换到模板中的两个位置,请调用转换函数两次

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);
            });
        }
    };
});
有关创建新作用域的详细信息,请参阅


使用AngularJS jqLite AngularJS jqLite是jQuery的一个很小的、与API兼容的子集,它允许Angular以跨浏览器兼容的方式操作DOM。jqLite只实现最常用的功能,目标是占用很小的空间

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);
            });
        }
    };
});
app.directive('toolbar',function($compile){
返回{
限制:'E',
作用域:{},
转移:{},
模板:
'' +
'',
//修正码
链接:功能(范围、元素、属性、控制器、转置){
转移(范围、功能(克隆){
元素。查找('my-main')。替换为(克隆);
});
转移(范围、功能(克隆){
元素。查找('my-overflow')。替换为(克隆);
});
}
};
});

这样就不需要将jQuery作为依赖项添加到应用程序中。

demo没有反映问题抱歉,已使用新的Plunkr更新。如果我这样做,恐怕模板无法工作。我从ngMaterial库中复制了这段代码,所以我确信它是正确的。不管怎样,谢谢你,搞定了。谢谢你,很高兴它对你有用。我在答案中添加了一个关于使用AngularJS jqLite的部分。
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);
            });
        }
    };
});
var newScope = scope.$new();
transclude(newScope, function(clone) {
    element.find('[transclude-main]').replaceWith(clone);
});
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);
            });
        }
    };
});