Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AngularJS - module dependencies, naming clash

I have two third-party modules, both defining a factory with the same name. Obviously, I don't have any control over the naming of those modules without resorting to a kludge.

Additionally, I have two further, internal modules, each using a different one of the two third-party modules as a dependency (as below). I was sure that I was unable to access components from a module not listed in current module's dependencies, but it turned out I was wrong.

Here even if own1 depends on thirdParty1 (which has hello defined as hello world) it's getting hi there (from thirdParty2) in controller. The same is for the other modules' pair.

Is there any way to "isolate" modules so I can only use stuff that I explicitly depend on? If not, what's the point of having modules if I can reach anything at any time (assuming main app module has it as its dependency)? Also if I have two modules with components named hello how can I tell which is gonna be used?

Here is jsbin for that http://jsbin.com/vapuye/3/edit?html,js,output

angular.module('app', ['own1', 'own2']);

//third-party modules
angular.module('thirdParty1', []).factory('hello', function () {
  return 'hello world';
});

angular.module('thirdParty2', []).factory('hello', function () {
  return 'hi there';
});

// "own" modules
angular.module('own1', ['thirdParty1']).controller('Own1Ctrl', function(hello) {
  this.greet = hello;
});

angular.module('own2', ['thirdParty2']).controller('Own2Ctrl', function(hello) {
  this.greet = hello;
});

And the result of:

<body ng-app="app">
  <div ng-controller="Own1Ctrl as own1">
    Own1: {{ own1.greet }}
  </div>
  <div ng-controller="Own2Ctrl as own2">
    Own2: {{ own2.greet }}
  </div>
</body>

Is :

Own1: hi there
Own2: hi there
like image 259
Michal Ostruszka Avatar asked May 21 '15 13:05

Michal Ostruszka


2 Answers

You can request a factory of a certain module explicitly (without dependency injection):

var injector = angular.injector(['thirdParty1']);
var hello1 = injector.get('hello');

var injector = angular.injector(['thirdParty2']);
var hello2 = injector.get('hello');

You can also use this, to wrap the third party factories into own factories:

angular.module('own1', ['thirdParty1']).factory('hello1', function () {
  var injector = angular.injector(['thirdParty1']);
  var hello = injector.get('hello');
  return hello;
});

angular.module('own2', ['thirdParty2']).factory('hello2', function () {
  var injector = angular.injector(['thirdParty2']);
  var hello = injector.get('hello');
  return hello;
});

This allows you to use hello1 and hello2 in all other parts of your application.

like image 90
basilikum Avatar answered Nov 15 '22 21:11

basilikum


Since there is no built-in name spacing of modules (or components of modules) the best way to achieve your goal is to use a unique naming convention for your modules. Most libraries for angular do this, and then you should be good to go.

Besides encapsulating your applications behavior, modules help testing and mocking your application.

I dont think it is possible for angular to differentiate between two components that are named the same (I think this changes with angular 2). And I might argue that two components that are named the same might do the same and you should look why you need both?

like image 28
Jonathan Avatar answered Nov 15 '22 22:11

Jonathan