Setting initial $rootScope defaults don't seem to work - angularjs

I would like to have few global variables that are UI related (i.e. open menu state). I decided to put these in $rootScope so they're always accessible.
This is the code I've written:
(function (angular) {
angular
.module("App", [])
.run(["$rootScope", function ($rootScope) {
angular.extend($rootScope, {
ui: {
menu: false,
...
}
});
}]);
})(angular);
I've deliberately used angular.extend, to make sure that consecutive manipulations to the same object are retained. And I think it's also more clean and safe than adding several properties to any object one by one.
Problem
Upper code doesn't do anything though. When I run my application and check root scope by calling:
$("body").scope().$root.ui
I get undefined until some property within ui gets manipulated by ng-click directives on my application. Only then my ui gets a reference... But it's still not the one I've defined in the run() function but rather angular generated object property that ng-click directive generated as per expression.
What am I doing wrong?

Resolved - module got overwritten
Ia managed to resolve it myself. Code contained in the upper question isn't sufficient to show the actual problem in my application. The problem was the way I was loading module requirements and file ordering.
I'm loading files in this order:
app.js
routing.js
service.something.js
...
filter.something.js
...
So I thought to add module requirements to my app module in subsequent files (make ti actually modularized). This would make it simple to either include or exclude particular files without any runtime errors. It would also allow loading additional files dynamically as application runs.
The problem with my code was that I've overridden my original module in subsequent files. When I added all module requirements into app.js everything everything started working.
Possible workaround
I can see that I'm not the only person that would like this kind of functionality. Lasy module requirements loading is possible as per this Google groups' post.
What it does is it creates a new injector function
instanceInjector.loadNewModules = function (mods) {
forEach(loadModules(mods), function(fn) { instanceInjector.invoke(fn || noop); });
};
that can later be used by individual modules to add themselves as requirement to the main application module by doing this:
$injector.loadNewModules(["Module1", "Module2", ...]);
Although it would be much better (my opinion) if there was an additional function on Module type called requires() so one could do this instead:
angular.module("MainModule").requires(["AdditionalModule", "OtherModule", ...]);
I think that would make it more concise and easy to use and understand.

Related

What's the difference between these two ways of defining a factory

.factory("user", userService);
function userService($q, $http) {
function User (){
//....
}
return User;
}
or
.factory("User", ["$q", "$http", function ($q, $http) {
var User = {
//....
}
return User;
}])
I often see both depending of the situation (or rather depending of the author), but I've been wondering for quite a long time now (since I've begun learning Angular), what makes it different, and if I can use one or the other without changing anything. I usually use the first one and following the logic because I find it easier, and because I'm confused with the second one. I may have made mistakes but that's why Im asking for some help. Thanks !
The second code snippet in your question is the one that I'd recommend you to use for all your angularjs services.
Angular framework offers Dependency Injection (DI) feature out of the box that can be used when defining components such as services, directives, filters, animations or when providing run and config blocks for a module.
If you define the dependencies without using an array of string in your angular app, then you are doing it wrong. This way of registering the dependencies will work well for non minified version of the JavaScript source file.
But if you intend to minify the files for production, which everyone must, then all those (dependency) arguments will be changed to something really random which angular will not be able to map to any registered component. So ultimately, an error will be thrown by the framework.
To avoid this mistake, one can just make sure to always use an array of type string to instruct the dependencies. Read this in more detail. If you are your own then you can maybe keep this tip in mind. However, if working in a team, it is good to configure this using the options below so that everyone in the team follows this. If not, then they will encounter an error.
I'd recommend you to use strict DI mode.
How to enable strict mode?
This mode can be enabled using two options as mentioned below.
Option-1:
<div ng-app="myApp" ng-strict-di>
<!-- your app here -->
</div>
Option-2:
angular.bootstrap(document, ['myApp'], {
strictDi: true
});
Learn why is strict DI mode good for your AngularJS app in my blog post.
The first form will not work with minification. The second form is required when minification is used. The reason for this is that the AngularJS injector uses the function parameter names to resolve the $q and $http dependencies in the first form. If the function parameter names are changed (e.g., by minification), that will fail. The second form relies on the strings "$q" and "$http", which will not be changed by minification.
This is discussed in step 7 of the AngularJS tutorial.

Add dependency to Angular module after it's been created

Do you guys know if it's possible to add a module dependency after it's been created? Something like that:
// init module in file A
angular.module("myApp", []);
// retrieve module in file B and add new dependencies:
mod = angular.module("myApp");
// now I want to add an 'ngResource' dependency to mod
// ???
EDIT: I understand this may seem a weird question. I am working on a component based app organization and want too see if a subcomponent can add dependencies to it parent component module without defining its own module. Something like that:
app/
components/
|__componentA/
|__app.js // initializes component A module
|__subcomponentA/
|__app.js // want to add subcomponentA dependencies to componentA module from here
My alternative is simply declare all subcomponentA dependencies directly on the componentA module, but from organization point of view, I'd prefer to keep these dependencies inside the subcomponentA directory, so if I later decide to remove the subcomponentA from the app, I don't need to remember to remove its dependencies from the componentA module. I want everything that concerns subcomponentA to be grouped inside the subcomponentA directory. My build script will ensure that componentA code is processed before the subcomponetA is, though.
Thank you to everyone who takes a stab at this.
I use the following method for this and working fine for me.
var app = angular.module("myApp", []);
angular.module("myApp").requires.push('ngResource');
I don't think this is possible. However, I'd love to be proven wrong.
From my experience (and according to the Angular documentation) module dependencies can only be declared when initializing a module. It's worth noting that until the application is bootstrapped, the dependencies aren't completely set. It's not possible to add dependencies to a running application as far as I know, unless there's a way to rebootstrap the entire app, which might have unwanted side effects anyway.
Edit: Actually....I've never tried this, but this actually might be a lot simpler than I originally thought. We could try the following:
File A:
window.myApp_dependencies = []; // Add dependencies to the global scope.
angular.module('myApp', dependencies);
File B:
var mod = angular.module("myApp");
window.myApp_dependencies.push('ngRoute');
This isn't really ideal as you are forced to create a variable on the global scope. It would be possible to do it with modules, though. Note that in this case, the dependencies would only be mutable until the app actually started - so, you could split dependencies across files, but you wouldn't be able to change them at runtime.
I don't know if this works. I'm going to try it out tomorrow, though.
Strange question but still what you trying to achieve is something wrong in prospect of angularjs/SPA/dependency injection
Your use case is something like you wants to use this dependency in a particular module or in one page. Thats why you wants to inject it at one position not the other.
But, doing this would make two different scopes for your application becuase using same name of module if you reinitiallized that module that would be different that the other one which is already declared
say: file A
angular.module("myApp", []);
This is defined and in file B
mod = angular.module("myApp", ['ngResource']);
so this would cause to have two different app with same name in one application and that two app with same name in different files
so its something like to have two different angular module inside on application.
Second option: let have the same module across the application and inject in at one point and in any controller you wants to use this inject that as a argument in that controller.
Hope this help!

Why requireJs wouldn't load defined dependency modules?

I am having problem while using Require.js to load dependencies for my module. Basically I have following module in which I define extension of Backbone Model.
define(["models/services/ProjectServices"],
function (ProjectServices) {
var SomeModel = Backbone.Model.extend({
sample: function () {
var servicesFromDependency = ProjectServices; //undefined
var projectServices = window.require.s.contexts._.defined["models/services/ProjectServices"]; //defined and Ok
}
});
return SomeModel;
}
);
In this module I want to use already defined ProjectServices module. In order to do that I add it as a dependency. The thing is that within defined sample function ProjectServices is showing as undefined. But if I look directly into require defined modules it is showing there correctly and I can use it (although I do not want as I don't like to hack it this way). To add more context, I am also using this ProjectServices dependency on other module and there it is loaded properly through define function.
Any suggestions on why module would not be loaded?
Try this inside a module:
var ProjectServices = require('models/services/ProjectServices');
I think in many situations, there is no need for window global assignment and I try to avoid while using requirjs.
The only thing I can come up with is a possible circular reference, meaning that two modules require each other (which should not be the case).
As you say that the require works well in other modules, it should not be due to a missing return statement in the required module, or a wrong path. (You might check this anyway).

How can I have Angular-Translate preload my translation before I can use it inside my controller?

I am trying out Angular Translate and I need to use the translations inside my controller, but the controller runs the code before my translation is even loaded yet..here is my code:
var myApp = angular.module('myApp', ['pascalprecht.translate']);
angular.module('myApp').config(function ($translateProvider) {
$translateProvider.useStaticFilesLoader({
prefix: 'locales/validation-',
suffix: '.json'
});
// load 'en' table on startup
$translateProvider.preferredLanguage('en');
});
angular.module('myApp').controller('Ctrl', ['$scope', '$translate', function ($scope, $translate) {
console.debug($translate('INVALID_INTEGER'));
$scope.switchLanguage = function (key) {
$translate.uses(key);
console.debug($translate('INVALID_INTEGER'));
};
}]);
when calling the console.debug($translate('INVALID_INTEGER')); it always shows INVALID_INTEGER instead of the real translation, so I conclude that my translation is not yet loaded. I'm new to both Angular and the Angular-Translate, so I'm not sure of what to do next? Do I have to a promise, I would prefer a built-in function within angular-translate instead. I want simple locale languages which are coming from external and separate json files for each language.
EDIT
The real problem I have is that all my translations are used directly inside the controller and not in the view. It seems that angular-translate works good for whatever is displayed in the view but in the controller it doesn't refresh the code inside the controller itself.
Please note that I now have a working Beta Project on Github which is where I use the translation... Angular-Validation (form validation made easy). My project is an Angular directive and uses the locales languages, if you run the project and choose a language before loading the template then it works, but after that calling the $scope.switchLanguage() won't have any effect on the controller, though any translation on the view would work.
Ok so from the github project above it is now apparent that the translation does not work for the following reasons:
Link code from ngxValidation directive is run only once on page load and it translates the strings to whatever the current language is set to. The code never runs again unless you fully refresh the page so even if you change the language with $translate.uses() the directive has the strings already translated and cached and does not even try to translate them again.
When you click the Load Testing Form multiple times nothing happens - the view is not reloaded (and the directive is not recreated, doh!). And that is not really surprising since it's the same view! Why would angular reload something that is already loaded - it cannot know you changed the translation and you actually do want to reload in this particular, special case.
So you would have a couple solutions the simplest of which I think is not to cache the translated strings, translate only just in time - inside validator(). That should always work. If you want to be smart with caching and what not you have to find a way to ensure the cache is always valid :) And as we all know there are only two hard problems in computer science one is cache invalidation and the other one is [insert_whatever_youre_working_on_right_now_here].
In detail:
In the directive you're doing:
messages[i] = $translate('INVALID_URL');
Replace all assignments like this with just:
messages[i] = 'INVALID_URL';
And then inside the validator function do:
if(!isValid) {
isFieldValid = false;
message += $translate(messages[j]);
}

AngularJS - How to route to a controller in different module

I have a question related to modules and routing in angularjs. The requirements are to define all routing configs in one module - lets call this ModuleRtr.
Once the route is triggered, it should call a controller (called TestCtr for example). This controller is defined in another module - let's call it ModuleCtrl.
If I try to do that, I got an exception like:
"Argument TestCtr is not a function, got undefined"
. The reason is that when angular broadcast $routeChangeSuccess event, the listener tries to access the controller (TestCtr) as part of the current module - ModuleRtr. Because it's not there, it throws an error.
If I simply create TestCtr controller in ModuleRtr (the same that has the route in it), then everything works. But I don't want that, I want to have my TestCtr in different module. I also don't want to have route define in ModuleCtrl module.
So, in more straightforward way, my question is: Is it possible a route defined in one module (ModuleRtr) to call a controller defined in another module (ModuleCtrl)?
Something that I forgot to mention...I don't want to bind these 2 modules by any means. That of course includes listing a dependency during module's creation. I have already tried dynamic loading of TestCtr - it didn't solve the problem.
The scenario is: You have 2 angularjs applications (modules). They don't know anything about each other...except one thing - somewhere in a shared/common location, there is an object which follows a particular structure (like a contract). The first module writes data there. Then it runs a common function from the second module (this is actually the question I am asking - how?). Then the second module knows already where to go (it's a contract) what to read and what to do. One way I can do this is to try dynamically generates the string that represents a module dependency when the other module is created. I am not sure if that is a good solution...
Many thanks!
You can use a single module with submodules for each functionality, such as:
angular.module('myApp.home',[]);
angular.module('myApp.routing',[]);
...modules here...
angular.module('myApp', [
'myApp.home',
'myApp.routing'
]);
So you can send a method from myApp.home calling a intermediate method from myApp and this one calling the myApp.routing method.
At least, this is how I see it.

Resources