2013-08-26 15 views
6

Ho due/più servizi con la stessa firma. Posso quindi iniettare dinamicamente nella direttiva? qualcosa di simile sottoIniezione servizio/fabbrica alla direttiva

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

allora dovrei essere in grado di utilizzare la direttiva, come di seguito

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

avrei l'aggiunta di più servizi con la stessa firma e dovrei essere in grado di utilizzare la direttiva senza cambiare, È possibile?

risposta

13

Non è possibile in questo modo. Il meglio che puoi fare è associare il campo di applicazione della direttiva a una funzione della sua portata genitore che restituisce un'istanza del servizio:

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

e quindi a suo avviso:

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

Infine, è necessario aggiungi getMyData() e getYourData() al campo di applicazione genitore:

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

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

Plunker sceneggiatura here.

Tuttavia, posso pensare ad un altro approccio: è possibile creare una fabbrica astratta e inserirla nella direttiva, quindi passare un parametro alla direttiva in modo che possa dire al factory astratto di creare il servizio corretto. Qualcosa di simile a questo:

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

E ora è necessario passare il tipo della direttiva:

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

Plunker here.

+0

Entrambi gli approcci guardare bene davvero. – Murali

+0

Penso che tu sia in grado di definire un semplice controller che esegue il datacall e lo passa alla direttiva usando ng-controller = "YourCtrl" –

+0

Davvero utile. Grazie! –

9

Ecco una soluzione senza la necessità di un controller padre o una fabbrica di fabbriche.

Nella direttiva, iniettare il $ servizio di iniettore per recuperare l'istanza di fabbrica:

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

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

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

Avviso sta accadendo nel metodo di controllo. Non riesco a far funzionare $ injector.get() nella funzione link.

Template:

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

- Modifica -

Soluzione di lavoro all'interno della funzione di collegamento:

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

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

        scope.name = factoryInstance.name; 
       } 
      } 
     }); 
Problemi correlati