see dependency tree for module/factory in angular - angularjs

Here's the problem. I have a someModuleA that has access to theFactoryOfInterestX:
angular.module('someModuleA', ['someModuleB', 'someModuleC', ... /*someModuleZ not here*/])
.controller('controllerFromA', ['theFactoryOfInterestX', , function(theFactoryOfInterestX) {
console.log(theFactoryOfInterestX); // that factory is available here
}]);
I know for a fact that theFactoryOfInterestX is only defined in someModuleZ:
angular.module('someModuleA', [/*stuff*/])
.factory('theFactoryOfInterestX', [function() { /*definition*/ }]);
So, is it clear that the dependent modules ['someModuleB', 'someModuleC', ...] of someModuleA, must at some point of time depend on someModuleZ? If yes, this is a surprising fact and I need to investigate how the dependency leads to someModuleZ. How can I do it? Is there a way to see the dependency graph of angular?

Related

angularjs - implement route's resolve feature without routing/ng-view

In a big application, i now need to access some data (json api call) from asynchronously (before, those data were accessed synchronously).
I would like not to have to change components implementation to now handle this async behaviour (too risky).
I thought about $routeProvider's "resolve" feature (with promises) that helps to abstract this async behaviour out from the components/controllers.
Unfortunately i am absolutely not using routing in any way.
Is there an implementation for that? If not, where could i start?
EDIT:
how i was before (jsonData were not loaded synchronously but it was transparent thanks to systemJS features, SystemJS, Which we are throwing in garbage now, hence the question):
https://plnkr.co/edit/BSreVYNAr7sijYwEpb5G?p=preview
How i am now:
https://plnkr.co/edit/WnX0ynOqkZsmEzIxl1SI?p=preview
Watch the console to see an example of the problems that can occur now.
I kind of made it work by going like that, but i'm not completely satisfied with it (watch the config block):
https://plnkr.co/edit/P9Rv6rnboFlaFZ0OARNG?p=preview
$provide.value('$provide', $provide);
$routeProvider.otherwise({
template: '<test></test>',
controller: function ($provide, myJsonData1) {
$provide.value('myJsonData', myJsonData1);
},
resolve: {
myJsonData1: function(){
return getMyJsonData();
}
}
});
Hope this helps :)

Change data between controllers with service

When I use this it works:`
angular.module('app').service('DataService', function() {
return {theme: "amelia"}
});
But when I use this, there is no update? Can you tell me the difference?
angular.module('app').service('DataService', function() {
return {
theme: function() {
return {theme: "amelia"}
}
};
});
Controller
$scope.settings = DataService.theme();
Jade
select.form-control(ng-model="settings.theme", ng-options="theme for theme in themes")
Is it possible to get the second way working? Because I will share more data then one Object!
Thank you!
The first version of the code calls the function once to instantiate the service. After that, because services are singletons in angular the function isn't called again, but rather the return value (a "static" object) is accessed in every controller that uses the service after that.
The second version, each controller you inject the service into calls the theme function, which instantiates a brand new object each time. You have now effectively mitigated the fact that the service is a singleton. This is why data will not be shared with the second set of code.
If you put a break point on the function call in each case and run your code you should see the first version called once while the second version will be called many times.
"Get It Working"...
You can't really make it work with a function call but if you need to share multiple data objects there isn't any reason not to nest them. You could very easily do something like:
angular.module('app').service('DataService', function() {
return {
dataObjects: [
{"type":"theme", "theme":"amelia"},
{"type":"user", "id":123, "name":"ABC"}
]};
});
In the example I added a second object which is a user object to make shared "dataObjects" array. To find a specific object in the "dataObjects" array, you could loop till you find the correct type ("theme", for example). If necessary, you could even nest one level deeper if you needed the objects to be pristine (without the added type attribute).
Hope that helps!
It should be theme: function().... inside your service. Replace "=" with ":".

Angular translate extend existing translations

I am trying to have external modules change my $translateProvider.translation on the main module. see this as a "tranlation plugin" for my app.
it seems like changing translations from the $translate service is not possible.
mymodule.service('MyService', function ($translateProvider) {
var lib = function () {
//EDITED FOR BREVITY
this._registerTranslations = function (ctrl) {
if (!ctrl.i18n) return;
for (var name in ctrl.i18n) {
/////////////////////////////
// THIS IS THE PLACE, OBVIOUSLY PROVIDER IS NOT AVAILABLE!!!!
$translateProvider.translations(name, ctrl.i18n[name]);
//////////////////////////////
}
};
//EDITED FOR BREVITY
};
return new lib();
});
anyone with a bright idea?
So, to answer your question: there's no way to extend existing translations during runtime with $translate service without using asynchronous loading. I wonder why you want to do that anyway, because adding translations in such a way means that they are already there (otherwise you would obviously use asynchronous loading).
Have a look at the Asynchronous loading page. You can create a factory that will load a translation from wherever you want.
I created an Angular constant to hold new translations. If I want to add a new translation, I add it to the constant. Then in my custom loader, I first check the constant to see if the translation exists (either a new one, or an updated one). If so, I load it from the constant. If not, I load it from a .json file (or wherever you load your initial translations from). Use $translate.refresh() to force translations to be reloaded and reevaluated.
Demo here
The demo is pretty simple. You would need to do a little more work if you wanted to just change a subset of the translations, but you get the general idea.
From the AngularJS docs (https://docs.angularjs.org/guide/providers):
You should use the Provider recipe only when you want to expose an API for application-wide configuration that must be made before the application starts. This is usually interesting only for reusable services whose behavior might need to vary slightly between applications.
Providers are to be used with the application's .config function. $translateProvider for configuration, $translate for other services and controllers.

How to create generic controllers in AngularJS?

I am looking for advice with regards to creating a generic controller which I can reuse in my application. As an example I have created the following GIST:
https://gist.github.com/heide-de/10832576
but here is the relevant code snippet:
angular.module('genericTestApp', [])
.factory('Names', function() {
return {
names: []
};
})
.controller('IndexController', function(Names) {
Names.names = [
{firstname:'Sarah', surname:'Schmitt'},
{firstname:'Paul', surname:'Wells'},
{firstname:'Felix', surname:'the cat'}
]
})
.controller('SecondIndexController', function(Names) {
Names.names = [
{firstname:'Octo', surname:'Cat'},
{firstname:'Beth', surname:'Appleby'},
{firstname:'Fred', surname:'Bloggs'}
]
})
.controller('TableController', function($scope, Names) {
$scope.names = Names.names;
})
What feels very wrong to me is that the TableController in this example relies on the fact that the injected Names factory needs to have been configured previously in the IndexController.
The next developer that comes along will just inject Names, and will have no idea that it needs configuring prior to that.
Is there a better way of doing this with Angular?
You're right in your approach – Configuring a factory in a controller is always a bad idea. A controller is supposed to contain view specific logic, and in my opinion should even only be included when that particular view is rendered. (that's how I write my apps anyway)
To configure anything when the application loads up, you need run, that should contain all the initial stuff that your app needs to do in the beginning.
This might be a good read.

What is AngularPublic.js?

If I wanted to add my own custom "provider" to the list (in AngularPublic.js), like so:
...
$provide.provider({
$anchorScroll: $AnchorScrollProvider,
$animate: $AnimateProvider,
$browser: $BrowserProvider,
$cacheFactory: $CacheFactoryProvider,
$controller: $ControllerProvider,
$myCustomController: $MyCustomControllerProvider, <---- I made this
$document: $DocumentProvider,
$exceptionHandler: $ExceptionHandlerProvider,
$filter: $FilterProvider,
$interpolate: $InterpolateProvider,
...etc
If I used an existing provider as boilerplate, would this be a bad idea?
Yes, it is definitely a bad idea. I don't think it is reasonable to modify the source code of Angular as Angular itself is fast growing, things change every second, you may find it is hard to merge your change with newest Angular version one day.
If you only want to add your custom provider into ngModule, you can just to this.
var ngModule = angular.module('ng');
ngModule.provider('myCustom', function() {
// Your code goes here
});
Hope it may help you.

Resources