我有两个/更多具有相同签名的服务。我可以动态注入到指令中吗?类似下面的内容
var app = angular.module('app',[]);
app.factory('myData', function(){
return {
name : "myName",
id : 1,
create: function(){
//do something
}
}
});
app.factory('yourData', function(){
return {
name : "yourName",
id : 1,
create: function(){
//do something
}
}
});
app.directive('changeIt',function($compile){
return {
restrict: 'CA',
scope:{
data : '=' //or some oether syntax?
},
link: function (scope, element, attrs) {
scope.name = data.name;
}
}
});
然后我应该能够使用下面的指令
<div class='change-it' data='myData'>{{name}}</div>
<div class='change-it' data='yourData'>{{name}}</div>
我会添加更多具有相同签名的服务,我应该能够在不改变的情况下使用该指令,是否可能?
答案 0 :(得分:14)
那是不可能的。您可以做的最好的事情是将指令范围绑定到其父范围的函数,该范围返回您的服务实例:
app.directive('changeIt', function(){
return {
restrict: 'CA',
scope: { getDataFn : '&' },
link: function (scope) {
scope.name = getDataFn().name;
}
}
});
然后在你看来:
<div class='change-it' get-data-fn='getMyData()'></div>
<div class='change-it' get-data-fn='getYourData()'></div>
最后,您需要将getMyData()
和getYourData()
添加到父作用域:
app.controller('Ctrl', function($scope, myData, yourData) {
$scope.getMyData = function() {
return myData;
};
$scope.getYourData = function() {
return yourData;
};
});
Plunker脚本here。
我可以想到另一种方法:您可以创建一个抽象工厂并将其注入到指令中,然后将参数传递给指令,以便它可以告诉抽象工厂创建正确的服务。像这样:
app.service('dataFactory', function(myData, yourData) {
this.create = function(type) {
if (type === 'myData')
return myData;
else if (type === 'yourData')
return yourData;
};
});
app.directive('changeIt', function(dataFactory){
return {
restrict: 'CA',
scope: true ,
link: function (scope, element, attrs) {
scope.name = dataFactory.create(attrs.type).name;
}
}
});
现在你需要将类型传递给指令:
<div class='change-it' type="myData"></div>
<div class='change-it' type="yourData"></div>
Plunker here。
答案 1 :(得分:10)
这是一个解决方案,无需父控制器或工厂工厂。
在指令中,注入 $ injector 服务以检索工厂实例:
app.directive('changeIt',function(){
return {
scope:{
factoryName : '@'
},
controller: function ($scope, $injector) {
var factoryInstance = $injector.get($scope.factoryName);
$scope.name = factoryInstance.name;
}
}
});
请注意,它正在控制器方法中发生。我无法使$ injector.get()在链接函数中工作。
模板:
<div class='change-it' factory-name="myData"> {{ name }} </div>
<div class='change-it' factory-name="yourData"> {{ name }} </div>
- 编辑 -
链接功能中的工作解决方案:
app.directive('changeIt',function(){
return {
scope:{
factoryName : '@'
},
link: function (scope, element) {
var factoryInstance = element.injector().get(scope.factoryName);
scope.name = factoryInstance.name;
}
}
});