我试图执行以下操作:
如果我添加<my-custom-directive></<my-custom-directive>
它应该扩展到
<div class="my-custom-container">
<label class="my-custom-label">Fallback</label>
<input class="my-custom-input"/>
</div>
可以通过在DDO中将上述内容设置为template
和replace:true
来完成。
如果我在HTML中添加以下内容:
<my-custom-directive>
<my-custom-label class="users-custom-class"><span>Custom content</span><my-custom-label>
</<my-custom-directive>
它应该扩展到
<div class="my-custom-container">
<label class="my-custom-label users-custom-class"><span>Custom content</span></label>
<input class="my-custom-input"/>
</div>
这意味着如果用户想要提供自定义<label>
,<input>
等,我们会使用翻译,并且已转换的内容会替换原始模板中的相应广告位,类似于replace:true
的方式指令将用它的模板替换自己。
我无法合并replace
和翻译功能。
我到目前为止(某些工作状态)的内容如下:
angular.module('test', [])
.directive('transTest', function() {
return {
transclude: {
lab: '?labelTest',
inp: '?inputTest'
},
replace: true,
template: '<div class="container"><label ng-transclude="lab">Fallbacl label</label><input type="text" placeholder="fallback" ng-transclude="inp"></div>',
link: function(scope, element, attrs, ctrl, transclude) {
console.log(transclude())
}
}
});
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.2/angular.js"></script>
<div ng-app="test">
<div trans-test class="test">
<label-test>test label</label-test>
<input-test>test input</input-test>
</div>
</div>
&#13;
如您所见,已转换的内容位于包含translude的元素内,而不是替换它。我已阅读source code comments文章,并检查了ui-bootstrap-accordion的实施情况,并尝试了transclude:'element'
的运气,但它在DOM中没有留下任何内容,只留下评论。
transclusion,replace等是我发现的可用选项,它提供的功能类似于我想要实现的功能。但他们似乎并不能很好地发挥作用。如果可能的话,在角度中实现这种功能的正确方法是什么??
答案 0 :(得分:5)
看来我终于成功了。解决方案由两部分组成:
使用类似于回退的模板定义transclude-slot元素的指令(默认)。
这样做的主要原因是在DDO中设置replace:true
时,利用angular的内置功能将属性复制到模板根元素。我不想在链接功能中手动完成。
另一个原因是它允许您添加其他功能,例如默认模板
第二步是在模板中不定义 ng-transclude
指令,而是使用传递给transclude
的{{1}}函数来访问被转换的各种广告位的内容,并将相应的元素替换为已转换的内容(如果存在)(使用link
)
嗯,这并不容易让我明白,也不容易解释。希望下面的演示比单词解释它更好:
transclude.isSlotFilled()
angular.module('test', [])
.directive('transTest', function() {
return {
replace: true,
transclude: {
lab: '?labelTest',
inp: '?inputTest'
},
template: '<div class="test-parent"><label class="fallback-label">Fallback </label><br><input type="text" class="fallback-input"></div>',
link: function(scope, element, attrs, ctrl, transclude) {
if (transclude.isSlotFilled('lab')) {
var label = transclude(angular.noop, null, 'lab');
element.find('label').replaceWith(label);
}
if (transclude.isSlotFilled('inp')) {
var input = transclude(angular.noop, null, 'inp');
element.find('input').replaceWith(input);
}
}
}
}).directive('labelTest', function($compile) {
return {
template: '<label class="fallback-label ng-transclude">Fallback </label>',
replace: true,
transclude: true
}
}).directive('inputTest', function($compile) {
return {
template: '<input type="text" class="fallback-input">',
replace: true
}
});
答案 1 :(得分:3)
您可能正在寻找更优雅的解决方案,但您可以使用指令的控制器$transclude
功能转到find out if a transclusion-slot
has been filled。
controller: function($transclude, $scope) {
$scope.fallback = !$transclude.isSlotFilled('lab');
然后,使用该信息来构建模板。
template: '<div class="container">\
<label ng-if="fallback === true">Fallback label</label>\
<div ng-if="fallback === false" ng-transclude="lab"></div>\
但是,如果您可以完全定义要转换的内容,
<label-test>
<label>test label</label>
</label-test>
替换目标内容可能更有意义 - 而不是整个元素:
template: '<div class="container">\
<div ng-transclude="lab">\
<label>Fallback label</label>\
</div>\
这是一个显示两种方法的plunker:http://plnkr.co/edit/EEq5vovFrSW7kG81yWuf?p=preview