1

I am new to js. I have a big web app, potentially will have more than ten factories.

Here is my code. All the factory and service are in the same module

here is an example of factories

.factory('A', function(){
        return function A(){
           this.number;
           this._id= new Date().getTime();
           this.type = "A";
        };
    }).factory('B', function(){
        return function B(){
        this.type= "B";
        this.number;
        this._id= new Date().getTime();
        };
    })

And I have a service which creates new instance of factory object. the addUnit() function actually map to users click, so the type probably be A, probably be B. I know I can have functions for each of A and B, but because of the potential number of factories, i hope i could use only one creation function which takes type as a parameter and create new object according to the type.

   .service('myService', ['A','B',
    function(A, B){    
        this.addUnit = function(type) {
            console.log(typeof A);
            var myUnit = new window[type]({   //ERROR!!
                'number' : 3,
            });

            return myUnit;
        }

        addUnit("A");
}])

However, the console could print out typeof A is function, but i got an error window[type] is not a function.

SOLUTION: Thanks @Claies ' suggestion, updated my service as below and works!

    .service('myService', ['A','B',
         function(A, B){    
          var $injector = angular.injector(['moduleName','ng']);
            this.addUnit = function(type) {
                console.log(typeof A);
                var myUnitFunc = $injector.get(type);
                var myUnit = new myUnitFunc({
                  'number' : 3,
                });

                return myUnit;
            }

           addUnit("A");
    }])
Ting
  • 23
  • 7
  • 2
    your question isn't really clear. `typeOf A` and `typeOf "A"` aren't the same. one would be a function, the other a string. – Claies Sep 14 '15 at 14:21
  • @Claies sorry about the typo. updated – Ting Sep 14 '15 at 14:22
  • what is `window`? how is it supposed to relate to these factories? – Claies Sep 14 '15 at 14:29
  • @Claies Well... that is my question. I console typeof A just to make sure the dependency is correct. window["A"] is supposed to convert a string to a function, but it doesn't work for me..... – Ting Sep 14 '15 at 14:29
  • @Ting: In angularjs you can obtain a provider (service/factory) through dependency injection. If addUnit is defined inside a controller/service, you can inject A into that controller/service and you will be able to call functions on A. Can you provide the whole source/scope where addUnit is defined so we know what you want to achieve? – Ma3x Sep 14 '15 at 14:30
  • I've never seen this `window[type]` syntax before. – Claies Sep 14 '15 at 14:31
  • @Claies here is a ref http://stackoverflow.com/questions/496961/call-a-javascript-function-name-using-a-string – Ting Sep 14 '15 at 14:39
  • @Ma3x updated my code. all are in same module, – Ting Sep 14 '15 at 14:40
  • well that will never work in angular, since putting things in the global scope isn't recommended, and definitely cannot happen for angular objects like factories. I guess that's the reason I've never seen that used, since the global scope is such a bad practice. – Claies Sep 14 '15 at 14:41
  • @Claies all right. What is commanded to do if i want to convert a string to a function not in global scope.... – Ting Sep 14 '15 at 14:44
  • sorry the commands in my previous comment weren't complete and probably wouldn't have worked; you definitely need to use `$injector`, but I've never needed to do this before, so I don't know the exact syntax. – Claies Sep 14 '15 at 14:50
  • @Claies thx!!! it works!!!! – Ting Sep 14 '15 at 15:17
  • @Claies updated post why I do this..... if you have any suggestions, pls let me know. – Ting Sep 14 '15 at 15:17
  • since I removed the comment which didn't have the correct syntax, you should consider making a self answer showing the syntax you used, to help others in the future. – Claies Sep 14 '15 at 15:18

3 Answers3

1

You can use the $injector if you want to instantiate providers by their name (providing their name as a string).

.service('myService', ['$injector', function($injector) {

  this.addUnit = function(type) {

    var instance;

    if ($injector.has(type))
    {
      var typeConstructor = $injector.get(type);
      instance = new typeConstructor();
      instance.number = 3;
    }

    return instance;
  }

}])

Here is a working sample: http://plnkr.co/edit/t4ILB4CV11Lni8pLGQ9j

Ma3x
  • 5,761
  • 2
  • 17
  • 22
0

Use service not factory.

.service('A', function(){

And the later code is wrong. I even can't guess what were you going to do. There is only one instans of service/factory.

Qwertiy
  • 19,681
  • 15
  • 61
  • 128
0
.constant('A', function A(number) {
  this._id = Date.now();
  this.type = "A";
  this.number = number;
})
.constant('B', function B(number) {
  this._id = Date.now();
  this.type = "B";
  this.number = "number";
})

.service('myService', ['A', 'B', function (A, B) {
  var constructors = {A:A, B:B};

  this.addUnit = function (type) {
    var C = constructors[type];
    return C && new C(3);
  };
}]);
Qwertiy
  • 19,681
  • 15
  • 61
  • 128