I am working through an eBook to learn the whole MEAN stack and came across an odd problem when working with angular.
Specifically, I was adding angular-route to my application to render a template. At first I could not get it to work and went over the code several times looking for any error I might have made. In the end, I had typed the order of two dependencies for the main application module differently than the book had shown.
This didn't work
var mainApplicationModule = angular.module(mainApplicationModuleName, ['example', 'ngRoute']);
This worked
var mainApplicationModule = angular.module(mainApplicationModuleName, ['ngRoute', 'example']);
So I don't have a problem exactly, but I was wondering if anyone could explain why this works this way? I have not been able to find anything about the order of dependency declaration mattering. I can post more of my code if it would be helpful.
This comes from Brad Dayley's book on the Subject.
The order matters in that the the list of modules(dependencies) to be injected has to be in the the order of "required". So if the example module requires the ngRoute then ngRoute has to be before example.
The angular.module() method uses following syntax:
angular.module(name, [requires],[configFn])
The name parameter is the name under which the module is registered in the injector service. The requires parameter is an array of names of modules that are added to the injector service for this module to use.
This explanation does beg for answer about possibility of circular module references in more complicated case. Here is some light on that by David M. Karr SO Answer Link.
Related
I have a project in Grails 2.4.4 in which I also use AngularJS.
I've decided to use the Asset Pipeline Plugin along with AngularJs Annotate Asset-Pipeline. The first one for processing, minifying, etc the static assets(js,css, etc) and the second one for getting the myFunc.$inject = [...] "injection" in every function that requires it due to the injection dependency in which AngularJS relies on.
According to the doc of AngularJs Annotate Asset-Pipeline it should put the myFunc.$inject=[] when the war is going to be generated on my js files when required, but the true is different: it is not working at all (I do not see any $inject in the minified file and the app breaks due to the dependency injection widely discussed on SO (examples: Angularjs error Unknown provider and AngularJS Error: $injector:unpr Unknown Provider)
Below is the relevant code (if any other is required, please, let me know)
BuildConfig.groovy
compile "org.grails.plugins:asset-pipeline:1.9.9"
compile "org.grails.plugins:angular-annotate-asset-pipeline:2.4.1"
AngularJS controller (this is just an example)
angular
.module('app', [])
.controller('myCtrl', myCtrl);
/*#ngInject*/ // << --- did not work!
function myCtrl ($scope){
//I also used the "ngIngect"; alternative here and it did not work either!
$scope.myVar = "sample text";
}
Short answer:
Change the version of the dependency
from this:
compile "org.grails.plugins:angular-annotate-asset-pipeline:2.4.1"
to this:
compile "org.grails.plugins:angular-annotate-asset-pipeline:1.1.3"
Long story
After digging into the AngularJs Annotate Asset-Pipeline, and with the help provided by a friend I came to the conclusion that the author of this plugin just removed the logic inside it.
This means that right now (May 25th, 20017) with the current version of this plugin (2.4.1) nobody will be able to use it as it was intended to be used.
So, if anybody is experiencing this same issue should use instead version 1.1.3 which is the latest I was able to use successfully.
I have an application built on generator-angular-fullstack and it does a great job of allowing all my angular components to live in their own separate files.
I was just running all my code through JSLint and it asked to remove 'use strict'; from my index.module.js file as it worked out that this was the global or starting file for my entire application.
I was reviewing the JSLint warning here use-the-function-form-of-use-strict
This got me thinking, how did JSLint know that index.module.js was the starting code block.
Which then got me thinking, does it matter what order angular startup methods are called.
Can these methods be run in any order you like, or is there an expected sequential order for these calls?
angular.module('appName')
angular.module('appName').run(function() { });
angular.module('appName').config(function() { });
angular.module('appName').service(function() { });
angular.module('appName').constant('blah', 'blah');
TL;DR - no it's not.
The way angular is doing it - is when the page renders and scripts are loaded it register all the components(services\config\constants..) but do not execute them.
When the registration completes angular is starting to execute the application, providers --> config --> run and so on..
If your interested in some more detailed explanation on the way angular works under the hood you can check out this awesome article.
*forgot to mention that you must define your module first.
Why doesn't angularJS directly throw the specific error location(i.e., in which file there is an error or fault), rather than giving a link their website link which gives some generic explanation? It is making debugging a very difficult task!
Whenever there is an error, i can't debug the app easily because I have to go through the complete application and search every line, if it is valid line or not?
You can use console.log() in the module where you are debugging, might make it easier.
Because AngularJS is not being compiled so it can not know its exact location where actual error occurred.
For example Suppose you are defining a module Say 'XYZ' as follows
angular.module('XYZ', []);
Then you are using this as
var app = angular.module('XYZ');
But if you did mistake and do as follows
var app = angular.module('XYZ', []);
AngularJS will think you want to override your previous module. Then angular can not found dependency for the old component which were defined earlier on 'XYZ' module. So angular will tell those component are not defined.
One more point mostly those error happens on angular digest cycle which is not in our code.
Another Example
$scope.$watch('foo', function() {
$scope.foo = $scope.foo + 1;
});
The above code will be executed infinite time because foo is being watch if it is changed, and insde of watch it is again being changed.
But after 10 iteration angular will stop execution and show a link. Because angular does know it is a digest cycle repetition happening. But do not know which part of the code is responsible for that.
Note: Yes, I found angularJS debugging is really little hard, But If
we see the error carefully and try to find out what latest changes we
did last time, then we can found exact problem.
I've developed my first spa application in Angular js but I've done it on localhost.
Now it's time to test it online. I'm sure that everything works localy but simply I can't make it work online.
It seems to me like controllers are not being loaded although they are linked well.
Routing works because html templates change but THERE ARE NO CONTROLLERS ???.
Here is sample output from console :
First,for every controller in my app I get this (total 5 times) :
Uncaught SyntaxError: Unexpected token <
And after that I get this for controller that is being used right now:
Error: [ng:areq] http://errors.angularjs.org/1.3.5/ng/areq?p0=homeCtrl&p1=not%20aNaNunction%2C%20got%20undefined
at Error (native)
at https://code.angularjs.org/1.3.5/angular.min.js:6:416
For every single controller I get the same error.
I followed rule to inject dependacys (found that on stackowerflow but it doesn't help at all) so my every controller looks like this:
myApp.controller('nearCtrl',
['$scope', 'geolocation', 'nearApartments', 'uiGmapGoogleMapApi',
function ($scope, geolocation, nearApartments, uiGmapGoogleMapApi) {...}])
Does anyone have an idea what could I do to fix this ?
Ok I found the solution,as usual it was trivial and now I feel like I shot myself in leg.
The thing was that I was very stupid and didn't follow good
practices as NAMING CONVENTION from the BEGINING of the
project !
In my index.html file there was an issue because few controllers were named by lowercase like myController.js and their real name on server was different like MyController.js so there's a problem.
I worked with git,merged branches and stuff and probabbly git messed up something with names(explains how it worked on localhost I guess) but that wouldn't happen if I had followed rules from the start.
To every wannabe Angular.js developer like me there are some great design guides and good practices described on link below.
Use them !
https://github.com/mgechev/angularjs-style-guide
Tnx everyone who tried to help me, Angular has really great community.
The trouble is with your server routing. You're serving your whole app instead of the individual JS files. First thing you should do is make sure 188.226.150.65/app/components/about/aboutController.js serves correctly the JS for aboutController.js.
Looking at each of your component folders, it seems all your controller.js files all have the same error:
Error in exception handler: The stream or file "/var/www/html/zimmer-
production/app/storage/logs/laravel.log" could not be opened: failed to open stream:
Permission denied in /var/www/html/zimmer-production/bootstrap/compiled.php:9016
The only controllers that seem to actually have any Javascript are the signup controllers and the apartmentControler. I'd check the permissions in your production environment, as that seems to be the problem.
In my angular code, to avoid code duplication, I inject a same factory into multiple services. At first, when I did this it started throwing errors Error: [$injector:unpr] Unknown provider
After some debugging, it became obvious that this was a load order issue. To get around it, in my build.config.js file, I changed module.exports.app_files.js so that factories were loaded before services.
My build.config.js file now has this in it
module.exports = {
build_dir: 'build'
compile_dir: 'bin',
app_files: {
modules: [
'src/**/*.js',
'!src/**/*.spec.js',
'!src/**/*-service.js',
'!src/**/*-controller.js',
'!src/**/*-config.js',
'!src/**/*-directive.js',
'!src/**/*-factory.js',
'!src/**/*-filter.js',
'!src/**/*-run.js'
],
js: [
'src/**/*-factory.js',
'src/**/*-service.js',
'src/**/*-controller.js',
'src/**/*-config.js',
'src/**/*-directive.js',
'src/**/*-filter.js',
'src/**/*-run.js',
'!src/**/*.spec.js'
],
...
The source code of the angular application is here and the modification is here
It would seem that I'm forced to have a hierarchy and that I could never have a factory-named file that has a dependence on a service named file. Whether one should or shouldn't is not the debate here; I'm more concerned about the hierarchy.
I would like to know if there is an alternative way around this?
[edit] : I think I have found the source of the problem (fingers crossed that it stays fixed). I was developing using grunt watch. However, when I stopped the process and simply ran grunt, everything is happy again. Thanks to the people below for asking questions and ascertaining that this was not normal behaviour!