参考plunker:http://plnkr.co/edit/otv5mVVQ36iPi3Mp0FYw?p=preview
假设我们有两个指令first-directive
和second-directive
。现在假设我们只能访问first-directive
,我们希望将second-directive
包裹起来并传递给我们自己的操纵属性。
app.directive('firstDirective', function() {
return {
scope: true,
priority: 1000,
transclude: true,
template: function(element,attributes){
console.log('template')
return '<second-directive two="{{one}}"></second-directive>'
},
compile: function(element,attributes) {
console.log('compile')
return {
pre: function(scope){
scope.one = 'foo'
console.log('cpre')
},
post: function(scope){
scope.one = 'foo'
console.log('cpost')
},
}
},
controller: ['$scope','$attrs',function($scope,$attrs){
console.log('controller');
$scope.one = 'foo';
}],
}
})
app.directive('secondDirective',function(){
return {
template: function (element,attributes){
console.log(attributes.two) //{{one}} not 'foo' or 'test'
return 'Hello {{two}}'
}
}
});
first-directive
的调用如下:
<first-directive one='test'></first-directive>
console.log输出如下:
template
compile
{{one}}
controller
cpre
cpost
因此我从中了解到在编译之前调用了模板。这是我新手眼中的特殊情况,因为无论如何都无法通过编译,控制器,前置或后置链接来操纵模板函数传回的值!
问题是:
如何使用我想要的动态属性值调用second-directive
?请注意,second-directive
完全独立,我们无法在那里添加代码。
PS - 我有一个可能的想法是按如下方式调用第二个指令:
template: function(element,attributes){
console.log('template')
var explicit = ???? /* how to access scope? */
return '<second-directive two="'+ explicit +'"></second-directive>'
},
或者
template: function(element,attributes){
console.log('template')
return $interpolate('<second-directive two="{{one}}"></second-directive>')(scopeObj) /* how does one access scopeObj with current scope values here? */
},
然而,再次,我不确定如何在调用任何其他函数之前将值传递给first-directive。 Controller可以访问$ scope,它被称为AFTER模板。
您的建议非常感谢。
答案 0 :(得分:0)
您是否写过第二条指令?
<second-directive two="'+ explicit +'"></second-directive>
要使上述代码正常工作,您需要在第二个指令中设置隔离范围对象,请查看下面的插件。
答案 1 :(得分:0)
我正在使用你的问题来学习,但我能找到这个,这对你有用:
app.directive("tryThis", function($compile){
return{
scope: {
one: '@',
},
link: function(scope, element){
var template = '<second-directive two="'+scope.one+'"></second-directive>';
var linkFn = $compile(template);
var content = linkFn(scope);
element.append(content);
}
}
});
Plunkr为here,请注意,控制台现在会记录test
而不是{{one}}
。如果secondDirective被赋予隔离范围,则test
将显示在屏幕上。
这个link也帮助我从概念上理解了你所面临的问题,给出了“编译期间没有范围”这一问题的一些背景 - 我不确定是否有办法解决这个问题。
答案 2 :(得分:0)
如果您只想将第一个指令中的数据传递给第二个指令模板,那么您可以使用
在第一个指令控制器中添加动力学属性
this.fromFirstDir =“你可以从这里传递”
第一个指令控制器:
controller: ['$scope','$attrs',function($scope,$attrs){
console.log('controller');
$scope.one = 'foo';
this.fromFirstDir = "you can pass from here"
}],
}
然后使用 secondDirective 中的 require 属性作为第一个指令控制器,您可以从 secondDirective 指令的链接功能访问此动态属性使用控制器传递给链接功能。最后将这些属性分配给传递给链接函数的本地范围。
app.directive('secondDirective',function(){
return {
scope: {twoData : '@twoData'},
require : '^firstDirective',
template: function (element,attributes){
console.log(attributes.two) //{{one}} not 'foo' or 'test'
return 'Hello <b>{{fromFirstDir}}</b>'
},
link : function(scope,element,attr,firstDirCtrl){
console.log("===",firstDirCtrl.fromFirstDir)
scope.fromFirstDir = firstDirCtrl.fromFirstDir;
}
}
});
通过这种方式,您的第二个指令可以使用这些动态属性。
这是最后的fiddle。
希望这会对你有所帮助。
答案 3 :(得分:0)
您不能(不能)访问模板内的范围(因为此时没有范围)。该模板用于创建一个或多个元素,然后将它们链接到一个范围(在实例化其控制器之后 - 如果有的话)。
有很多方法可以在指令之间传递值,每种方法最适合特定用途。最简单的(但不一定是最好的,取决于你的用例细节)是在wrapper指令的作用域上赋值,让内部指令从作用域读取它:
<!-- HTML -->
<one for-two="{{test}}"></one>
// JS
angular.
module('myApp', []).
directive('one', oneDirective).
directive('two', twoDirective);
function oneDirective() {
return {
restrict: 'E',
scope: true,
link: function onePostLink(scope, elem, attrs) {
scope.two = attrs.forTwo;
},
template: '<two></two>'
};
}
function twoDirective() {
return {
restrict: 'E',
template: 'Hello, {{two}} !'
};
}
答案 4 :(得分:0)
您有transclude: true
但未在模板中使用它。你不能只使用这个标记并使用第一个指令的模板<ng-transclude>
吗?你有scope: true
所以你可以从父/控制器中操作属性,并且更改将传播到两个指令。
标记
<first-directive one="test">
<second-directive two="test"></second-directive>
</first-directive>
第一指令的模板
template: `<div>
my first directive content
<ng-transclude></ng-transclude>
</div>`;