Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Injecting service/factory to directive

I have two/more services with same signature. Can I dynamically inject then into the 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 as below

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

I would be adding more services with the same signature and I should be able to use the directive without changing, is it possible?

like image 644
Murali Avatar asked Aug 26 '13 01:08

Murali


People also ask

Can we inject service in directive in angular?

The config method accepts a function, which can be injected with "providers" and "constants" as dependencies. Note that you cannot inject "services" or "values" into configuration. The provider method can only be injected with other "providers".

What is the difference between a service () and a factory ()?

factory() is a method that takes a name and function that are injected in the same way as in service. The major difference between an AngularJS service and an AngularJS factory is that a service is a constructor function and a factory is not.

Which components can be injected as dependency in AngularJS?

26) Which of the following components can be injected as a dependency in AngularJS? Answer: D is the correct answer. The "Application Module" can be injected as a dependency in AngularJS.

What is $inject in AngularJS?

$injector is used to retrieve object instances as defined by provider, instantiate types, invoke methods, and load modules.


1 Answers

That's not possible that way. The best you can do is bind the directive scope to a function of its parent scope that 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 view:

<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 think of another approach, though: you could create an abstract factory and inject it into the directive, and then pass a parameter to the directive so it could tell the abstract factory to create the correct service. Something like this:

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 here.

like image 137
Michael Benford Avatar answered Nov 08 '22 19:11

Michael Benford