2013-08-26 11 views
6

Mam dwie/więcej usług z tym samym podpisem. Czy mogę dynamicznie wtrysnąć do dyrektywy? coś jak poniżejUsługa wtrysku/zakład do dyrektywy

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; 
     } 
    } 
}); 

Wtedy muszę być w stanie użyć dyrektywy jak poniżej

<div class='change-it' data='myData'>{{name}}</div> 
<div class='change-it' data='yourData'>{{name}}</div> 

będę dodając więcej usług z tym samym podpisem i powinny być w stanie użyć dyrektywy bez zmiany, Czy to możliwe?

Odpowiedz

13

To niemożliwe w ten sposób. Najlepsze co możesz zrobić, to wiążą się z zakresu dyrektywy na funkcję jej zakres dominującej, która zwraca instancję usługi:

app.directive('changeIt', function(){ 
    return { 
    restrict: 'CA', 
    scope: { getDataFn : '&' }, 
    link: function (scope) { 
     scope.name = getDataFn().name; 
    } 
    } 
});  

a następnie w widoku:

<div class='change-it' get-data-fn='getMyData()'></div> 
<div class='change-it' get-data-fn='getYourData()'></div> 

Wreszcie, trzeba dodać getMyData() i getYourData() zakresu dominującej:

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

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

Plunker skrypt here.

Mogę wymyślić inne podejście: możesz stworzyć abstrakcyjną fabrykę i wprowadzić ją do dyrektywy, a następnie przekazać parametr do dyrektywy, aby mógł powiedzieć abstrakcyjnej fabryce, aby utworzyła poprawną usługę. Coś takiego:

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; 
    } 
    } 
}); 

A teraz trzeba przekazać typ do dyrektywy:

<div class='change-it' type="myData"></div> 
<div class='change-it' type="yourData"></div> 

Plunker here.

+0

Oba podejścia dobrze wyglądać naprawdę. – Murali

+0

Myślę, że jesteś w stanie zdefiniować prosty kontroler, który wykonuje datakall i przekazuje go do dyrektywy za pomocą ng-controller = "YourCtrl" –

+0

Naprawdę pomocne. Dzięki! –

9

Oto rozwiązanie bez potrzeby kontrolera nadrzędnego lub fabryki fabryk.

w dyrektywie, wstrzyknąć $ wtryskiwacz usługę pobierać instancję fabryczny:

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

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

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

Wskazówka to się dzieje w metodzie kontrolera. Nie mogłem wykonać funkcji $ injector.get() w funkcji łączenia.

Szablon:

<div class='change-it' factory-name="myData"> {{ name }} </div> 
<div class='change-it' factory-name="yourData"> {{ name }} </div> 

- Edit -

Roztwór roboczy wewnątrz funkcji Link:

app.directive('changeIt',function(){ 
      return { 
       scope:{ 
        factoryName : '@' 
       }, 
       link: function (scope, element) { 

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

        scope.name = factoryInstance.name; 
       } 
      } 
     }); 
Powiązane problemy