Engineering / factory for directive

I have two more services with the same signature. Can I insert dynamically into a directive? something like below

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

Then I should be able to use the directive below

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

I would add more services with the same signature, and I could use the directive without changing, is this possible?

+6
source share
2 answers

It's impossible. The best you can do is associate the scope of the directive with the function of the parent scope, which returns an instance of your service:

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

and then, in your opinion:

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

Finally, you need to add getMyData() and getYourData() to the parent scope:

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

Plunker script here .

I can come up with another approach: you can create an abstract factory and enter it into a directive, and then pass the parameter to the directive so that it can tell the abstract factory to create the correct service. Something like that:

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

And now you need to pass the type to the directive:

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

Plunker is here .

+13
source

Here is a solution that does not require a parent controller or factory factories.

In the directive, insert the $ injector service to get a factory instance:

 app.directive('changeIt',function(){ return { scope:{ factoryName : '@' }, controller: function ($scope, $injector) { var factoryInstance = $injector.get($scope.factoryName); $scope.name = factoryInstance.name; } } }); 

Note that this happens in the controller method. I could not get $ injector.get () to work in the link function.

Template:

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

- Change -

A working solution within the link function:

  app.directive('changeIt',function(){ return { scope:{ factoryName : '@' }, link: function (scope, element) { var factoryInstance = element.injector().get(scope.factoryName); scope.name = factoryInstance.name; } } }); 
+9
source

Source: https://habr.com/ru/post/952471/


All Articles