6

我有两个/多个具有相同签名的服务。我可以动态地注入指令吗?像下面的东西

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>

我将添加更多具有相同签名的服务,并且我应该能够在不更改的情况下使用该指令,这可能吗?

4

2 回答 2

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()and添加getYourData()到父范围:

app.controller('Ctrl', function($scope, myData, yourData) {
  $scope.getMyData = function() {
    return myData;
  };

  $scope.getYourData = function() {
    return yourData; 
  };
});

Plunker 脚本在这里

不过,我可以想到另一种方法:您可以创建一个抽象工厂并将其注入指令中,然后将参数传递给指令,以便它可以告诉抽象工厂创建正确的服务。像这样的东西:

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在这里

于 2013-08-26T03:45:52.747 回答
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;
                }
            }
        }); 
于 2014-03-26T11:44:04.970 回答