im new in AngularJS, and have question how i can load controller and other js from structured folders?
For example i have structure:
app/
-common
-users
--userController.js
--userService.js
-orders
-app.js
How i should load controller and service from folder user?
And one more small question: what means squre bracerts?
app.config(['someThing'], function($routeProvider)
You can put the your code where you wants to. If you put them into angular modules, angular will find it. So if you have a service in /app/common/services/foo.js like:
angular.module('app').service('foo', function() { ... });
You can do this in the userController:
angular.module('app').controller('UserController', function($scope, foo) { ... });
Here you see how I injected foo in our controller. Angular Dependency Injection system is smart enough to find your code no matter where you put them.
You can also create different modules than app, you can have:
angular.module('other').service('bar', function() { ... });
And where you define the app module, something like this:
angular.module('app', []);
You just need to add the new module there as a dependency, that is what the [] are for:
angular.module('app', ['other']);
Now you can use the service bar in your controller too :)
On the other hand, the syntax you're talking about is the array notation, something like this:
angular.module('app').controller('FooCtrl', ['$scope', 'foo', function($scope, foo) { ... }]);
This is needed if you mangle your code when you minify it because in the minified code, you could get something like this:
angular.module('app').controller('FooCtrl', ['$scope', 'foo', function(f, g) { ... }]);
As you see, the function parameters are now f and g and Angular doesn't know what to inject based on those names, so it looks on the strings we provided, so it will know that f is $scope and g is foo.
There is no need to use this annotation directly, there are several tools that will do that for you like ngmin.
Cheers.
EDIT: You would need to add every javascript file into a <script> or the won't get loaded and Angular wouldn't find it.
Adding the files one by one is a pain, because you can have 5 or you can have 200.
It is better to concat them and for that I recommend: grunt-concat-sourcemap because it will generate a sourcemap so you will have 1 file with the entire app but in the dev tools you will see them in separate files.
I recommend you to check linemanjs which is a good tool to develop javascript apps and it concat the files for you, source maps, minify, the array notation stuff also...
You will have to link all files in your main HTML page and make sure they are loaded. As pointed out by Dwight above.
An alternative approach would be to use something like Grunt.js to "build" the app. This would include combining all the controller.js files into one – which you then load into your HTML page. This way all the files will be separate for development but will get concocted for deployment.
Related
I am using Angular constant as an configuration file for my services, my problem is that this file can become huge and i am would like to separate the configuration into multiple files. But i don´t want to create a new Angular constant that i need to inject in the services that uses constants.
Is there a way to have only one main constant file that requires all the other files so that there is only one inject into the services? Or is it possibly to create one constant from all js files in a specific folder?
Other solutions to this problem would also be very helpful.
You can use $provide.decorator for that:
$provide.decorator('yourSettings', ['$delegate', function ($delegate) {
$delegate.newProp = 'new value';
return delegate;
}]);
See docs.
I'm starting a new angular project from a scratch and I want to avoid using require.js, browserify or webpack entirely. I'm gonna put all my code into separate files - no monolithic controllers.js or directives.js files...
Few options that are left are:
Use <script> tags and always put new files at the bottom (downside I might mess up order of the files at some point)
Use concatination mechanism, i.e. gulp-concat or grunt-concat
Both of them are ugly - first is maintenance nightmare and the second requires build step and file watcher setup...
The closest thing that I could use is require.js but I'm really disgusted with how the code looks after combining angular with require:
define([], function () {
angular.module('app').controller('BlaBlaController', function () { ... });
})
Since angular is handling all the DI for me require.js is used only for file loading which is kinda sad and makes require.js overkill for such a small task.
What I want to make is extend $inject service so that it would know how to load external files and that's how imagine it should look like:
Create di.config.js file where I specify paths for various "injectables" (much like require.conf.js
Create a simple script loader that would know how to recursively load modules
Now for DI mechanism
--
if (injectableIsLoaded) {
angular.module('app').controller('Controller', function (dep1) {});
} else if (injectableHasPath) {
diLoader.load(injectablePath).then(evalModule);
} else {
throw "No path for module";
}
Does anyone know if that would be possible at all?
What I win from this - I don't need to wrap my angular code in weird require.js calls, don't need a build step, can keep all files separete and load them separatly on demand...
So I'm hoping to do some lazy loading in my angular app -- I want to pull down everything I need to render the landing page, and then subsequently pull down the rest.
The problem is, it seems like I have to define all of my angular module dependencies up-front, when I first run the app...
var myApp = angular.module('myApp', []);
// then, after 1st page render:
var myModule = angular.module('myApp.subModule', []);
How do I now inject myApp.subModule into the dependencies of myApp?
Thanks!
-Daniel
You can use ocLazyLoad for this purpose.
https://github.com/ocombe/ocLazyLoad
The way I understand - you include ocLazyLoad.js in your code.
Then, instead of angular.module('app',['module1','module2']) your code becomes angular.module('app',['oc.lazyLoad']).
Then you inject $ocLazyLoad into your controller and use it like $ocLazyLoad.load({name:'module1', files:['js/controllers/module1.js']},{name:'module2',files:['js/controllers/module2']}).
You can check out the examples on the github page.
I have some simple pages that don't need a specific application module to be provided in the ng-app attribute. But those pages also use some of my custom directives.
As it seems natural I've put all my directives in separate namespace (namely module) i.e. MyApp.Directives.
This is all great when I also provide my application module, because I add MyApp.Directives as dependency and it works.
angular.module("MyApp", ["MyApp.Directives", ...])
But. As said I also have some very simple pages, that don't really require any particular application module because they don't need any custom controllers or anything. They're just driven by ng-... attributes/directives.
Question
I know I can simply add all my custom directives to ng module and they will become accessible to all pages. Those with custom application module and those without. But this beats the purpose of modules, so I'm wondering if there's any other way to tell dependency injector of my additional directives/filters?
I would like to avoid any unneeded code in my application to keep is small and maintainable. (what AngularJS is all about). What I'm looking is actually some sort of hack that I'd be using in my directives' files to make ng module aware of my directives but without adding them to ng module directly... A rather advanced Angular question as it likely involves some internals manipulation.
I've tried manully adding my directives' module to angular.module("ng").requires array but that didn't do the trick.
#1) If you only have one module you can do it with ngApp:
<html ng-app="MyApp.Directives">
#2) If you have multiple modules you can use angular.bootstrap like so:
angular.element(document).ready(function(){
angular.bootstrap(document,['MyApp.Directives','MyApp.Filters']);
});
#3) Or just create a simple module for declaring dependencies:
<html ng-app="myApp">
......
<script>
angular.module('myApp',['MyApp.Directives','MyApp.Filters']);
</script>
If we could only write something like this:
<html ng-app="MyApp.Directives MyApp.Filters">
I made a patch to the source code:
function angularInit(element, bootstrap) {
// some code
if (appElement) {
bootstrap(appElement, module ? module.split(/\s+/) : []); // split by spaces :)
}
}
Here is a demo: http://plnkr.co/edit/kSrY3WYzLG39NJ4UgTRM?p=preview
I have a html file with multiple script tags(close to 20). I've decided to concatenate all the JS files into one and then minify the concatenated file. I am using ant tasks to concatenate and will do so for minification as well. I am aware that I need to provide the option of a non-concatenated/non-minified version for the purposes of debugging(aka in the dev env).
I was wondering how to achieve this. For ex: the file main.html has 20 script tags, one way I figured to do it was use a HTML preprocessor and conditionally include script tags:
#ifdef perf
<script src="main.min.js"></script>
#else
<script src="ctrl.js"></script>
<script src="services.js"></script>
<script src="directives.js"></script>
<script src="model.js"></script>
.
.
.P.S
<script src="file_no_20.js"></script>
#endif
main.min.js is the concatenated and minified file during the build process using ant.
Is there a better way of doing this? What are the downsides of this approach?
Thanks,
Chris.
P.S: Thinking of using the http://fmpp.sourceforge.net/ for html preprocessing, any other suggestions are appreciated.
Chrome supports an awesome feature called "source mapping" that is perfect for this. I'd suggest you read the guide here for more info:
http://www.html5rocks.com/en/tutorials/developertools/sourcemaps/
There are some caveats if you're using AngularJS in regards to minification. From the docs:
Since angular infers the controller's dependencies from the names of arguments to the controller's constructor function, if you were to minify the JavaScript code for PhoneListCtrl controller, all of its function arguments would be minified as well, and the dependency injector would not being able to identify services correctly.
To overcome issues caused by minification, just assign an array with service identifier strings into the $inject property of the controller function, just like the last line in the snippet (commented out) suggests:
PhoneListCtrl.$inject = ['$scope', '$http'];
There is also one more way to specify this dependency list and avoid minification issues — using the bracket notation which wraps the function to be injected into an array of strings (representing the dependency names) followed by the function to be injected:
var PhoneListCtrl = ['$scope', '$http', function($scope, $http) { /* constructor body */ }];
Both of these methods work with any function that can be injected by Angular, so it's up to your project's style guide to decide which one you use.
http://docs.angularjs.org/tutorial/step_05
I suggest using tag libraries, something like http://java.sun.com/j2ee/tutorial/1_3-fcs/doc/JSPTags4.html#67771 to acheieve this. Include your script's like:
<script:include src="myscript1.js" />
<script:include src="myscript2.js" />
<script:include src="myscript3.js" />
..
And the use a page parameter for your system to decide if the scripts has to be concatenated and minified. Something like below:
www.yourapp.com/app?debugMode=true
By default the scripts are concatinated and minified. If you are a developer working on the project just add a page parameter like debugMode=true. When debugMode is true, just render the scripts as it is.
There are many services out there in the market like http://developer.yahoo.com/yui/compressor/ that can be integrated with your project to do this job for you.
Do not compress the scripts everytime you load the page. Do it the first time and cache it so that you dont have to do it everytime. At any point of time to rebuild the latest script file, just add another parameter like ?rebuild=true so that all the latest files and minfied and cached. You could do the same with CSS too.