2013-08-26 57 views
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> 

我會用相同的簽名來添加更多的服務,我應該能夠使用該指令不改變,可能嗎?

回答

13

這是不可能的。你能做的最好的是指令範圍綁定到它的父作用域的函數,返回你的服務的一個實例:

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

+0

這兩個方法很好看真。 – Murali

+0

我想你可以定義一個簡單的控制器來執行datacall並將它傳遞給指令使用ng-controller =「YourCtrl」 –

+0

真的很有幫助。謝謝! –

9

這是一個不需要父控制器或工廠工廠的解決方案。

在該指令,注入$注射器服務檢索工廠實例:

app.directive('changeIt',function(){ 
     return { 
      scope:{ 
       factoryName : '@' 
      }, 
      controller: function ($scope, $injector) { 

       var factoryInstance = $injector.get($scope.factoryName); 

       $scope.name = factoryInstance.name; 
      } 
     } 
    }); 

注意它的發生在控制器方法。我無法使$ inject.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; 
       } 
      } 
     });