Is it ok to write multiple Angular component in a single file? - angularjs

I am about to write a common Angular module which can be used as a plug and play module in my application.
What I want
I want to put the module definition and all its factory, directive, constants in a single js file, example:
angular.module('commonModule', [])
.factory(...)
.directive(...)
.constant(...)
Why because
Whenever a developer wants to use my module he/she just need to call a single js file and just need to inject my module in their module.
What is my problem
I have read the John papa's Angular 1 good practice style guide, he told that it is good to define a single component in a file, but here I am doing the opposite so what should I do?

Separate. Just so and not otherwise.
Keeping components separately is one of the best practices in programming world. No matter if you have few lines of code at the moment, later code will increase. Doing so from the beginning you cultivate a literate programming discipline. Bad practice to come up with a bunch of exceptions in the rules, like "if I have few lines of code I can write all components of my app in one single file". It makes rules and possibility to follow them more complicated.
Whenever a developer wants to use my module he/she just need to call a
single js file and just need to inject my module in their module.
Correct. For consumer it is very convenient to include just one single file in his/her project. But it is bad for code maintenance. So just use any JS bundler to concatenate all dependencies in one result file so consumers can just inject it in their module.

Related

Organizing AngularJS applications

I feel like there is relatively little documentation on the "best practices" of how one should go about organizing AngularJS code. For example, in many of my web pages, i.e.
index.php
profile.php
editprofile.php
There are often many factories and methods that I need repeated. For example, profile.php,, editprofile.php, and index.php all need the factory userDropdown (to get the top navbar dropdown menu). However, some of them need "modified versions of factories". For example:
index.php needs a way to get all the users and their information
profile.php needs a way to get some users information
editProfile.php needs a way to get only one user information
What I mean is that (and the above was a poor example), is that often many .js files needs some modified "child" of a "parent" factory. I find it hard to scale my application because profile.php, index.php, and editProfile.php all refer to their own factories and methods, not a base file. Changes, improvements, errors, found in one factory and is corrected, will not propagate into other files (which I find very frustrating). I also don't want to write /copy/paste services and factories over and over again. Other issue I've had is that:
X.js file need some providers that Y.js file doesn't. However, both needs providers A and B, but X needs C and Y needs D. Is it bad for me to use the same "factory" and providers" for both of them (i.e. inject A, B, C, and D into both of them?) That's the problem I see with having a base factory of a factory to serve a lot of .js files. How much space or inefficiency is it to define providers or injectable services that you don't use?
How do I accomplish some scalable angularJS code to do this, or how do you guys go about organizing your angular code? And also, what about repeating HTML templates (i.e. repeating HTML code that needs to be used in almost every page? I've heard of some service called $templateCache but couldn't figure out how to use it.)
https://github.com/johnpapa/angular-styleguide This also has an example app but seriously read through his guidelines they seem to be exactly what you are looking for and have been a great resource for me as I've been learning to build bigger angular apps.

Why do I need to inject the controllers I want in my app?

I am reading the source code for an app which reads as follows:
angular.module('graffio', [
'graffio.signupController',
'graffio.loginController',
'graffio.mainController',
'ui.router'
])
I have quite a few questions! So much confusion...
How is code loading these controllers which are defined later in the
code?
Why do I even need to state which controllers I want in my
app? Why can't I just have all the ones I declare?
Why does the angular documentation use the word 'injectable' so much? Isn't
injectable just the same as require?
With Angular, you can group as much or as little code into a module as you like. And you can compose modules together, like the author of the app you are looking at has done. The final module will have all of the services, config blocks, routes, controllers, directives, filters and so on that are in all of the modules it depends on as well as its own module.
This author has chosen to put each controller into its own module. Which is why the main module needs to depend on each of those modules. In my opinion, this seems like overkill, but it is what has been done, and all you need to do is understand it, not agree with it.
In answer to your other questions:
How is code loading these controllers which are defined later in the code?
When your code first runs, all the modules will be declared, and populated with directives, routes, controllers, services and so on. Nothing gets used yet. So long as when the code you have above is run, the other modules have already been declared then everything is fine (this may be done by a build process such as a Grunt task).
Then, when the document.ready event occurs, Angular looks through your HTML for an ng-app directive that says which module to load as your application. It then does what it calls the "bootstrap" process for that module.
Why do I even need to state which controllers I want in my app? Why can't I just have all the ones I declare?
Because this author has put each controller in their own module. If you put all the controllers you want into one module, then you don't need to declare them like that.
Why does the angular documentation use the word 'injectable' so much? Isn't injectable just the same as require?
Sort of. It is similar in that you are asking for a dependency by name and then using it.
It is different in that with require you can't typically modify what value is retrieved for a given dependency at runtime. With dependency injection, you can swap or modify dependencies at run time if you so choose (before your app starts properly and the dependencies are injected into the code using them).
This is perfect for testing, so that you can use a mock (fake) version of a dependency for testing purposes, instead of using the normal version. Think of a service that makes a call to get some data from the server and returns a promise. You can just create a mock version of that service that doesn't call to the server, just returns some test data immediately. This makes your unit tests fast, and means you don't need to be running your web server for them to work.

Angular seed with services and directives

I am using angular seed project
https://github.com/angular/angular-seed
where should I put the services and directives ?
This is really totally up to you but there are some good recommendations on project structure here: https://docs.google.com/document/d/1XXMvReO8-Awi1EZXAXS4PzDzdNvV6pGcuaF4Q9821Es/pub
Typically my structure looks something like
app\scripts\user.js
app\scripts\todo.js
Where User.js would have a service and possibly multiple controllers in it... if the file gets too large then I break it up into parts.
The problem with grouping all services together and all controllers is that the services and controllers typically have a relationship (functionally). When you want to re-use the service/controller you are typically going to use them together, when editing one you usually need a reference to the other. This makes it easiest to find things and not have 1000 js files to include and manage in the dependencies and script inclusions.
Also when it comes time and you want to make a bower component out of one of the sections it's easier to see which parts need to be pulled out.
You can make a folder for each under app, so your project tree will look like this:
app/directives
app/services

pitfalls of IIFEs with AngularJS

I have an application made with angularJS, whole application is composed of IIFEs(Immediately Invoked Function Expression). Every module, directive, controller is itself an IIFE and they are around 100s.
I want to know what is the performance pitfall when an app has so many IIFEs.
It is OK to use IIFEs with AngularJS?
How good is using libs like browserify and requirejs with AngularJS for managing the dependencies?
Can you please throw some light on this?
The question you need to ask first is whether you've got some internal parts within the IIFE that you don't want to expose to the global scope.
The whole point of creating a closure in this manner is to mimic encapsulation and avoid polluting the global scope.
The performance pitfall is not so easy to measure; I think the performance issue is negligible when you create the IIFE (don't forget you're just creating a function). One performance issue that I might think of is that when you reference a function variable form an inner function, you need to travel through the scope chain and get it from the closure object.
I would recommend you to look at patterns like module pattern, revealing module pattern etc. I personally use the revealing module pattern.
Browserify and requireJS are two libraries that implement two different specs; the commonJS and AMD respectively. These two specifications try to accommodate a functionality that is not supported by ES3 or ES5; That is a way of defining module and then loading them in specified locations.
If you want to define modules and load them synchronously in a similar manner to hose nodeJS works, you can use Browserify. In addition, Browserify allows you to use the same modules both for client-side and server-side (as long as you're using nodeJS).
On the other hand if you want to asynchronously load your modules you can go with AMD and requireJS, but you won't be able to reuse them on the back-end.
Finally, bare in mind that everything you've mentioned is not directly connected to angularJS; those are some good JavaScript practises to overcome some issues of the language itself. It can be well used whether you're working with angular or not.
I would recommend that you use either browserify or requireJS; it will benefit you in the long run. Just imagine having 100 JS files; you would need to out the manually into your html in the correct order based on the dependency graph. You can easily come across issues like race conditions where one file should have been inserted before another one.
As for the performance overhead of IIFEs, you shouldn't have any serious issues.
As another answer said, IIFEs are a good general practice, independent of AngularJS.
If you're concerned about the performance of IIFEs, go ahead and check out these performance tests on JSPerf (or write your own):
http://jsperf.com/iife-antecedents-in-js
http://jsperf.com/immediate-anonymous-function-invocation
While some ways of IIFE creation are clearly much slower than others, I wouldn't worry about the performance of IIFEs unless you're in a large loop.

What is angular-loader.js for?

I saw a similar question on the Google groups and also here on Stackoverflow. Both times the question was not answered. The code in this file doesn't make it very clear about what exactly it does and how it is used. Also it's not clear from the Angular documentation.
Can someone explain how this is used. Also can this be used along with Require.js?
Angular loader allows your angular scripts to be loaded in any order.
As angular-seed project shows us, Angular loader does not have any specific api, you just put it at the top of your index file (so that it's executed first) and then proceed to load your application files anyway you prefer.
But, the most important thing for your use case is that you don't really need angular loader at all. RequireJS also allows your files to be loaded in any order, but it also provides you with many other features that angular loader just isn't made for.
So, yes, you may use it with RequireJS, but you don't need to, because it becomes redundant.
Angular modules solve the problem of removing global state from the application and provide a way of configuring the injector. As opposed to AMD or require.js modules, Angular modules don't try to solve the problem of script load ordering or lazy script fetching. These goals are orthogonal and both module systems can live side by side and fulfil their goals.
http://docs.angularjs.org/tutorial/step_07#anoteaboutdiinjectorandproviders
It allows for you asynchronously load files when bootstrapping your angular application. A good example is the angular-seed project that has an index-async.html file that does this.
index-async.html
This is useful for using other libraries that load in modules asynchronously.
See angular-async-loader:
https://github.com/subchen/angular-async-loader/
To async load following components:
List item
controller
services
filter
directive
value
constant
provider
decorator

Resources